xref: /openbmc/linux/include/linux/soc/qcom/qmi.h (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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