qmidev: add void requests

Add a shortcut for making requests that don't return anything but a
result code.

BUG=None
TEST=still work

Change-Id: I4c291c087c377aec39f1a44004df4cd594915f17
diff --git a/src/qmidev.c b/src/qmidev.c
index c1c8e75..a97ef01 100644
--- a/src/qmidev.c
+++ b/src/qmidev.c
@@ -27,6 +27,8 @@
 #include "qmimsg.h"
 #include "util.h"
 
+static const int qmidev_log_unhandled_messages = 0;
+
 struct qmidev {
   void *priv;
 
@@ -62,7 +64,7 @@
   void *context;
 };
 
-static void call_listeners(struct qmidev *qmidev, struct qmimsg *message);
+static int call_listeners(struct qmidev *qmidev, struct qmimsg *message);
 static void call_callbacks(struct qmidev *qmidev);
 
 static struct qmidev *qmidev_new(void)
@@ -441,6 +443,42 @@
   return 0;
 }
 
+struct void_context {
+  qmidev_response_fn caller_callback;
+  void *caller_context;
+};
+
+static void void_callback(struct qmidev *qmidev,
+                          void *data,
+                          int result,
+                          struct qmimsg *message)
+{
+  struct void_context *context = data;
+
+  assert(qmidev);
+  assert(data);
+
+  /* unused */
+  message = message;
+
+  context->caller_callback(qmidev, context->caller_context, result);
+  g_slice_free(struct void_context, context);
+}
+
+int qmidev_send_void_request(struct qmidev *qmidev,
+                             struct qmimsg *req_msg,
+                             uint16_t resp_msg_id,
+                             qmidev_response_fn caller_callback,
+                             void *caller_context)
+{
+  struct void_context *context = g_slice_new(struct void_context);
+  context->caller_callback = caller_callback;
+  context->caller_context = caller_context;
+
+  return qmidev_send_request(qmidev, req_msg, resp_msg_id,
+                             &void_callback, context);
+}
+
 static int dev_read_fn(void *ctx, void *buf, size_t len)
 {
   assert(ctx);
@@ -461,7 +499,8 @@
   /* TODO: Do something. */
   if (result)
     return;
-  call_listeners(qmidev, msg);
+  if (call_listeners(qmidev, msg) && qmidev_log_unhandled_messages)
+    qmimsg_print(msg);
   qmimsg_free(msg);
 }
 
@@ -595,6 +634,7 @@
   uint8_t service;
   uint8_t client;
   uint16_t transaction;
+  int calls;
 };
 
 static void call_listener(void *data, void *user_data)
@@ -617,18 +657,22 @@
                                   listener->context,
                                   context->message);
   if (result) {
-    /* The glib documentation does not note this, but it is in safe to call
-       g_list_remove while called back from g_list_foreach. */
+    /* The glib documentation does not note this, but it is in fact safe to
+       call g_list_remove while called back from g_list_foreach. */
     qmidev_cancel_listen(context->qmidev, listener);
   }
+
+  context->calls++;
 }
 
-static void call_listeners(struct qmidev *qmidev, struct qmimsg *message)
+static int call_listeners(struct qmidev *qmidev, struct qmimsg *message)
 {
   struct call_listener_context context;
   context.qmidev = qmidev;
   context.message = message;
   qmimsg_get_header(message,
                     &context.service, &context.client, &context.transaction);
+  context.calls = 0;
   g_list_foreach(qmidev->listeners, &call_listener, &context);
+  return context.calls == 0;
 }
diff --git a/src/qmidev.h b/src/qmidev.h
index f7b73b4..16becde 100644
--- a/src/qmidev.h
+++ b/src/qmidev.h
@@ -13,6 +13,8 @@
 #ifndef LIBQMI_QMIDEV_H
 #define LIBQMI_QMIDEV_H
 
+#include <libqmi.h>
+
 #include <stddef.h>
 #include <stdint.h>
 
@@ -90,6 +92,12 @@
                         qmidev_request_fn callback,
                         void *context);
 
+int qmidev_send_void_request(struct qmidev *qmidev,
+                             struct qmimsg *req_msg,
+                             uint16_t resp_msg_id,
+                             qmidev_response_fn caller_callback,
+                             void *caller_context);
+
 /**
  * Sends a QMI message.
  * Returns zero on success, errno on failure.
diff --git a/src/qmidms.c b/src/qmidms.c
index 6ac9d40..af4510a 100644
--- a/src/qmidms.c
+++ b/src/qmidms.c
@@ -20,6 +20,7 @@
 
 #include <libqmi.h>
 
+#include "error.h"
 #include "qmi.h"
 #include "qmidev.h"
 #include "qmimsg.h"
@@ -168,35 +169,6 @@
   return result;
 }
 
-struct set_power_context {
-  qmidev_response_fn caller_callback;
-  void *caller_context;
-};
-
-static void set_power(struct qmidev *qmidev,
-                         void *data,
-                         int status,
-                         struct qmimsg *message)
-{
-  assert(qmidev);
-  assert(data);
-
-  struct set_power_context *context = data;
-  int result;
-
-  if (status) {
-    result = status;
-    goto out;
-  }
-
-  message = message;
-  result = 0;
-
-out:
-  context->caller_callback(qmidev, context->caller_context, result);
-  g_slice_free(struct set_power_context, context);
-}
-
 int qmidev_set_power(struct qmidev *qmidev,
                      qmidev_power_state state,
                      qmidev_response_fn caller_callback,
@@ -205,25 +177,18 @@
   uint8_t mode = state;
   int result;
 
-  struct set_power_context *context = g_slice_new(struct set_power_context);
-  context->caller_callback = caller_callback;
-  context->caller_context  = caller_context;
-
   struct qmimsg *message;
   result = qmidev_make_request(qmidev,
                                QMI_SVC_DMS,
                                QMIDMS_MSG_SET_OPERATING_MODE,
                                &message);
-  qmimsg_tlv_add(message, QMI_TLV_VALUE, sizeof(mode), &mode);
-  result = qmidev_send_request(qmidev, message,
-                               QMIDMS_MSG_SET_OPERATING_MODE,
-                               &set_power, context);
   if (result)
-    goto fail;
-
-  return 0;
-
-fail:
-  g_slice_free(struct set_power_context, context);
-  return result;
+    return result;
+  result = qmimsg_tlv_add(message, QMI_TLV_VALUE, sizeof(mode), &mode);
+  if (result)
+    return QMI_ERR_INTERNAL;
+  return qmidev_send_void_request(qmidev, message,
+                                  QMIDMS_MSG_SET_OPERATING_MODE,
+                                  caller_callback,
+                                  caller_context);
 }