// SPDX-License-Identifier: GPL-2.0 /* * Copyright 2019 Google LLC */ #include #include #include /* Operation code; what the EC should do with the property */ enum ec_property_op { EC_OP_GET = 0, EC_OP_SET = 1, }; struct ec_property_request { u8 op; /* One of enum ec_property_op */ u8 property_id[4]; /* The 32 bit PID is stored Little Endian */ u8 length; u8 data[WILCO_EC_PROPERTY_MAX_SIZE]; } __packed; struct ec_property_response { u8 reserved[2]; u8 op; /* One of enum ec_property_op */ u8 property_id[4]; /* The 32 bit PID is stored Little Endian */ u8 length; u8 data[WILCO_EC_PROPERTY_MAX_SIZE]; } __packed; static int send_property_msg(struct wilco_ec_device *ec, struct ec_property_request *rq, struct ec_property_response *rs) { struct wilco_ec_message ec_msg; int ret; memset(&ec_msg, 0, sizeof(ec_msg)); ec_msg.type = WILCO_EC_MSG_PROPERTY; ec_msg.request_data = rq; ec_msg.request_size = sizeof(*rq); ec_msg.response_data = rs; ec_msg.response_size = sizeof(*rs); ret = wilco_ec_mailbox(ec, &ec_msg); if (ret < 0) return ret; if (rs->op != rq->op) return -EBADMSG; if (memcmp(rq->property_id, rs->property_id, sizeof(rs->property_id))) return -EBADMSG; return 0; } int wilco_ec_get_property(struct wilco_ec_device *ec, struct wilco_ec_property_msg *prop_msg) { struct ec_property_request rq; struct ec_property_response rs; int ret; memset(&rq, 0, sizeof(rq)); rq.op = EC_OP_GET; put_unaligned_le32(prop_msg->property_id, rq.property_id); ret = send_property_msg(ec, &rq, &rs); if (ret < 0) return ret; prop_msg->length = rs.length; memcpy(prop_msg->data, rs.data, rs.length); return 0; } EXPORT_SYMBOL_GPL(wilco_ec_get_property); int wilco_ec_set_property(struct wilco_ec_device *ec, struct wilco_ec_property_msg *prop_msg) { struct ec_property_request rq; struct ec_property_response rs; int ret; memset(&rq, 0, sizeof(rq)); rq.op = EC_OP_SET; put_unaligned_le32(prop_msg->property_id, rq.property_id); rq.length = prop_msg->length; memcpy(rq.data, prop_msg->data, prop_msg->length); ret = send_property_msg(ec, &rq, &rs); if (ret < 0) return ret; if (rs.length != prop_msg->length) return -EBADMSG; return 0; } EXPORT_SYMBOL_GPL(wilco_ec_set_property); int wilco_ec_get_byte_property(struct wilco_ec_device *ec, u32 property_id, u8 *val) { struct wilco_ec_property_msg msg; int ret; msg.property_id = property_id; ret = wilco_ec_get_property(ec, &msg); if (ret < 0) return ret; if (msg.length != 1) return -EBADMSG; *val = msg.data[0]; return 0; } EXPORT_SYMBOL_GPL(wilco_ec_get_byte_property); int wilco_ec_set_byte_property(struct wilco_ec_device *ec, u32 property_id, u8 val) { struct wilco_ec_property_msg msg; msg.property_id = property_id; msg.data[0] = val; msg.length = 1; return wilco_ec_set_property(ec, &msg); } EXPORT_SYMBOL_GPL(wilco_ec_set_byte_property);