1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2017 Linaro Ltd.
6 #include <linux/slab.h>
7 #include <linux/uaccess.h>
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/string.h>
12 #include <linux/soc/qcom/qmi.h>
14 #define QMI_ENCDEC_ENCODE_TLV(type, length, p_dst) do { \
16 *p_dst++ = ((u8)((length) & 0xFF)); \
17 *p_dst++ = ((u8)(((length) >> 8) & 0xFF)); \
20 #define QMI_ENCDEC_DECODE_TLV(p_type, p_length, p_src) do { \
21 *p_type = (u8)*p_src++; \
22 *p_length = (u8)*p_src++; \
23 *p_length |= ((u8)*p_src) << 8; \
26 #define QMI_ENCDEC_ENCODE_N_BYTES(p_dst, p_src, size) \
28 memcpy(p_dst, p_src, size); \
29 p_dst = (u8 *)p_dst + size; \
30 p_src = (u8 *)p_src + size; \
33 #define QMI_ENCDEC_DECODE_N_BYTES(p_dst, p_src, size) \
35 memcpy(p_dst, p_src, size); \
36 p_dst = (u8 *)p_dst + size; \
37 p_src = (u8 *)p_src + size; \
40 #define UPDATE_ENCODE_VARIABLES(temp_si, buf_dst, \
41 encoded_bytes, tlv_len, encode_tlv, rc) \
43 buf_dst = (u8 *)buf_dst + rc; \
44 encoded_bytes += rc; \
46 temp_si = temp_si + 1; \
50 #define UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc) \
52 buf_src = (u8 *)buf_src + rc; \
53 decoded_bytes += rc; \
56 #define TLV_LEN_SIZE sizeof(u16)
57 #define TLV_TYPE_SIZE sizeof(u8)
58 #define OPTIONAL_TLV_TYPE_START 0x10
60 static int qmi_encode(struct qmi_elem_info
*ei_array
, void *out_buf
,
61 const void *in_c_struct
, u32 out_buf_len
,
64 static int qmi_decode(struct qmi_elem_info
*ei_array
, void *out_c_struct
,
65 const void *in_buf
, u32 in_buf_len
, int dec_level
);
68 * skip_to_next_elem() - Skip to next element in the structure to be encoded
69 * @ei_array: Struct info describing the element to be skipped.
70 * @level: Depth level of encoding/decoding to identify nested structures.
72 * This function is used while encoding optional elements. If the flag
73 * corresponding to an optional element is not set, then encoding the
74 * optional element can be skipped. This function can be used to perform
77 * Return: struct info of the next element that can be encoded.
79 static struct qmi_elem_info
*skip_to_next_elem(struct qmi_elem_info
*ei_array
,
82 struct qmi_elem_info
*temp_ei
= ei_array
;
86 temp_ei
= temp_ei
+ 1;
89 tlv_type
= temp_ei
->tlv_type
;
90 temp_ei
= temp_ei
+ 1;
91 } while (tlv_type
== temp_ei
->tlv_type
);
98 * qmi_calc_min_msg_len() - Calculate the minimum length of a QMI message
99 * @ei_array: Struct info array describing the structure.
100 * @level: Level to identify the depth of the nested structures.
102 * Return: Expected minimum length of the QMI message or 0 on error.
104 static int qmi_calc_min_msg_len(struct qmi_elem_info
*ei_array
,
108 struct qmi_elem_info
*temp_ei
= ei_array
;
113 while (temp_ei
->data_type
!= QMI_EOTI
) {
114 /* Optional elements do not count in minimum length */
115 if (temp_ei
->data_type
== QMI_OPT_FLAG
) {
116 temp_ei
= skip_to_next_elem(temp_ei
, level
);
120 if (temp_ei
->data_type
== QMI_DATA_LEN
) {
121 min_msg_len
+= (temp_ei
->elem_size
== sizeof(u8
) ?
122 sizeof(u8
) : sizeof(u16
));
125 } else if (temp_ei
->data_type
== QMI_STRUCT
) {
126 min_msg_len
+= qmi_calc_min_msg_len(temp_ei
->ei_array
,
129 } else if (temp_ei
->data_type
== QMI_STRING
) {
131 min_msg_len
+= temp_ei
->elem_len
<= U8_MAX
?
132 sizeof(u8
) : sizeof(u16
);
133 min_msg_len
+= temp_ei
->elem_len
* temp_ei
->elem_size
;
136 min_msg_len
+= (temp_ei
->elem_len
* temp_ei
->elem_size
);
141 * Type & Length info. not prepended for elements in the
145 min_msg_len
+= (TLV_TYPE_SIZE
+ TLV_LEN_SIZE
);
152 * qmi_encode_basic_elem() - Encodes elements of basic/primary data type
153 * @buf_dst: Buffer to store the encoded information.
154 * @buf_src: Buffer containing the elements to be encoded.
155 * @elem_len: Number of elements, in the buf_src, to be encoded.
156 * @elem_size: Size of a single instance of the element to be encoded.
158 * This function encodes the "elem_len" number of data elements, each of
159 * size "elem_size" bytes from the source buffer "buf_src" and stores the
160 * encoded information in the destination buffer "buf_dst". The elements are
161 * of primary data type which include u8 - u64 or similar. This
162 * function returns the number of bytes of encoded information.
164 * Return: The number of bytes of encoded information.
166 static int qmi_encode_basic_elem(void *buf_dst
, const void *buf_src
,
167 u32 elem_len
, u32 elem_size
)
171 for (i
= 0; i
< elem_len
; i
++) {
172 QMI_ENCDEC_ENCODE_N_BYTES(buf_dst
, buf_src
, elem_size
);
180 * qmi_encode_struct_elem() - Encodes elements of struct data type
181 * @ei_array: Struct info array descibing the struct element.
182 * @buf_dst: Buffer to store the encoded information.
183 * @buf_src: Buffer containing the elements to be encoded.
184 * @elem_len: Number of elements, in the buf_src, to be encoded.
185 * @out_buf_len: Available space in the encode buffer.
186 * @enc_level: Depth of the nested structure from the main structure.
188 * This function encodes the "elem_len" number of struct elements, each of
189 * size "ei_array->elem_size" bytes from the source buffer "buf_src" and
190 * stores the encoded information in the destination buffer "buf_dst". The
191 * elements are of struct data type which includes any C structure. This
192 * function returns the number of bytes of encoded information.
194 * Return: The number of bytes of encoded information on success or negative
197 static int qmi_encode_struct_elem(struct qmi_elem_info
*ei_array
,
198 void *buf_dst
, const void *buf_src
,
199 u32 elem_len
, u32 out_buf_len
,
202 int i
, rc
, encoded_bytes
= 0;
203 struct qmi_elem_info
*temp_ei
= ei_array
;
205 for (i
= 0; i
< elem_len
; i
++) {
206 rc
= qmi_encode(temp_ei
->ei_array
, buf_dst
, buf_src
,
207 out_buf_len
- encoded_bytes
, enc_level
);
209 pr_err("%s: STRUCT Encode failure\n", __func__
);
212 buf_dst
= buf_dst
+ rc
;
213 buf_src
= buf_src
+ temp_ei
->elem_size
;
217 return encoded_bytes
;
221 * qmi_encode_string_elem() - Encodes elements of string data type
222 * @ei_array: Struct info array descibing the string element.
223 * @buf_dst: Buffer to store the encoded information.
224 * @buf_src: Buffer containing the elements to be encoded.
225 * @out_buf_len: Available space in the encode buffer.
226 * @enc_level: Depth of the string element from the main structure.
228 * This function encodes a string element of maximum length "ei_array->elem_len"
229 * bytes from the source buffer "buf_src" and stores the encoded information in
230 * the destination buffer "buf_dst". This function returns the number of bytes
231 * of encoded information.
233 * Return: The number of bytes of encoded information on success or negative
236 static int qmi_encode_string_elem(struct qmi_elem_info
*ei_array
,
237 void *buf_dst
, const void *buf_src
,
238 u32 out_buf_len
, int enc_level
)
241 int encoded_bytes
= 0;
242 struct qmi_elem_info
*temp_ei
= ei_array
;
244 u32 string_len_sz
= 0;
246 string_len
= strlen(buf_src
);
247 string_len_sz
= temp_ei
->elem_len
<= U8_MAX
?
248 sizeof(u8
) : sizeof(u16
);
249 if (string_len
> temp_ei
->elem_len
) {
250 pr_err("%s: String to be encoded is longer - %d > %d\n",
251 __func__
, string_len
, temp_ei
->elem_len
);
255 if (enc_level
== 1) {
256 if (string_len
+ TLV_LEN_SIZE
+ TLV_TYPE_SIZE
>
258 pr_err("%s: Output len %d > Out Buf len %d\n",
259 __func__
, string_len
, out_buf_len
);
263 if (string_len
+ string_len_sz
> out_buf_len
) {
264 pr_err("%s: Output len %d > Out Buf len %d\n",
265 __func__
, string_len
, out_buf_len
);
268 rc
= qmi_encode_basic_elem(buf_dst
, &string_len
,
273 rc
= qmi_encode_basic_elem(buf_dst
+ encoded_bytes
, buf_src
,
274 string_len
, temp_ei
->elem_size
);
277 return encoded_bytes
;
281 * qmi_encode() - Core Encode Function
282 * @ei_array: Struct info array describing the structure to be encoded.
283 * @out_buf: Buffer to hold the encoded QMI message.
284 * @in_c_struct: Pointer to the C structure to be encoded.
285 * @out_buf_len: Available space in the encode buffer.
286 * @enc_level: Encode level to indicate the depth of the nested structure,
287 * within the main structure, being encoded.
289 * Return: The number of bytes of encoded information on success or negative
292 static int qmi_encode(struct qmi_elem_info
*ei_array
, void *out_buf
,
293 const void *in_c_struct
, u32 out_buf_len
,
296 struct qmi_elem_info
*temp_ei
= ei_array
;
297 u8 opt_flag_value
= 0;
298 u32 data_len_value
= 0, data_len_sz
;
299 u8
*buf_dst
= (u8
*)out_buf
;
303 u32 encoded_bytes
= 0;
311 tlv_pointer
= buf_dst
;
314 buf_dst
= buf_dst
+ (TLV_LEN_SIZE
+ TLV_TYPE_SIZE
);
316 while (temp_ei
->data_type
!= QMI_EOTI
) {
317 buf_src
= in_c_struct
+ temp_ei
->offset
;
318 tlv_type
= temp_ei
->tlv_type
;
320 if (temp_ei
->array_type
== NO_ARRAY
) {
322 } else if (temp_ei
->array_type
== STATIC_ARRAY
) {
323 data_len_value
= temp_ei
->elem_len
;
324 } else if (data_len_value
<= 0 ||
325 temp_ei
->elem_len
< data_len_value
) {
326 pr_err("%s: Invalid data length\n", __func__
);
330 switch (temp_ei
->data_type
) {
332 rc
= qmi_encode_basic_elem(&opt_flag_value
, buf_src
,
335 temp_ei
= temp_ei
+ 1;
337 temp_ei
= skip_to_next_elem(temp_ei
, enc_level
);
341 memcpy(&data_len_value
, buf_src
, temp_ei
->elem_size
);
342 data_len_sz
= temp_ei
->elem_size
== sizeof(u8
) ?
343 sizeof(u8
) : sizeof(u16
);
344 /* Check to avoid out of range buffer access */
345 if ((data_len_sz
+ encoded_bytes
+ TLV_LEN_SIZE
+
346 TLV_TYPE_SIZE
) > out_buf_len
) {
347 pr_err("%s: Too Small Buffer @DATA_LEN\n",
351 rc
= qmi_encode_basic_elem(buf_dst
, &data_len_value
,
353 UPDATE_ENCODE_VARIABLES(temp_ei
, buf_dst
,
354 encoded_bytes
, tlv_len
,
357 temp_ei
= skip_to_next_elem(temp_ei
, enc_level
);
362 case QMI_UNSIGNED_1_BYTE
:
363 case QMI_UNSIGNED_2_BYTE
:
364 case QMI_UNSIGNED_4_BYTE
:
365 case QMI_UNSIGNED_8_BYTE
:
366 case QMI_SIGNED_2_BYTE_ENUM
:
367 case QMI_SIGNED_4_BYTE_ENUM
:
368 /* Check to avoid out of range buffer access */
369 if (((data_len_value
* temp_ei
->elem_size
) +
370 encoded_bytes
+ TLV_LEN_SIZE
+ TLV_TYPE_SIZE
) >
372 pr_err("%s: Too Small Buffer @data_type:%d\n",
373 __func__
, temp_ei
->data_type
);
376 rc
= qmi_encode_basic_elem(buf_dst
, buf_src
,
379 UPDATE_ENCODE_VARIABLES(temp_ei
, buf_dst
,
380 encoded_bytes
, tlv_len
,
385 rc
= qmi_encode_struct_elem(temp_ei
, buf_dst
, buf_src
,
387 out_buf_len
- encoded_bytes
,
391 UPDATE_ENCODE_VARIABLES(temp_ei
, buf_dst
,
392 encoded_bytes
, tlv_len
,
397 rc
= qmi_encode_string_elem(temp_ei
, buf_dst
, buf_src
,
398 out_buf_len
- encoded_bytes
,
402 UPDATE_ENCODE_VARIABLES(temp_ei
, buf_dst
,
403 encoded_bytes
, tlv_len
,
407 pr_err("%s: Unrecognized data type\n", __func__
);
411 if (encode_tlv
&& enc_level
== 1) {
412 QMI_ENCDEC_ENCODE_TLV(tlv_type
, tlv_len
, tlv_pointer
);
413 encoded_bytes
+= (TLV_TYPE_SIZE
+ TLV_LEN_SIZE
);
414 tlv_pointer
= buf_dst
;
416 buf_dst
= buf_dst
+ TLV_LEN_SIZE
+ TLV_TYPE_SIZE
;
421 return encoded_bytes
;
425 * qmi_decode_basic_elem() - Decodes elements of basic/primary data type
426 * @buf_dst: Buffer to store the decoded element.
427 * @buf_src: Buffer containing the elements in QMI wire format.
428 * @elem_len: Number of elements to be decoded.
429 * @elem_size: Size of a single instance of the element to be decoded.
431 * This function decodes the "elem_len" number of elements in QMI wire format,
432 * each of size "elem_size" bytes from the source buffer "buf_src" and stores
433 * the decoded elements in the destination buffer "buf_dst". The elements are
434 * of primary data type which include u8 - u64 or similar. This
435 * function returns the number of bytes of decoded information.
437 * Return: The total size of the decoded data elements, in bytes.
439 static int qmi_decode_basic_elem(void *buf_dst
, const void *buf_src
,
440 u32 elem_len
, u32 elem_size
)
444 for (i
= 0; i
< elem_len
; i
++) {
445 QMI_ENCDEC_DECODE_N_BYTES(buf_dst
, buf_src
, elem_size
);
453 * qmi_decode_struct_elem() - Decodes elements of struct data type
454 * @ei_array: Struct info array descibing the struct element.
455 * @buf_dst: Buffer to store the decoded element.
456 * @buf_src: Buffer containing the elements in QMI wire format.
457 * @elem_len: Number of elements to be decoded.
458 * @tlv_len: Total size of the encoded inforation corresponding to
459 * this struct element.
460 * @dec_level: Depth of the nested structure from the main structure.
462 * This function decodes the "elem_len" number of elements in QMI wire format,
463 * each of size "(tlv_len/elem_len)" bytes from the source buffer "buf_src"
464 * and stores the decoded elements in the destination buffer "buf_dst". The
465 * elements are of struct data type which includes any C structure. This
466 * function returns the number of bytes of decoded information.
468 * Return: The total size of the decoded data elements on success, negative
471 static int qmi_decode_struct_elem(struct qmi_elem_info
*ei_array
,
472 void *buf_dst
, const void *buf_src
,
473 u32 elem_len
, u32 tlv_len
,
476 int i
, rc
, decoded_bytes
= 0;
477 struct qmi_elem_info
*temp_ei
= ei_array
;
479 for (i
= 0; i
< elem_len
&& decoded_bytes
< tlv_len
; i
++) {
480 rc
= qmi_decode(temp_ei
->ei_array
, buf_dst
, buf_src
,
481 tlv_len
- decoded_bytes
, dec_level
);
484 buf_src
= buf_src
+ rc
;
485 buf_dst
= buf_dst
+ temp_ei
->elem_size
;
489 if ((dec_level
<= 2 && decoded_bytes
!= tlv_len
) ||
490 (dec_level
> 2 && (i
< elem_len
|| decoded_bytes
> tlv_len
))) {
491 pr_err("%s: Fault in decoding: dl(%d), db(%d), tl(%d), i(%d), el(%d)\n",
492 __func__
, dec_level
, decoded_bytes
, tlv_len
,
497 return decoded_bytes
;
501 * qmi_decode_string_elem() - Decodes elements of string data type
502 * @ei_array: Struct info array descibing the string element.
503 * @buf_dst: Buffer to store the decoded element.
504 * @buf_src: Buffer containing the elements in QMI wire format.
505 * @tlv_len: Total size of the encoded inforation corresponding to
506 * this string element.
507 * @dec_level: Depth of the string element from the main structure.
509 * This function decodes the string element of maximum length
510 * "ei_array->elem_len" from the source buffer "buf_src" and puts it into
511 * the destination buffer "buf_dst". This function returns number of bytes
512 * decoded from the input buffer.
514 * Return: The total size of the decoded data elements on success, negative
517 static int qmi_decode_string_elem(struct qmi_elem_info
*ei_array
,
518 void *buf_dst
, const void *buf_src
,
519 u32 tlv_len
, int dec_level
)
522 int decoded_bytes
= 0;
524 u32 string_len_sz
= 0;
525 struct qmi_elem_info
*temp_ei
= ei_array
;
527 if (dec_level
== 1) {
528 string_len
= tlv_len
;
530 string_len_sz
= temp_ei
->elem_len
<= U8_MAX
?
531 sizeof(u8
) : sizeof(u16
);
532 rc
= qmi_decode_basic_elem(&string_len
, buf_src
,
537 if (string_len
> temp_ei
->elem_len
) {
538 pr_err("%s: String len %d > Max Len %d\n",
539 __func__
, string_len
, temp_ei
->elem_len
);
541 } else if (string_len
> tlv_len
) {
542 pr_err("%s: String len %d > Input Buffer Len %d\n",
543 __func__
, string_len
, tlv_len
);
547 rc
= qmi_decode_basic_elem(buf_dst
, buf_src
+ decoded_bytes
,
548 string_len
, temp_ei
->elem_size
);
549 *((char *)buf_dst
+ string_len
) = '\0';
552 return decoded_bytes
;
556 * find_ei() - Find element info corresponding to TLV Type
557 * @ei_array: Struct info array of the message being decoded.
558 * @type: TLV Type of the element being searched.
560 * Every element that got encoded in the QMI message will have a type
561 * information associated with it. While decoding the QMI message,
562 * this function is used to find the struct info regarding the element
563 * that corresponds to the type being decoded.
565 * Return: Pointer to struct info, if found
567 static struct qmi_elem_info
*find_ei(struct qmi_elem_info
*ei_array
,
570 struct qmi_elem_info
*temp_ei
= ei_array
;
572 while (temp_ei
->data_type
!= QMI_EOTI
) {
573 if (temp_ei
->tlv_type
== (u8
)type
)
575 temp_ei
= temp_ei
+ 1;
582 * qmi_decode() - Core Decode Function
583 * @ei_array: Struct info array describing the structure to be decoded.
584 * @out_c_struct: Buffer to hold the decoded C struct
585 * @in_buf: Buffer containing the QMI message to be decoded
586 * @in_buf_len: Length of the QMI message to be decoded
587 * @dec_level: Decode level to indicate the depth of the nested structure,
588 * within the main structure, being decoded
590 * Return: The number of bytes of decoded information on success, negative
593 static int qmi_decode(struct qmi_elem_info
*ei_array
, void *out_c_struct
,
594 const void *in_buf
, u32 in_buf_len
,
597 struct qmi_elem_info
*temp_ei
= ei_array
;
598 u8 opt_flag_value
= 1;
599 u32 data_len_value
= 0, data_len_sz
= 0;
600 u8
*buf_dst
= out_c_struct
;
601 const u8
*tlv_pointer
;
604 u32 decoded_bytes
= 0;
605 const void *buf_src
= in_buf
;
608 while (decoded_bytes
< in_buf_len
) {
609 if (dec_level
>= 2 && temp_ei
->data_type
== QMI_EOTI
)
610 return decoded_bytes
;
612 if (dec_level
== 1) {
613 tlv_pointer
= buf_src
;
614 QMI_ENCDEC_DECODE_TLV(&tlv_type
,
615 &tlv_len
, tlv_pointer
);
616 buf_src
+= (TLV_TYPE_SIZE
+ TLV_LEN_SIZE
);
617 decoded_bytes
+= (TLV_TYPE_SIZE
+ TLV_LEN_SIZE
);
618 temp_ei
= find_ei(ei_array
, tlv_type
);
619 if (!temp_ei
&& tlv_type
< OPTIONAL_TLV_TYPE_START
) {
620 pr_err("%s: Inval element info\n", __func__
);
622 } else if (!temp_ei
) {
623 UPDATE_DECODE_VARIABLES(buf_src
,
624 decoded_bytes
, tlv_len
);
629 * No length information for elements in nested
630 * structures. So use remaining decodable buffer space.
632 tlv_len
= in_buf_len
- decoded_bytes
;
635 buf_dst
= out_c_struct
+ temp_ei
->offset
;
636 if (temp_ei
->data_type
== QMI_OPT_FLAG
) {
637 memcpy(buf_dst
, &opt_flag_value
, sizeof(u8
));
638 temp_ei
= temp_ei
+ 1;
639 buf_dst
= out_c_struct
+ temp_ei
->offset
;
642 if (temp_ei
->data_type
== QMI_DATA_LEN
) {
643 data_len_sz
= temp_ei
->elem_size
== sizeof(u8
) ?
644 sizeof(u8
) : sizeof(u16
);
645 rc
= qmi_decode_basic_elem(&data_len_value
, buf_src
,
647 memcpy(buf_dst
, &data_len_value
, sizeof(u32
));
648 temp_ei
= temp_ei
+ 1;
649 buf_dst
= out_c_struct
+ temp_ei
->offset
;
650 tlv_len
-= data_len_sz
;
651 UPDATE_DECODE_VARIABLES(buf_src
, decoded_bytes
, rc
);
654 if (temp_ei
->array_type
== NO_ARRAY
) {
656 } else if (temp_ei
->array_type
== STATIC_ARRAY
) {
657 data_len_value
= temp_ei
->elem_len
;
658 } else if (data_len_value
> temp_ei
->elem_len
) {
659 pr_err("%s: Data len %d > max spec %d\n",
660 __func__
, data_len_value
, temp_ei
->elem_len
);
664 switch (temp_ei
->data_type
) {
665 case QMI_UNSIGNED_1_BYTE
:
666 case QMI_UNSIGNED_2_BYTE
:
667 case QMI_UNSIGNED_4_BYTE
:
668 case QMI_UNSIGNED_8_BYTE
:
669 case QMI_SIGNED_2_BYTE_ENUM
:
670 case QMI_SIGNED_4_BYTE_ENUM
:
671 rc
= qmi_decode_basic_elem(buf_dst
, buf_src
,
674 UPDATE_DECODE_VARIABLES(buf_src
, decoded_bytes
, rc
);
678 rc
= qmi_decode_struct_elem(temp_ei
, buf_dst
, buf_src
,
679 data_len_value
, tlv_len
,
683 UPDATE_DECODE_VARIABLES(buf_src
, decoded_bytes
, rc
);
687 rc
= qmi_decode_string_elem(temp_ei
, buf_dst
, buf_src
,
691 UPDATE_DECODE_VARIABLES(buf_src
, decoded_bytes
, rc
);
695 pr_err("%s: Unrecognized data type\n", __func__
);
698 temp_ei
= temp_ei
+ 1;
701 return decoded_bytes
;
705 * qmi_encode_message() - Encode C structure as QMI encoded message
706 * @type: Type of QMI message
707 * @msg_id: Message ID of the message
708 * @len: Passed as max length of the message, updated to actual size
709 * @txn_id: Transaction ID
710 * @ei: QMI message descriptor
711 * @c_struct: Reference to structure to encode
713 * Return: Buffer with encoded message, or negative ERR_PTR() on error
715 void *qmi_encode_message(int type
, unsigned int msg_id
, size_t *len
,
716 unsigned int txn_id
, struct qmi_elem_info
*ei
,
717 const void *c_struct
)
719 struct qmi_header
*hdr
;
724 /* Check the possibility of a zero length QMI message */
726 ret
= qmi_calc_min_msg_len(ei
, 1);
728 pr_err("%s: Calc. len %d != 0, but NULL c_struct\n",
730 return ERR_PTR(-EINVAL
);
734 msg
= kzalloc(sizeof(*hdr
) + *len
, GFP_KERNEL
);
736 return ERR_PTR(-ENOMEM
);
738 /* Encode message, if we have a message */
740 msglen
= qmi_encode(ei
, msg
+ sizeof(*hdr
), c_struct
, *len
, 1);
743 return ERR_PTR(msglen
);
749 hdr
->txn_id
= txn_id
;
750 hdr
->msg_id
= msg_id
;
751 hdr
->msg_len
= msglen
;
753 *len
= sizeof(*hdr
) + msglen
;
757 EXPORT_SYMBOL(qmi_encode_message
);
760 * qmi_decode_message() - Decode QMI encoded message to C structure
761 * @buf: Buffer with encoded message
762 * @len: Amount of data in @buf
763 * @ei: QMI message descriptor
764 * @c_struct: Reference to structure to decode into
766 * Return: The number of bytes of decoded information on success, negative
769 int qmi_decode_message(const void *buf
, size_t len
,
770 struct qmi_elem_info
*ei
, void *c_struct
)
775 if (!c_struct
|| !buf
|| !len
)
778 return qmi_decode(ei
, c_struct
, buf
+ sizeof(struct qmi_header
),
779 len
- sizeof(struct qmi_header
), 1);
781 EXPORT_SYMBOL(qmi_decode_message
);
783 /* Common header in all QMI responses */
784 struct qmi_elem_info qmi_response_type_v01_ei
[] = {
786 .data_type
= QMI_SIGNED_2_BYTE_ENUM
,
788 .elem_size
= sizeof(u16
),
789 .array_type
= NO_ARRAY
,
790 .tlv_type
= QMI_COMMON_TLV_TYPE
,
791 .offset
= offsetof(struct qmi_response_type_v01
, result
),
795 .data_type
= QMI_SIGNED_2_BYTE_ENUM
,
797 .elem_size
= sizeof(u16
),
798 .array_type
= NO_ARRAY
,
799 .tlv_type
= QMI_COMMON_TLV_TYPE
,
800 .offset
= offsetof(struct qmi_response_type_v01
, error
),
804 .data_type
= QMI_EOTI
,
807 .array_type
= NO_ARRAY
,
808 .tlv_type
= QMI_COMMON_TLV_TYPE
,
813 EXPORT_SYMBOL(qmi_response_type_v01_ei
);
815 MODULE_DESCRIPTION("QMI encoder/decoder helper");
816 MODULE_LICENSE("GPL v2");