qmidms: get/set operating mode ("power") requests
Implement requests to get and set the device's operating mode.
BUG=chromium-os:28019
TEST=manual, works
Change-Id: I24a42ad8e8c270dfa64eeb560856cdeb0eb555b9
diff --git a/src/qmi.h b/src/qmi.h
index 9f27801..cfca765 100644
--- a/src/qmi.h
+++ b/src/qmi.h
@@ -15,8 +15,14 @@
struct qmimsg;
-#define QMI_CID_NONE ((uint8_t)0x00)
-#define QMI_CID_BROADCAST ((uint8_t)0xFF)
+enum {
+ QMI_CID_NONE = 0x00,
+ QMI_CID_BROADCAST = 0xFF
+};
+
+enum {
+ QMI_TLV_VALUE = 0x01
+};
enum {
/** Control service */
diff --git a/src/qmictl.c b/src/qmictl.c
index 7799b0c..d442d3e 100644
--- a/src/qmictl.c
+++ b/src/qmictl.c
@@ -30,12 +30,20 @@
#define QMI_CTL_CLIENT 0x00
enum {
- QMICTL_MSG_GET_CID = 0x0022,
- QMICTL_MSG_RELEASE_CID = 0x0023
+ QMICTL_MSG_SET_INSTANCE_ID = 0x0020,
+ QMICTL_MSG_GET_VERSION_INFO,
+ QMICTL_MSG_GET_CLIENT_ID,
+ QMICTL_MSG_RELEASE_CLIENT_ID,
+ QMICTL_MSG_REVOKE_CLIENT_ID,
+ QMICTL_MSG_INVALID_CLIENT_ID,
+ QMICTL_MSG_SET_DATA_FORMAT,
+ QMICTL_MSG_SYNC,
+ QMICTL_MSG_EVENT,
+ QMICTL_MSG_SET_POWER_SAVE_CONFIG,
+ QMICTL_MSG_SET_POWER_SAVE_MODE,
+ QMICTL_MSG_GET_POWER_SAVE_MODE
};
-#define QMI_TLV_ID ((uint8_t)0x01)
-
struct qmi_cid {
uint8_t service;
uint8_t client;
@@ -46,7 +54,7 @@
assert(message);
assert(id_out);
- return qmimsg_tlv_get(message, QMI_TLV_ID, sizeof(*id_out), id_out);
+ return qmimsg_tlv_get(message, QMI_TLV_VALUE, sizeof(*id_out), id_out);
}
struct get_cid_context {
@@ -103,15 +111,17 @@
context->service = service;
struct qmimsg *message;
- result = qmidev_make_request(qmidev, QMI_SVC_CTL, QMICTL_MSG_GET_CID,
+ result = qmidev_make_request(qmidev,
+ QMI_SVC_CTL,
+ QMICTL_MSG_GET_CLIENT_ID,
&message);
if (result)
goto fail;
- qmimsg_tlv_add(message, QMI_TLV_ID, sizeof(service), &service);
+ qmimsg_tlv_add(message, QMI_TLV_VALUE, sizeof(service), &service);
result = qmidev_send_request(qmidev, message,
- QMICTL_MSG_GET_CID,
+ QMICTL_MSG_GET_CLIENT_ID,
&got_cid, context);
if (result)
goto fail;
@@ -178,15 +188,17 @@
context->id.client = client;
struct qmimsg *message;
- result = qmidev_make_request(qmidev, QMI_SVC_CTL, QMICTL_MSG_RELEASE_CID,
+ result = qmidev_make_request(qmidev,
+ QMI_SVC_CTL,
+ QMICTL_MSG_RELEASE_CLIENT_ID,
&message);
if (result)
goto fail;
- qmimsg_tlv_add(message, QMI_TLV_ID, sizeof(context->id), &context->id);
+ qmimsg_tlv_add(message, QMI_TLV_VALUE, sizeof(context->id), &context->id);
result = qmidev_send_request(qmidev, message,
- QMICTL_MSG_RELEASE_CID,
+ QMICTL_MSG_RELEASE_CLIENT_ID,
&released_cid, context);
if (result)
goto fail;
diff --git a/src/qmidms.c b/src/qmidms.c
index ccc3f1d..6ac9d40 100644
--- a/src/qmidms.c
+++ b/src/qmidms.c
@@ -25,7 +25,9 @@
#include "qmimsg.h"
enum {
- QMIDMS_MSG_GET_IDS = 37
+ QMIDMS_MSG_GET_IDS = 0x0025,
+ QMIDMS_MSG_GET_OPERATING_MODE = 0x002D,
+ QMIDMS_MSG_SET_OPERATING_MODE = 0x002E
};
enum {
@@ -40,13 +42,12 @@
};
static void got_ids(struct qmidev *qmidev,
- void *data,
- int status,
- struct qmimsg *message)
+ void *data,
+ int status,
+ struct qmimsg *message)
{
assert(qmidev);
assert(data);
- assert(message);
struct get_ids_context *context = data;
int result;
@@ -101,3 +102,128 @@
g_slice_free(struct get_ids_context, context);
return result;
}
+
+struct get_power_context {
+ qmidev_power_state_response_fn caller_callback;
+ void *caller_context;
+};
+
+static void got_power(struct qmidev *qmidev,
+ void *data,
+ int status,
+ struct qmimsg *message)
+{
+ uint8_t mode;
+
+ assert(qmidev);
+ assert(data);
+
+ struct get_power_context *context = data;
+ int result;
+
+ if (status) {
+ result = status;
+ goto out;
+ }
+
+ result = qmimsg_tlv_get(message, QMI_TLV_VALUE, sizeof(mode), &mode);
+ if (result)
+ goto out;
+
+ result = 0;
+
+out:
+ context->caller_callback(qmidev, context->caller_context, result, mode);
+ g_slice_free(struct get_power_context, context);
+}
+
+int qmidev_get_power(struct qmidev *qmidev,
+ qmidev_power_state_response_fn caller_callback,
+ void *caller_context)
+{
+ int result;
+
+ struct get_power_context *context = g_slice_new(struct get_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_GET_OPERATING_MODE,
+ &message);
+ if (result)
+ goto fail;
+
+ result = qmidev_send_request(qmidev, message,
+ QMIDMS_MSG_GET_OPERATING_MODE,
+ &got_power, context);
+ if (result)
+ goto fail;
+
+ return 0;
+
+fail:
+ g_slice_free(struct get_power_context, context);
+ 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,
+ void *caller_context)
+{
+ 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;
+}