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 { |
26 | u8 ; |
27 | u16 ; |
28 | u16 ; |
29 | u16 ; |
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 | |