Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.3 271 lines 7.9 kB view raw
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 * 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_INCOMPATIBLE_STATE_V01 90 92#define QMI_ERR_NOT_SUPPORTED_V01 94 93 94/** 95 * qmi_response_type_v01 - common response header (decoded) 96 * @result: result of the transaction 97 * @error: error value, when @result is QMI_RESULT_FAILURE_V01 98 */ 99struct qmi_response_type_v01 { 100 u16 result; 101 u16 error; 102}; 103 104extern struct qmi_elem_info qmi_response_type_v01_ei[]; 105 106/** 107 * struct qmi_service - context to track lookup-results 108 * @service: service type 109 * @version: version of the @service 110 * @instance: instance id of the @service 111 * @node: node of the service 112 * @port: port of the service 113 * @priv: handle for client's use 114 * @list_node: list_head for house keeping 115 */ 116struct qmi_service { 117 unsigned int service; 118 unsigned int version; 119 unsigned int instance; 120 121 unsigned int node; 122 unsigned int port; 123 124 void *priv; 125 struct list_head list_node; 126}; 127 128struct qmi_handle; 129 130/** 131 * struct qmi_ops - callbacks for qmi_handle 132 * @new_server: inform client of a new_server lookup-result, returning 133 * successfully from this call causes the library to call 134 * @del_server as the service is removed from the 135 * lookup-result. @priv of the qmi_service can be used by 136 * the client 137 * @del_server: inform client of a del_server lookup-result 138 * @net_reset: inform client that the name service was restarted and 139 * that and any state needs to be released 140 * @msg_handler: invoked for incoming messages, allows a client to 141 * override the usual QMI message handler 142 * @bye: inform a client that all clients from a node are gone 143 * @del_client: inform a client that a particular client is gone 144 */ 145struct qmi_ops { 146 int (*new_server)(struct qmi_handle *qmi, struct qmi_service *svc); 147 void (*del_server)(struct qmi_handle *qmi, struct qmi_service *svc); 148 void (*net_reset)(struct qmi_handle *qmi); 149 void (*msg_handler)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 150 const void *data, size_t count); 151 void (*bye)(struct qmi_handle *qmi, unsigned int node); 152 void (*del_client)(struct qmi_handle *qmi, 153 unsigned int node, unsigned int port); 154}; 155 156/** 157 * struct qmi_txn - transaction context 158 * @qmi: QMI handle this transaction is associated with 159 * @id: transaction id 160 * @lock: for synchronization between handler and waiter of messages 161 * @completion: completion object as the transaction receives a response 162 * @result: result code for the completed transaction 163 * @ei: description of the QMI encoded response (optional) 164 * @dest: destination buffer to decode message into (optional) 165 */ 166struct qmi_txn { 167 struct qmi_handle *qmi; 168 169 u16 id; 170 171 struct mutex lock; 172 struct completion completion; 173 int result; 174 175 struct qmi_elem_info *ei; 176 void *dest; 177}; 178 179/** 180 * struct qmi_msg_handler - description of QMI message handler 181 * @type: type of message 182 * @msg_id: message id 183 * @ei: description of the QMI encoded message 184 * @decoded_size: size of the decoded object 185 * @fn: function to invoke as the message is decoded 186 */ 187struct qmi_msg_handler { 188 unsigned int type; 189 unsigned int msg_id; 190 191 struct qmi_elem_info *ei; 192 193 size_t decoded_size; 194 void (*fn)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 195 struct qmi_txn *txn, const void *decoded); 196}; 197 198/** 199 * struct qmi_handle - QMI context 200 * @sock: socket handle 201 * @sock_lock: synchronization of @sock modifications 202 * @sq: sockaddr of @sock 203 * @work: work for handling incoming messages 204 * @wq: workqueue to post @work on 205 * @recv_buf: scratch buffer for handling incoming messages 206 * @recv_buf_size: size of @recv_buf 207 * @lookups: list of registered lookup requests 208 * @lookup_results: list of lookup-results advertised to the client 209 * @services: list of registered services (by this client) 210 * @ops: reference to callbacks 211 * @txns: outstanding transactions 212 * @txn_lock: lock for modifications of @txns 213 * @handlers: list of handlers for incoming messages 214 */ 215struct qmi_handle { 216 struct socket *sock; 217 struct mutex sock_lock; 218 219 struct sockaddr_qrtr sq; 220 221 struct work_struct work; 222 struct workqueue_struct *wq; 223 224 void *recv_buf; 225 size_t recv_buf_size; 226 227 struct list_head lookups; 228 struct list_head lookup_results; 229 struct list_head services; 230 231 struct qmi_ops ops; 232 233 struct idr txns; 234 struct mutex txn_lock; 235 236 const struct qmi_msg_handler *handlers; 237}; 238 239int qmi_add_lookup(struct qmi_handle *qmi, unsigned int service, 240 unsigned int version, unsigned int instance); 241int qmi_add_server(struct qmi_handle *qmi, unsigned int service, 242 unsigned int version, unsigned int instance); 243 244int qmi_handle_init(struct qmi_handle *qmi, size_t max_msg_len, 245 const struct qmi_ops *ops, 246 const struct qmi_msg_handler *handlers); 247void qmi_handle_release(struct qmi_handle *qmi); 248 249ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 250 struct qmi_txn *txn, int msg_id, size_t len, 251 struct qmi_elem_info *ei, const void *c_struct); 252ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 253 struct qmi_txn *txn, int msg_id, size_t len, 254 struct qmi_elem_info *ei, const void *c_struct); 255ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq, 256 int msg_id, size_t len, struct qmi_elem_info *ei, 257 const void *c_struct); 258 259void *qmi_encode_message(int type, unsigned int msg_id, size_t *len, 260 unsigned int txn_id, struct qmi_elem_info *ei, 261 const void *c_struct); 262 263int qmi_decode_message(const void *buf, size_t len, 264 struct qmi_elem_info *ei, void *c_struct); 265 266int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn, 267 struct qmi_elem_info *ei, void *c_struct); 268int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout); 269void qmi_txn_cancel(struct qmi_txn *txn); 270 271#endif