19b8a11e8SBjorn Andersson // SPDX-License-Identifier: GPL-2.0 29b8a11e8SBjorn Andersson /* 39b8a11e8SBjorn Andersson * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. 49b8a11e8SBjorn Andersson * Copyright (c) 2017, Linaro Ltd. 59b8a11e8SBjorn Andersson */ 69b8a11e8SBjorn Andersson #ifndef __QMI_HELPERS_H__ 79b8a11e8SBjorn Andersson #define __QMI_HELPERS_H__ 89b8a11e8SBjorn Andersson 93830d077SBjorn Andersson #include <linux/completion.h> 103830d077SBjorn Andersson #include <linux/idr.h> 113830d077SBjorn Andersson #include <linux/list.h> 123830d077SBjorn Andersson #include <linux/qrtr.h> 139b8a11e8SBjorn Andersson #include <linux/types.h> 143830d077SBjorn Andersson #include <linux/workqueue.h> 153830d077SBjorn Andersson 163830d077SBjorn Andersson struct socket; 179b8a11e8SBjorn Andersson 189b8a11e8SBjorn Andersson /** 198058dfa0SLukas Bulwahn * struct qmi_header - wireformat header of QMI messages 209b8a11e8SBjorn Andersson * @type: type of message 219b8a11e8SBjorn Andersson * @txn_id: transaction id 229b8a11e8SBjorn Andersson * @msg_id: message id 239b8a11e8SBjorn Andersson * @msg_len: length of message payload following header 249b8a11e8SBjorn Andersson */ 259b8a11e8SBjorn Andersson struct qmi_header { 269b8a11e8SBjorn Andersson u8 type; 279b8a11e8SBjorn Andersson u16 txn_id; 289b8a11e8SBjorn Andersson u16 msg_id; 299b8a11e8SBjorn Andersson u16 msg_len; 309b8a11e8SBjorn Andersson } __packed; 319b8a11e8SBjorn Andersson 329b8a11e8SBjorn Andersson #define QMI_REQUEST 0 339b8a11e8SBjorn Andersson #define QMI_RESPONSE 2 349b8a11e8SBjorn Andersson #define QMI_INDICATION 4 359b8a11e8SBjorn Andersson 369b8a11e8SBjorn Andersson #define QMI_COMMON_TLV_TYPE 0 379b8a11e8SBjorn Andersson 389b8a11e8SBjorn Andersson enum qmi_elem_type { 399b8a11e8SBjorn Andersson QMI_EOTI, 409b8a11e8SBjorn Andersson QMI_OPT_FLAG, 419b8a11e8SBjorn Andersson QMI_DATA_LEN, 429b8a11e8SBjorn Andersson QMI_UNSIGNED_1_BYTE, 439b8a11e8SBjorn Andersson QMI_UNSIGNED_2_BYTE, 449b8a11e8SBjorn Andersson QMI_UNSIGNED_4_BYTE, 459b8a11e8SBjorn Andersson QMI_UNSIGNED_8_BYTE, 469b8a11e8SBjorn Andersson QMI_SIGNED_2_BYTE_ENUM, 479b8a11e8SBjorn Andersson QMI_SIGNED_4_BYTE_ENUM, 489b8a11e8SBjorn Andersson QMI_STRUCT, 499b8a11e8SBjorn Andersson QMI_STRING, 509b8a11e8SBjorn Andersson }; 519b8a11e8SBjorn Andersson 529b8a11e8SBjorn Andersson enum qmi_array_type { 539b8a11e8SBjorn Andersson NO_ARRAY, 549b8a11e8SBjorn Andersson STATIC_ARRAY, 559b8a11e8SBjorn Andersson VAR_LEN_ARRAY, 569b8a11e8SBjorn Andersson }; 579b8a11e8SBjorn Andersson 589b8a11e8SBjorn Andersson /** 599b8a11e8SBjorn Andersson * struct qmi_elem_info - describes how to encode a single QMI element 609b8a11e8SBjorn Andersson * @data_type: Data type of this element. 619b8a11e8SBjorn Andersson * @elem_len: Array length of this element, if an array. 629b8a11e8SBjorn Andersson * @elem_size: Size of a single instance of this data type. 639b8a11e8SBjorn Andersson * @array_type: Array type of this element. 649b8a11e8SBjorn Andersson * @tlv_type: QMI message specific type to identify which element 659b8a11e8SBjorn Andersson * is present in an incoming message. 669b8a11e8SBjorn Andersson * @offset: Specifies the offset of the first instance of this 679b8a11e8SBjorn Andersson * element in the data structure. 689b8a11e8SBjorn Andersson * @ei_array: Null-terminated array of @qmi_elem_info to describe nested 699b8a11e8SBjorn Andersson * structures. 709b8a11e8SBjorn Andersson */ 719b8a11e8SBjorn Andersson struct qmi_elem_info { 729b8a11e8SBjorn Andersson enum qmi_elem_type data_type; 739b8a11e8SBjorn Andersson u32 elem_len; 749b8a11e8SBjorn Andersson u32 elem_size; 759b8a11e8SBjorn Andersson enum qmi_array_type array_type; 769b8a11e8SBjorn Andersson u8 tlv_type; 779b8a11e8SBjorn Andersson u32 offset; 78*ff6d3658SJeff Johnson const struct qmi_elem_info *ei_array; 799b8a11e8SBjorn Andersson }; 809b8a11e8SBjorn Andersson 819b8a11e8SBjorn Andersson #define QMI_RESULT_SUCCESS_V01 0 829b8a11e8SBjorn Andersson #define QMI_RESULT_FAILURE_V01 1 839b8a11e8SBjorn Andersson 849b8a11e8SBjorn Andersson #define QMI_ERR_NONE_V01 0 859b8a11e8SBjorn Andersson #define QMI_ERR_MALFORMED_MSG_V01 1 869b8a11e8SBjorn Andersson #define QMI_ERR_NO_MEMORY_V01 2 879b8a11e8SBjorn Andersson #define QMI_ERR_INTERNAL_V01 3 889b8a11e8SBjorn Andersson #define QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 5 899b8a11e8SBjorn Andersson #define QMI_ERR_INVALID_ID_V01 41 909b8a11e8SBjorn Andersson #define QMI_ERR_ENCODING_V01 58 91fbe639b4SSibi Sankar #define QMI_ERR_DISABLED_V01 69 929b8a11e8SBjorn Andersson #define QMI_ERR_INCOMPATIBLE_STATE_V01 90 939b8a11e8SBjorn Andersson #define QMI_ERR_NOT_SUPPORTED_V01 94 949b8a11e8SBjorn Andersson 959b8a11e8SBjorn Andersson /** 968058dfa0SLukas Bulwahn * struct qmi_response_type_v01 - common response header (decoded) 979b8a11e8SBjorn Andersson * @result: result of the transaction 989b8a11e8SBjorn Andersson * @error: error value, when @result is QMI_RESULT_FAILURE_V01 999b8a11e8SBjorn Andersson */ 1009b8a11e8SBjorn Andersson struct qmi_response_type_v01 { 1019b8a11e8SBjorn Andersson u16 result; 1029b8a11e8SBjorn Andersson u16 error; 1039b8a11e8SBjorn Andersson }; 1049b8a11e8SBjorn Andersson 105*ff6d3658SJeff Johnson extern const struct qmi_elem_info qmi_response_type_v01_ei[]; 1069b8a11e8SBjorn Andersson 1073830d077SBjorn Andersson /** 1083830d077SBjorn Andersson * struct qmi_service - context to track lookup-results 1093830d077SBjorn Andersson * @service: service type 1103830d077SBjorn Andersson * @version: version of the @service 1113830d077SBjorn Andersson * @instance: instance id of the @service 1123830d077SBjorn Andersson * @node: node of the service 1133830d077SBjorn Andersson * @port: port of the service 1143830d077SBjorn Andersson * @priv: handle for client's use 1153830d077SBjorn Andersson * @list_node: list_head for house keeping 1163830d077SBjorn Andersson */ 1173830d077SBjorn Andersson struct qmi_service { 1183830d077SBjorn Andersson unsigned int service; 1193830d077SBjorn Andersson unsigned int version; 1203830d077SBjorn Andersson unsigned int instance; 1213830d077SBjorn Andersson 1223830d077SBjorn Andersson unsigned int node; 1233830d077SBjorn Andersson unsigned int port; 1243830d077SBjorn Andersson 1253830d077SBjorn Andersson void *priv; 1263830d077SBjorn Andersson struct list_head list_node; 1273830d077SBjorn Andersson }; 1283830d077SBjorn Andersson 1293830d077SBjorn Andersson struct qmi_handle; 1303830d077SBjorn Andersson 1313830d077SBjorn Andersson /** 1323830d077SBjorn Andersson * struct qmi_ops - callbacks for qmi_handle 1333830d077SBjorn Andersson * @new_server: inform client of a new_server lookup-result, returning 1343830d077SBjorn Andersson * successfully from this call causes the library to call 1353830d077SBjorn Andersson * @del_server as the service is removed from the 1363830d077SBjorn Andersson * lookup-result. @priv of the qmi_service can be used by 1373830d077SBjorn Andersson * the client 1383830d077SBjorn Andersson * @del_server: inform client of a del_server lookup-result 1393830d077SBjorn Andersson * @net_reset: inform client that the name service was restarted and 1403830d077SBjorn Andersson * that and any state needs to be released 1413830d077SBjorn Andersson * @msg_handler: invoked for incoming messages, allows a client to 1423830d077SBjorn Andersson * override the usual QMI message handler 1433830d077SBjorn Andersson * @bye: inform a client that all clients from a node are gone 1443830d077SBjorn Andersson * @del_client: inform a client that a particular client is gone 1453830d077SBjorn Andersson */ 1463830d077SBjorn Andersson struct qmi_ops { 1473830d077SBjorn Andersson int (*new_server)(struct qmi_handle *qmi, struct qmi_service *svc); 1483830d077SBjorn Andersson void (*del_server)(struct qmi_handle *qmi, struct qmi_service *svc); 1493830d077SBjorn Andersson void (*net_reset)(struct qmi_handle *qmi); 1503830d077SBjorn Andersson void (*msg_handler)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 1513830d077SBjorn Andersson const void *data, size_t count); 1523830d077SBjorn Andersson void (*bye)(struct qmi_handle *qmi, unsigned int node); 1533830d077SBjorn Andersson void (*del_client)(struct qmi_handle *qmi, 1543830d077SBjorn Andersson unsigned int node, unsigned int port); 1553830d077SBjorn Andersson }; 1563830d077SBjorn Andersson 1573830d077SBjorn Andersson /** 1583830d077SBjorn Andersson * struct qmi_txn - transaction context 1593830d077SBjorn Andersson * @qmi: QMI handle this transaction is associated with 1603830d077SBjorn Andersson * @id: transaction id 1613830d077SBjorn Andersson * @lock: for synchronization between handler and waiter of messages 1623830d077SBjorn Andersson * @completion: completion object as the transaction receives a response 1633830d077SBjorn Andersson * @result: result code for the completed transaction 1643830d077SBjorn Andersson * @ei: description of the QMI encoded response (optional) 1653830d077SBjorn Andersson * @dest: destination buffer to decode message into (optional) 1663830d077SBjorn Andersson */ 1673830d077SBjorn Andersson struct qmi_txn { 1683830d077SBjorn Andersson struct qmi_handle *qmi; 1693830d077SBjorn Andersson 170c4fe17e0SArun Kumar Neelakantam u16 id; 1713830d077SBjorn Andersson 1723830d077SBjorn Andersson struct mutex lock; 1733830d077SBjorn Andersson struct completion completion; 1743830d077SBjorn Andersson int result; 1753830d077SBjorn Andersson 176*ff6d3658SJeff Johnson const struct qmi_elem_info *ei; 1773830d077SBjorn Andersson void *dest; 1783830d077SBjorn Andersson }; 1793830d077SBjorn Andersson 1803830d077SBjorn Andersson /** 1813830d077SBjorn Andersson * struct qmi_msg_handler - description of QMI message handler 1823830d077SBjorn Andersson * @type: type of message 1833830d077SBjorn Andersson * @msg_id: message id 1843830d077SBjorn Andersson * @ei: description of the QMI encoded message 1853830d077SBjorn Andersson * @decoded_size: size of the decoded object 1863830d077SBjorn Andersson * @fn: function to invoke as the message is decoded 1873830d077SBjorn Andersson */ 1883830d077SBjorn Andersson struct qmi_msg_handler { 1893830d077SBjorn Andersson unsigned int type; 1903830d077SBjorn Andersson unsigned int msg_id; 1913830d077SBjorn Andersson 192*ff6d3658SJeff Johnson const struct qmi_elem_info *ei; 1933830d077SBjorn Andersson 1943830d077SBjorn Andersson size_t decoded_size; 1953830d077SBjorn Andersson void (*fn)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 1963830d077SBjorn Andersson struct qmi_txn *txn, const void *decoded); 1973830d077SBjorn Andersson }; 1983830d077SBjorn Andersson 1993830d077SBjorn Andersson /** 2003830d077SBjorn Andersson * struct qmi_handle - QMI context 2013830d077SBjorn Andersson * @sock: socket handle 2023830d077SBjorn Andersson * @sock_lock: synchronization of @sock modifications 2033830d077SBjorn Andersson * @sq: sockaddr of @sock 2043830d077SBjorn Andersson * @work: work for handling incoming messages 2053830d077SBjorn Andersson * @wq: workqueue to post @work on 2063830d077SBjorn Andersson * @recv_buf: scratch buffer for handling incoming messages 2073830d077SBjorn Andersson * @recv_buf_size: size of @recv_buf 2083830d077SBjorn Andersson * @lookups: list of registered lookup requests 2093830d077SBjorn Andersson * @lookup_results: list of lookup-results advertised to the client 2103830d077SBjorn Andersson * @services: list of registered services (by this client) 2113830d077SBjorn Andersson * @ops: reference to callbacks 2123830d077SBjorn Andersson * @txns: outstanding transactions 2133830d077SBjorn Andersson * @txn_lock: lock for modifications of @txns 2143830d077SBjorn Andersson * @handlers: list of handlers for incoming messages 2153830d077SBjorn Andersson */ 2163830d077SBjorn Andersson struct qmi_handle { 2173830d077SBjorn Andersson struct socket *sock; 2183830d077SBjorn Andersson struct mutex sock_lock; 2193830d077SBjorn Andersson 2203830d077SBjorn Andersson struct sockaddr_qrtr sq; 2213830d077SBjorn Andersson 2223830d077SBjorn Andersson struct work_struct work; 2233830d077SBjorn Andersson struct workqueue_struct *wq; 2243830d077SBjorn Andersson 2253830d077SBjorn Andersson void *recv_buf; 2263830d077SBjorn Andersson size_t recv_buf_size; 2273830d077SBjorn Andersson 2283830d077SBjorn Andersson struct list_head lookups; 2293830d077SBjorn Andersson struct list_head lookup_results; 2303830d077SBjorn Andersson struct list_head services; 2313830d077SBjorn Andersson 2323830d077SBjorn Andersson struct qmi_ops ops; 2333830d077SBjorn Andersson 2343830d077SBjorn Andersson struct idr txns; 2353830d077SBjorn Andersson struct mutex txn_lock; 2363830d077SBjorn Andersson 2373830d077SBjorn Andersson const struct qmi_msg_handler *handlers; 2383830d077SBjorn Andersson }; 2393830d077SBjorn Andersson 2403830d077SBjorn Andersson int qmi_add_lookup(struct qmi_handle *qmi, unsigned int service, 2413830d077SBjorn Andersson unsigned int version, unsigned int instance); 2423830d077SBjorn Andersson int qmi_add_server(struct qmi_handle *qmi, unsigned int service, 2433830d077SBjorn Andersson unsigned int version, unsigned int instance); 2443830d077SBjorn Andersson 2453830d077SBjorn Andersson int qmi_handle_init(struct qmi_handle *qmi, size_t max_msg_len, 2463830d077SBjorn Andersson const struct qmi_ops *ops, 2473830d077SBjorn Andersson const struct qmi_msg_handler *handlers); 2483830d077SBjorn Andersson void qmi_handle_release(struct qmi_handle *qmi); 2493830d077SBjorn Andersson 2503830d077SBjorn Andersson ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 2513830d077SBjorn Andersson struct qmi_txn *txn, int msg_id, size_t len, 252*ff6d3658SJeff Johnson const struct qmi_elem_info *ei, const void *c_struct); 2533830d077SBjorn Andersson ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 2543830d077SBjorn Andersson struct qmi_txn *txn, int msg_id, size_t len, 255*ff6d3658SJeff Johnson const struct qmi_elem_info *ei, const void *c_struct); 2563830d077SBjorn Andersson ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 257*ff6d3658SJeff Johnson int msg_id, size_t len, const struct qmi_elem_info *ei, 2583830d077SBjorn Andersson const void *c_struct); 2593830d077SBjorn Andersson 2609b8a11e8SBjorn Andersson void *qmi_encode_message(int type, unsigned int msg_id, size_t *len, 261*ff6d3658SJeff Johnson unsigned int txn_id, const struct qmi_elem_info *ei, 2629b8a11e8SBjorn Andersson const void *c_struct); 2639b8a11e8SBjorn Andersson 2649b8a11e8SBjorn Andersson int qmi_decode_message(const void *buf, size_t len, 265*ff6d3658SJeff Johnson const struct qmi_elem_info *ei, void *c_struct); 2669b8a11e8SBjorn Andersson 2673830d077SBjorn Andersson int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, 268*ff6d3658SJeff Johnson const struct qmi_elem_info *ei, void *c_struct); 2693830d077SBjorn Andersson int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout); 2703830d077SBjorn Andersson void qmi_txn_cancel(struct qmi_txn *txn); 2713830d077SBjorn Andersson 2729b8a11e8SBjorn Andersson #endif 273