Merge remote-tracking branch 'cros/upstream' into merge-upstream

26ec43c sar: add support for Transmission Status
e9b5af3 sar: add missing Since tags in enums
9cb417b mbimcli,sar: reword command help items
d3ed5f9 mbimcli,sar: set operations receive strings, not flags
701de6d libmbim-glib,sar: renamed Transmission Status related enums
6a0fd38 docs: add missing doc for Transmission Status related enums
97028c6 mbim-codegen: avoid struct plurals in method documentation
55aca95 doc: skip running gtkdoc-rebase on local install step
fdd51e5 docs: add 'online-location' reference
e2b3546 core: update copyright years to 2021
2731324 build: add new RELEASING doc explaining how releases are made
76c8be6 README: add CoC info

BUG=None
TEST=deploy MM and libmbim to jinlon and test internet connection

Change-Id: I1d91abbda739c5db0ae32690040095965cafa2a2
diff --git a/README b/README
index 6d93228..7a862b4 100644
--- a/README
+++ b/README
@@ -4,3 +4,11 @@
 License:
   The libmbim-glib library is released under the LGPLv2+ license.
   The mbimcli tool is released under the GPLv2+ license.
+
+Code of Conduct.
+Please note that this project is released with a Contributor Code of Conduct.
+By participating in this project you agree to abide by its terms, which you can
+find in the following link:
+  https://www.freedesktop.org/wiki/CodeOfConduct
+CoC issues may be raised to the project maintainers at the following address:
+  libmbim-devel-owner@lists.freedesktop.org
diff --git a/RELEASING b/RELEASING
new file mode 100644
index 0000000..624e823
--- /dev/null
+++ b/RELEASING
@@ -0,0 +1,35 @@
+
+The libmbim releases are generated using the GNU autotools.
+
+1) Configure and build the whole project, making sure gtk-doc is enabled:
+
+    $ NOCONFIGURE=1 ./autogen.sh
+    $ ./configure --enable-gtk-doc
+    $ make -j8
+
+2) Run distcheck so that the source distribution tarball is generated, and the
+   project test suite is run on it:
+
+    $ make distcheck
+
+3) Compute checksum of the tarball so that it can be referenced in the release
+   email:
+
+    $ sha256sum libmbim-${VERSION}.tar.xz
+
+4) Sign release tarball, and verify it (*):
+
+    $ gpg --detach-sign --armor libmbim-${VERSION}.tar.xz
+    $ gpg --verify libmbim-${VERSION}.tar.xz.asc libmbim-${VERSION}.tar.xz
+
+5) Upload source tarball (.tar.xz) and signature (.tar.xz.asc) to
+   freedesktop.org
+
+TODO: manpages and gtk-doc references
+
+-------------------------------------------------------------------------------
+
+*) Verifying the release signature requires the public key of the person who
+   signed it, e.g.:
+
+    $ curl https://www.freedesktop.org/software/libmbim/0x3CAD53398973FFFA.asc | gpg --import
diff --git a/build-aux/mbim-codegen/Message.py b/build-aux/mbim-codegen/Message.py
index e6cb6bf..af7407b 100644
--- a/build-aux/mbim-codegen/Message.py
+++ b/build-aux/mbim-codegen/Message.py
@@ -246,21 +246,21 @@
             elif field['format'] == 'struct':
                 inner_template = (' * @${field}: (in): the \'${name}\' field, given as a #${struct}.\n')
             elif field['format'] == 'struct-array':
-                inner_template = (' * @${field}: (in)(array zero-terminated=1)(element-type ${struct}): the \'${name}\' field, given as an array of #${struct}s.\n')
+                inner_template = (' * @${field}: (in)(array zero-terminated=1)(element-type ${struct}): the \'${name}\' field, given as an array of #${struct} items.\n')
             elif field['format'] == 'ref-struct-array':
-                inner_template = (' * @${field}: (in): the \'${name}\' field, given as an array of #${struct}s.\n')
+                inner_template = (' * @${field}: (in): the \'${name}\' field, given as an array of #${struct} items.\n')
             elif field['format'] == 'ipv4':
                 inner_template = (' * @${field}: (in): the \'${name}\' field, given as a #MbimIPv4.\n')
             elif field['format'] == 'ref-ipv4':
                 inner_template = (' * @${field}: (in): the \'${name}\' field, given as a #MbimIPv4.\n')
             elif field['format'] == 'ipv4-array':
-                inner_template = (' * @${field}: (in)(array zero-terminated=1)(element-type MbimIPv4): the \'${name}\' field, given as an array of #MbimIPv4.\n')
+                inner_template = (' * @${field}: (in)(array zero-terminated=1)(element-type MbimIPv4): the \'${name}\' field, given as an array of #MbimIPv4 items.\n')
             elif field['format'] == 'ipv6':
                 inner_template = (' * @${field}: (in): the \'${name}\' field, given as a #MbimIPv6.\n')
             elif field['format'] == 'ref-ipv6':
                 inner_template = (' * @${field}: (in): the \'${name}\' field, given as a #MbimIPv6.\n')
             elif field['format'] == 'ipv6-array':
-                inner_template = (' * @${field}: (in)(array zero-terminated=1)(element-type MbimIPv6): the \'${name}\' field, given as an array of #MbimIPv6.\n')
+                inner_template = (' * @${field}: (in)(array zero-terminated=1)(element-type MbimIPv6): the \'${name}\' field, given as an array of #MbimIPv6 items.\n')
 
             template += (string.Template(inner_template).substitute(translations))
 
@@ -497,21 +497,21 @@
             elif field['format'] == 'struct':
                 inner_template = (' * @out_${field}: (out)(optional)(transfer full): return location for a newly allocated #${struct}, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_free().\n')
             elif field['format'] == 'struct-array':
-                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type ${struct}): return location for a newly allocated array of #${struct}s, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_array_free().\n')
+                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type ${struct}): return location for a newly allocated array of #${struct} items, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_array_free().\n')
             elif field['format'] == 'ref-struct-array':
-                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type ${struct}): return location for a newly allocated array of #${struct}s, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_array_free().\n')
+                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type ${struct}): return location for a newly allocated array of #${struct} items, or %NULL if the \'${name}\' field is not needed. Free the returned value with ${struct_underscore}_array_free().\n')
             elif field['format'] == 'ipv4':
                 inner_template = (' * @out_${field}: (out)(optional)(transfer none): return location for a #MbimIPv4, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n')
             elif field['format'] == 'ref-ipv4':
                 inner_template = (' * @out_${field}: (out)(optional)(transfer none): return location for a #MbimIPv4, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n')
             elif field['format'] == 'ipv4-array':
-                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type MbimIPv4): return location for a newly allocated array of #MbimIPv4s, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n')
+                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type MbimIPv4): return location for a newly allocated array of #MbimIPv4 items, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n')
             elif field['format'] == 'ipv6':
                 inner_template = (' * @out_${field}: (out)(optional)(transfer none): return location for a #MbimIPv6, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n')
             elif field['format'] == 'ref-ipv6':
                 inner_template = (' * @out_${field}: (out)(optional)(transfer none): return location for a #MbimIPv6, or %NULL if the \'${name}\' field is not needed. Do not free the returned value, it is owned by @message.\n')
             elif field['format'] == 'ipv6-array':
-                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type MbimIPv6): return location for a newly allocated array of #MbimIPv6s, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n')
+                inner_template = (' * @out_${field}: (out)(optional)(transfer full)(array zero-terminated=1)(element-type MbimIPv6): return location for a newly allocated array of #MbimIPv6 items, or %NULL if the \'${name}\' field is not needed. Free the returned value with g_free().\n')
 
             template += (string.Template(inner_template).substitute(translations))
 
diff --git a/data/mbim-service-ms-sar.json b/data/mbim-service-ms-sar.json
index c3e3557..402490d 100644
--- a/data/mbim-service-ms-sar.json
+++ b/data/mbim-service-ms-sar.json
@@ -44,6 +44,34 @@
                        { "name"             : "ConfigStates",
                          "format"           : "ref-struct-array" ,
                          "struct-type"      : "MbimSarConfigState",
-                         "array-size-field" : "ConfigStatesCount" } ] }
+                         "array-size-field" : "ConfigStatesCount" } ] },
 
+  // *********************************************************************************
+
+  { "name"         : "Transmission status",
+    "service"      : "MS SAR",
+    "type"         : "Command",
+    "since"        : "1.26",
+    "set"          : [ { "name"             : "ChannelNotification",
+                         "format"           : "guint32" ,
+                         "public-format"    : "MbimTransmissionNotificationStatus"},
+                       { "name"             : "HysteresisTimer",
+                         "format"           : "guint32" } ],
+    "query"        : [],
+    "response"     : [ { "name"             : "ChannelNotification",
+                         "format"           : "guint32" ,
+                         "public-format"    : "MbimTransmissionNotificationStatus"},
+                       { "name"             : "TransmissionStatus",
+                         "format"           : "guint32" ,
+                         "public-format"    : "MbimTransmissionState"},
+                       { "name"             : "HysteresisTimer",
+                         "format"           : "guint32" } ],
+    "notification" : [ { "name"             : "ChannelNotification",
+                         "format"           : "guint32" ,
+                         "public-format"    : "MbimTransmissionNotificationStatus"},
+                       { "name"             : "TransmissionStatus",
+                         "format"           : "guint32" ,
+                         "public-format"    : "MbimTransmissionState"},
+                       { "name"             : "HysteresisTimer",
+                         "format"           : "guint32" } ] }
 ]
diff --git a/docs/reference/libmbim-glib/libmbim-glib-common.sections b/docs/reference/libmbim-glib/libmbim-glib-common.sections
index 19b6ac2..454665d 100644
--- a/docs/reference/libmbim-glib/libmbim-glib-common.sections
+++ b/docs/reference/libmbim-glib/libmbim-glib-common.sections
@@ -329,6 +329,8 @@
 MbimSarBackoffState
 MbimSarControlMode
 MbimSarWifiHardwareState
+MbimTransmissionNotificationStatus
+MbimTransmissionState
 <SUBSECTION Methods>
 mbim_device_type_get_string
 mbim_cellular_class_build_string_from_mask
@@ -388,6 +390,8 @@
 mbim_sar_backoff_state_get_string
 mbim_sar_control_mode_get_string
 mbim_sar_wifi_hardware_state_get_string
+mbim_transmission_notification_status_get_string
+mbim_transmission_state_get_string
 <SUBSECTION Private>
 mbim_device_type_build_string_from_mask
 mbim_cellular_class_get_string
@@ -449,6 +453,8 @@
 mbim_sar_backoff_state_build_string_from_mask
 mbim_sar_control_mode_build_string_from_mask
 mbim_sar_wifi_hardware_state_build_string_from_mask
+mbim_transmission_notification_status_build_string_from_mask
+mbim_transmission_state_build_string_from_mask
 <SUBSECTION Standard>
 MBIM_TYPE_ACTIVATION_COMMAND
 MBIM_TYPE_ACTIVATION_STATE
@@ -513,6 +519,8 @@
 MBIM_TYPE_SAR_BACKOFF_STATE
 MBIM_TYPE_SAR_CONTROL_MODE
 MBIM_TYPE_SAR_WIFI_HARDWARE_STATE
+MBIM_TYPE_TRANSMISSION_NOTIFICATION_STATUS
+MBIM_TYPE_TRANSMISSION_STATE
 mbim_activation_command_get_type
 mbim_activation_state_get_type
 mbim_auth_protocol_get_type
@@ -576,6 +584,8 @@
 mbim_sar_backoff_state_get_type
 mbim_sar_control_mode_get_type
 mbim_sar_wifi_hardware_state_get_type
+mbim_transmission_notification_status_get_type
+mbim_transmission_state_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 3d8138b..1d2851c 100644
--- a/docs/reference/libmbim-glib/libmbim-glib-docs.xml
+++ b/docs/reference/libmbim-glib/libmbim-glib-docs.xml
@@ -8,7 +8,10 @@
 <book id="libmbim-glib">
   <bookinfo>
     <title>libmbim-glib Reference Manual</title>
-    <releaseinfo>for libmbim-glib &version;</releaseinfo>
+    <releaseinfo>
+      For libmbim-glib &version;. The latest version of this documentation can be found on-line at
+     <ulink role="online-location" url="https://www.freedesktop.org/software/libmbim/libmbim-glib/latest/">https://www.freedesktop.org/software/libmbim/libmbim-glib/latest/</ulink>.
+    </releaseinfo>
 
     <copyright>
       <year>2013</year>
@@ -19,6 +22,7 @@
       <year>2018</year>
       <year>2019</year>
       <year>2020</year>
+      <year>2021</year>
       <holder>The libmbim-glib authors</holder>
     </copyright>
 
diff --git a/gtk-doc.make b/gtk-doc.make
index 7d9a27f..913aa4f 100644
--- a/gtk-doc.make
+++ b/gtk-doc.make
@@ -285,7 +285,6 @@
 	    mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
 	      $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
 	  fi; \
-	  $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \
 	fi
 
 uninstall-local:
diff --git a/src/libmbim-glib/mbim-enums.h b/src/libmbim-glib/mbim-enums.h
index 8e6da3a..8f27d6f 100644
--- a/src/libmbim-glib/mbim-enums.h
+++ b/src/libmbim-glib/mbim-enums.h
@@ -1221,6 +1221,8 @@
  * @MBIM_SAR_CONTROL_MODE_OS: SAR backoff is controlled by the host operating system.
  *
  * SAR backoff mechanism control modes.
+ *
+ * Since: 1.26
  */
 typedef enum { /*< since=1.26 >*/
     MBIM_SAR_CONTROL_MODE_DEVICE = 0,
@@ -1233,6 +1235,8 @@
  * @MBIM_SAR_BACKOFF_STATE_ENABLED: SAR backoff is enabled.
  *
  * SAR backoff state.
+ *
+ * Since: 1.26
  */
 typedef enum { /*< since=1.26 >*/
     MBIM_SAR_BACKOFF_STATE_DISABLED = 0,
@@ -1245,12 +1249,42 @@
  * @MBIM_SAR_WIFI_HARDWARE_STATE_NOT_INTEGRATED: Not integrated.
  *
  * Whether the Wi-Fi and cellular SAR are integrated at hardware level.
+ *
+ * Since: 1.26
  */
 typedef enum { /*< since=1.26 >*/
-    MBIM_SAR_WIFI_HARDWARE_STATE_INTEGRATED = 0,
+    MBIM_SAR_WIFI_HARDWARE_STATE_INTEGRATED     = 0,
     MBIM_SAR_WIFI_HARDWARE_STATE_NOT_INTEGRATED = 1
 } MbimSarWifiHardwareState;
 
+/**
+ * MbimTransmissionNotificationStatus:
+ * @MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED: Notification disabled.
+ * @MBIM_TRANSMISSION_NOTIFICATION_STATUS_ENABLED: Notification enabled.
+ *
+ * Whether modem channel transmission status notification is disabled or enabled.
+ *
+ * Since: 1.26
+ */
+typedef enum { /*< since=1.26 >*/
+    MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED = 0,
+    MBIM_TRANSMISSION_NOTIFICATION_STATUS_ENABLED  = 1
+} MbimTransmissionNotificationStatus;
+
+/**
+ * MbimTransmissionState:
+ * @MBIM_TRANSMISSION_STATE_INACTIVE: Modem was not actively transmitting data.
+ * @MBIM_TRANSMISSION_STATE_ACTIVE: Modem was actively transmitting data.
+ *
+ * Whether modem is having TX traffic every hysteresis timeout.
+ *
+ * Since: 1.26
+ */
+typedef enum { /*< since=1.26 >*/
+    MBIM_TRANSMISSION_STATE_INACTIVE = 0,
+    MBIM_TRANSMISSION_STATE_ACTIVE   = 1
+} MbimTransmissionState;
+
 G_END_DECLS
 
 #endif /* _LIBMBIM_GLIB_MBIM_ENUMS_H_ */
diff --git a/src/mbim-proxy/mbim-proxy.c b/src/mbim-proxy/mbim-proxy.c
index 6af9a45..b152007 100644
--- a/src/mbim-proxy/mbim-proxy.c
+++ b/src/mbim-proxy/mbim-proxy.c
@@ -142,7 +142,7 @@
 {
     g_print ("\n"
              PROGRAM_NAME " " PROGRAM_VERSION "\n"
-             "Copyright (C) 2013-2020 Aleksander Morgado\n"
+             "Copyright (C) 2013-2021 Aleksander Morgado\n"
              "Copyright (C) 2014-2018 Greg Suarez\n"
              "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>\n"
              "This is free software: you are free to change and redistribute it.\n"
diff --git a/src/mbimcli/mbimcli-ms-sar.c b/src/mbimcli/mbimcli-ms-sar.c
index 8f6349f..13af884 100644
--- a/src/mbimcli/mbimcli-ms-sar.c
+++ b/src/mbimcli/mbimcli-ms-sar.c
@@ -41,18 +41,28 @@
 static Context *ctx;
 
 /* Options */
-static gchar   *set_sar_config_flag;
+static gchar   *set_sar_config_str;
 static gboolean query_sar_config_flag;
+static gchar   *set_transmission_status_str;
+static gboolean query_transmission_status_flag;
 
 static GOptionEntry entries[] = {
-    { "ms-set-sar-config", 0, 0, G_OPTION_ARG_STRING, &set_sar_config_flag,
+    { "ms-set-sar-config", 0, 0, G_OPTION_ARG_STRING, &set_sar_config_str,
       "Set SAR config",
-      "(device|os),(enabled|disabled)[,[{antenna_index,backoff_index}...]]"
+      "[(device|os),(enabled|disabled)[,[{antenna_index,backoff_index}...]]]"
     },
     { "ms-query-sar-config", 0, 0, G_OPTION_ARG_NONE, &query_sar_config_flag,
       "Query SAR config",
       NULL
     },
+    { "ms-set-transmission-status", 0, 0, G_OPTION_ARG_STRING, &set_transmission_status_str,
+      "Set transmission status and hysteresis timer (in seconds)",
+      "[(enabled|disabled),(timer)]"
+    },
+    { "ms-query-transmission-status", 0, 0, G_OPTION_ARG_NONE, &query_transmission_status_flag,
+      "Query transmission status",
+      NULL
+    },
     { NULL }
 };
 
@@ -80,8 +90,10 @@
     if (checked)
         return !!n_actions;
 
-    n_actions = !!set_sar_config_flag +
-                query_sar_config_flag;
+    n_actions = !!set_sar_config_str +
+                query_sar_config_flag +
+                !!set_transmission_status_str +
+                query_transmission_status_flag;
 
     if (n_actions > 1) {
         g_printerr ("error: too many Microsoft SAR actions requested\n");
@@ -174,6 +186,51 @@
     shutdown (TRUE);
 }
 
+static void
+modem_transmission_status_ready (MbimDevice   *device,
+                                 GAsyncResult *res)
+{
+    g_autoptr(MbimMessage)              response = NULL;
+    g_autoptr(GError)                   error = NULL;
+    MbimTransmissionNotificationStatus  channel_notification;
+    const gchar                        *channel_notification_str;
+    MbimTransmissionState               transmission_status;
+    const gchar                        *transmission_status_str;
+    guint32                             hysteresis_timer;
+
+    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_ms_sar_transmission_status_response_parse (
+            response,
+            &channel_notification,
+            &transmission_status,
+            &hysteresis_timer,
+            &error)) {
+        g_printerr ("error: couldn't parse response message: %s\n", error->message);
+        shutdown (FALSE);
+        return;
+    }
+
+    channel_notification_str = mbim_transmission_notification_status_get_string (channel_notification);
+    transmission_status_str  = mbim_transmission_state_get_string (transmission_status);
+
+    g_print ("[%s] Transmission status:\n"
+             "\t        notification: %s\n"
+             "\t              status: %s\n"
+             "\t    hysteresis timer: (%u)\n",
+             mbim_device_get_path_display (device),
+             VALIDATE_UNKNOWN (channel_notification_str),
+             VALIDATE_UNKNOWN (transmission_status_str),
+             hysteresis_timer);
+
+    shutdown (TRUE);
+}
+
 static gboolean
 sar_config_input_parse (const gchar         *str,
                         MbimSarControlMode  *mode,
@@ -244,6 +301,48 @@
     return TRUE;
 }
 
+static gboolean
+transmission_status_input_parse (const gchar                        *str,
+                                 MbimTransmissionNotificationStatus *notification,
+                                 guint                              *hysteresis_timer)
+{
+    g_auto(GStrv) split = NULL;
+
+    g_assert (notification != NULL);
+    g_assert (hysteresis_timer != NULL);
+
+    /* Format of the string is:
+     *    "(notification: enabled or disabled),(seconds: 1~5)"
+     */
+    split = g_strsplit (str, ",", -1);
+
+    if (g_strv_length (split) < 2) {
+        g_printerr ("error: couldn't parse input string, missing arguments\n");
+        return FALSE;
+    }
+
+    if (g_ascii_strcasecmp (split[0], "disabled") == 0) {
+        *notification = MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED;
+    } else if (g_ascii_strcasecmp (split[0], "enabled") == 0) {
+        *notification = MBIM_TRANSMISSION_NOTIFICATION_STATUS_ENABLED;
+    } else {
+        g_printerr ("error: invalid state: '%s', it must be enabled or disabled\n", split[0]);
+        return FALSE;
+    }
+
+    if (!mbimcli_read_uint_from_string (split[1], hysteresis_timer)) {
+        g_printerr ("error: couldn't parse input string, invalid seconds '%s'\n", split[1]);
+        return FALSE;
+    }
+
+    if (*hysteresis_timer < 1 || *hysteresis_timer > 5) {
+        g_printerr ("error: the seconds of hysteresis_timer is %u, it must in range [1,5]\n", *hysteresis_timer);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 void
 mbimcli_ms_sar_run (MbimDevice   *device,
                     GCancellable *cancellable)
@@ -256,7 +355,7 @@
     ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
 
     /* Request to set SAR config */
-    if (set_sar_config_flag) {
+    if (set_sar_config_str) {
         g_autoptr(GPtrArray) states_array = NULL;
 
         MbimSarControlMode         mode;
@@ -265,7 +364,7 @@
         const MbimSarConfigState **states_ptrs  = NULL;
 
         g_print ("Asynchronously set sar config\n");
-        if (!sar_config_input_parse (set_sar_config_flag, &mode, &state, &states_array)) {
+        if (!sar_config_input_parse (set_sar_config_str, &mode, &state, &states_array)) {
             shutdown (FALSE);
             return;
         }
@@ -298,5 +397,41 @@
         return;
     }
 
+    /* Request to set transmission status */
+    if (set_transmission_status_str) {
+        MbimTransmissionNotificationStatus notification     = MBIM_TRANSMISSION_NOTIFICATION_STATUS_DISABLED;
+        guint32                            hysteresis_timer = 0;
+        g_debug ("Asynchronously set transmission status");
+
+        if (!transmission_status_input_parse (set_transmission_status_str,
+                                              &notification,
+                                              &hysteresis_timer)) {
+            shutdown (FALSE);
+            return;
+        }
+
+        request = mbim_message_ms_sar_transmission_status_set_new (notification, hysteresis_timer, NULL);
+        mbim_device_command (ctx->device,
+                             request,
+                             10,
+                             ctx->cancellable,
+                             (GAsyncReadyCallback)modem_transmission_status_ready,
+                             NULL);
+        return;
+    }
+
+    /* Request to query transmission status */
+    if (query_transmission_status_flag) {
+        g_debug ("Asynchronously query transmission status");
+        request = mbim_message_ms_sar_transmission_status_query_new (NULL);
+        mbim_device_command (ctx->device,
+                             request,
+                             10,
+                             ctx->cancellable,
+                             (GAsyncReadyCallback)modem_transmission_status_ready,
+                             NULL);
+        return;
+    }
+
     g_warn_if_reached ();
 }
diff --git a/src/mbimcli/mbimcli.c b/src/mbimcli/mbimcli.c
index b2fa72e..f0126f3 100644
--- a/src/mbimcli/mbimcli.c
+++ b/src/mbimcli/mbimcli.c
@@ -178,7 +178,7 @@
 print_version_and_exit (void)
 {
     g_print (PROGRAM_NAME " " PROGRAM_VERSION "\n"
-             "Copyright (C) 2013-2020 Aleksander Morgado\n"
+             "Copyright (C) 2013-2021 Aleksander Morgado\n"
              "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>\n"
              "This is free software: you are free to change and redistribute it.\n"
              "There is NO WARRANTY, to the extent permitted by law.\n"
diff --git a/utils/mbim-network.in b/utils/mbim-network.in
index 17d92e4..e19f0e7 100755
--- a/utils/mbim-network.in
+++ b/utils/mbim-network.in
@@ -79,7 +79,7 @@
 version ()
 {
     echo "mbim-network @VERSION@"
-    echo "Copyright (C) 2013-2018 Aleksander Morgado"
+    echo "Copyright (C) 2013-2021 Aleksander Morgado"
     echo "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl-2.0.html>"
     echo "This is free software: you are free to change and redistribute it."
     echo "There is NO WARRANTY, to the extent permitted by law."