qmi.h (7978B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. 4 * Copyright (c) 2017, Linaro Ltd. 5 */ 6#ifndef __QMI_HELPERS_H__ 7#define __QMI_HELPERS_H__ 8 9#include <linux/completion.h> 10#include <linux/idr.h> 11#include <linux/list.h> 12#include <linux/qrtr.h> 13#include <linux/types.h> 14#include <linux/workqueue.h> 15 16struct socket; 17 18/** 19 * struct qmi_header - wireformat header of QMI messages 20 * @type: type of message 21 * @txn_id: transaction id 22 * @msg_id: message id 23 * @msg_len: length of message payload following header 24 */ 25struct qmi_header { 26 u8 type; 27 u16 txn_id; 28 u16 msg_id; 29 u16 msg_len; 30} __packed; 31 32#define QMI_REQUEST 0 33#define QMI_RESPONSE 2 34#define QMI_INDICATION 4 35 36#define QMI_COMMON_TLV_TYPE 0 37 38enum qmi_elem_type { 39 QMI_EOTI, 40 QMI_OPT_FLAG, 41 QMI_DATA_LEN, 42 QMI_UNSIGNED_1_BYTE, 43 QMI_UNSIGNED_2_BYTE, 44 QMI_UNSIGNED_4_BYTE, 45 QMI_UNSIGNED_8_BYTE, 46 QMI_SIGNED_2_BYTE_ENUM, 47 QMI_SIGNED_4_BYTE_ENUM, 48 QMI_STRUCT, 49 QMI_STRING, 50}; 51 52enum qmi_array_type { 53 NO_ARRAY, 54 STATIC_ARRAY, 55 VAR_LEN_ARRAY, 56}; 57 58/** 59 * struct qmi_elem_info - describes how to encode a single QMI element 60 * @data_type: Data type of this element. 61 * @elem_len: Array length of this element, if an array. 62 * @elem_size: Size of a single instance of this data type. 63 * @array_type: Array type of this element. 64 * @tlv_type: QMI message specific type to identify which element 65 * is present in an incoming message. 66 * @offset: Specifies the offset of the first instance of this 67 * element in the data structure. 68 * @ei_array: Null-terminated array of @qmi_elem_info to describe nested 69 * structures. 70 */ 71struct qmi_elem_info { 72 enum qmi_elem_type data_type; 73 u32 elem_len; 74 u32 elem_size; 75 enum qmi_array_type array_type; 76 u8 tlv_type; 77 u32 offset; 78 struct qmi_elem_info *ei_array; 79}; 80 81#define QMI_RESULT_SUCCESS_V01 0 82#define QMI_RESULT_FAILURE_V01 1 83 84#define QMI_ERR_NONE_V01 0 85#define QMI_ERR_MALFORMED_MSG_V01 1 86#define QMI_ERR_NO_MEMORY_V01 2 87#define QMI_ERR_INTERNAL_V01 3 88#define QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 5 89#define QMI_ERR_INVALID_ID_V01 41 90#define QMI_ERR_ENCODING_V01 58 91#define QMI_ERR_DISABLED_V01 69 92#define QMI_ERR_INCOMPATIBLE_STATE_V01 90 93#define QMI_ERR_NOT_SUPPORTED_V01 94 94 95/** 96 * struct qmi_response_type_v01 - common response header (decoded) 97 * @result: result of the transaction 98 * @error: error value, when @result is QMI_RESULT_FAILURE_V01 99 */ 100struct qmi_response_type_v01 { 101 u16 result; 102 u16 error; 103}; 104 105extern struct qmi_elem_info qmi_response_type_v01_ei[]; 106 107/** 108 * struct qmi_service - context to track lookup-results 109 * @service: service type 110 * @version: version of the @service 111 * @instance: instance id of the @service 112 * @node: node of the service 113 * @port: port of the service 114 * @priv: handle for client's use 115 * @list_node: list_head for house keeping 116 */ 117struct qmi_service { 118 unsigned int service; 119 unsigned int version; 120 unsigned int instance; 121 122 unsigned int node; 123 unsigned int port; 124 125 void *priv; 126 struct list_head list_node; 127}; 128 129struct qmi_handle; 130 131/** 132 * struct qmi_ops - callbacks for qmi_handle 133 * @new_server: inform client of a new_server lookup-result, returning 134 * successfully from this call causes the library to call 135 * @del_server as the service is removed from the 136 * lookup-result. @priv of the qmi_service can be used by 137 * the client 138 * @del_server: inform client of a del_server lookup-result 139 * @net_reset: inform client that the name service was restarted and 140 * that and any state needs to be released 141 * @msg_handler: invoked for incoming messages, allows a client to 142 * override the usual QMI message handler 143 * @bye: inform a client that all clients from a node are gone 144 * @del_client: inform a client that a particular client is gone 145 */ 146struct qmi_ops { 147 int (*new_server)(struct qmi_handle *qmi, struct qmi_service *svc); 148 void (*del_server)(struct qmi_handle *qmi, struct qmi_service *svc); 149 void (*net_reset)(struct qmi_handle *qmi); 150 void (*msg_handler)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 151 const void *data, size_t count); 152 void (*bye)(struct qmi_handle *qmi, unsigned int node); 153 void (*del_client)(struct qmi_handle *qmi, 154 unsigned int node, unsigned int port); 155}; 156 157/** 158 * struct qmi_txn - transaction context 159 * @qmi: QMI handle this transaction is associated with 160 * @id: transaction id 161 * @lock: for synchronization between handler and waiter of messages 162 * @completion: completion object as the transaction receives a response 163 * @result: result code for the completed transaction 164 * @ei: description of the QMI encoded response (optional) 165 * @dest: destination buffer to decode message into (optional) 166 */ 167struct qmi_txn { 168 struct qmi_handle *qmi; 169 170 u16 id; 171 172 struct mutex lock; 173 struct completion completion; 174 int result; 175 176 struct qmi_elem_info *ei; 177 void *dest; 178}; 179 180/** 181 * struct qmi_msg_handler - description of QMI message handler 182 * @type: type of message 183 * @msg_id: message id 184 * @ei: description of the QMI encoded message 185 * @decoded_size: size of the decoded object 186 * @fn: function to invoke as the message is decoded 187 */ 188struct qmi_msg_handler { 189 unsigned int type; 190 unsigned int msg_id; 191 192 struct qmi_elem_info *ei; 193 194 size_t decoded_size; 195 void (*fn)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 196 struct qmi_txn *txn, const void *decoded); 197}; 198 199/** 200 * struct qmi_handle - QMI context 201 * @sock: socket handle 202 * @sock_lock: synchronization of @sock modifications 203 * @sq: sockaddr of @sock 204 * @work: work for handling incoming messages 205 * @wq: workqueue to post @work on 206 * @recv_buf: scratch buffer for handling incoming messages 207 * @recv_buf_size: size of @recv_buf 208 * @lookups: list of registered lookup requests 209 * @lookup_results: list of lookup-results advertised to the client 210 * @services: list of registered services (by this client) 211 * @ops: reference to callbacks 212 * @txns: outstanding transactions 213 * @txn_lock: lock for modifications of @txns 214 * @handlers: list of handlers for incoming messages 215 */ 216struct qmi_handle { 217 struct socket *sock; 218 struct mutex sock_lock; 219 220 struct sockaddr_qrtr sq; 221 222 struct work_struct work; 223 struct workqueue_struct *wq; 224 225 void *recv_buf; 226 size_t recv_buf_size; 227 228 struct list_head lookups; 229 struct list_head lookup_results; 230 struct list_head services; 231 232 struct qmi_ops ops; 233 234 struct idr txns; 235 struct mutex txn_lock; 236 237 const struct qmi_msg_handler *handlers; 238}; 239 240int qmi_add_lookup(struct qmi_handle *qmi, unsigned int service, 241 unsigned int version, unsigned int instance); 242int qmi_add_server(struct qmi_handle *qmi, unsigned int service, 243 unsigned int version, unsigned int instance); 244 245int qmi_handle_init(struct qmi_handle *qmi, size_t max_msg_len, 246 const struct qmi_ops *ops, 247 const struct qmi_msg_handler *handlers); 248void qmi_handle_release(struct qmi_handle *qmi); 249 250ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 251 struct qmi_txn *txn, int msg_id, size_t len, 252 struct qmi_elem_info *ei, const void *c_struct); 253ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 254 struct qmi_txn *txn, int msg_id, size_t len, 255 struct qmi_elem_info *ei, const void *c_struct); 256ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 257 int msg_id, size_t len, struct qmi_elem_info *ei, 258 const void *c_struct); 259 260void *qmi_encode_message(int type, unsigned int msg_id, size_t *len, 261 unsigned int txn_id, struct qmi_elem_info *ei, 262 const void *c_struct); 263 264int qmi_decode_message(const void *buf, size_t len, 265 struct qmi_elem_info *ei, void *c_struct); 266 267int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, 268 struct qmi_elem_info *ei, void *c_struct); 269int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout); 270void qmi_txn_cancel(struct qmi_txn *txn); 271 272#endif