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 16 struct 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 */ 25 struct 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 38 enum 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 52 enum 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 */ 71 struct 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 const 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 */ 100 struct qmi_response_type_v01 { 101 u16 result; 102 u16 error; 103 }; 104 105 extern const 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 */ 117 struct 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 129 struct 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 */ 146 struct 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 */ 167 struct 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 const 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 */ 188 struct qmi_msg_handler { 189 unsigned int type; 190 unsigned int msg_id; 191 192 const 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 */ 216 struct 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 240 int qmi_add_lookup(struct qmi_handle *qmi, unsigned int service, 241 unsigned int version, unsigned int instance); 242 int qmi_add_server(struct qmi_handle *qmi, unsigned int service, 243 unsigned int version, unsigned int instance); 244 245 int 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); 248 void qmi_handle_release(struct qmi_handle *qmi); 249 250 ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 251 struct qmi_txn *txn, int msg_id, size_t len, 252 const struct qmi_elem_info *ei, const void *c_struct); 253 ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 254 struct qmi_txn *txn, int msg_id, size_t len, 255 const struct qmi_elem_info *ei, const void *c_struct); 256 ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 257 int msg_id, size_t len, const struct qmi_elem_info *ei, 258 const void *c_struct); 259 260 void *qmi_encode_message(int type, unsigned int msg_id, size_t *len, 261 unsigned int txn_id, const struct qmi_elem_info *ei, 262 const void *c_struct); 263 264 int qmi_decode_message(const void *buf, size_t len, 265 const struct qmi_elem_info *ei, void *c_struct); 266 267 int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, 268 const struct qmi_elem_info *ei, void *c_struct); 269 int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout); 270 void qmi_txn_cancel(struct qmi_txn *txn); 271 272 #endif 273