|  | /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or modify | 
|  | * it under the terms of the GNU General Public License version 2 and | 
|  | * only version 2 as published by the Free Software Foundation. | 
|  | * | 
|  | * This program is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU General Public License for more details. | 
|  | */ | 
|  |  | 
|  | #ifndef _QMI_ENCDEC_H_ | 
|  | #define _QMI_ENCDEC_H_ | 
|  |  | 
|  | #include <linux/types.h> | 
|  | #include <linux/errno.h> | 
|  | #include <linux/mm.h> | 
|  | #include <linux/list.h> | 
|  | #include <linux/socket.h> | 
|  | #include <linux/gfp.h> | 
|  |  | 
|  | #define QMI_REQUEST_CONTROL_FLAG 0x00 | 
|  | #define QMI_RESPONSE_CONTROL_FLAG 0x02 | 
|  | #define QMI_INDICATION_CONTROL_FLAG 0x04 | 
|  | #define QMI_HEADER_SIZE 7 | 
|  |  | 
|  | /** | 
|  | * elem_type - Enum to identify the data type of elements in a data | 
|  | *             structure. | 
|  | */ | 
|  | enum elem_type { | 
|  | QMI_OPT_FLAG = 1, | 
|  | QMI_DATA_LEN, | 
|  | QMI_UNSIGNED_1_BYTE, | 
|  | QMI_UNSIGNED_2_BYTE, | 
|  | QMI_UNSIGNED_4_BYTE, | 
|  | QMI_UNSIGNED_8_BYTE, | 
|  | QMI_SIGNED_2_BYTE_ENUM, | 
|  | QMI_SIGNED_4_BYTE_ENUM, | 
|  | QMI_STRUCT, | 
|  | QMI_STRING, | 
|  | QMI_EOTI, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * array_type - Enum to identify if an element in a data structure is | 
|  | *              an array. If so, then is it a static length array or a | 
|  | *              variable length array. | 
|  | */ | 
|  | enum array_type { | 
|  | NO_ARRAY = 0, | 
|  | STATIC_ARRAY = 1, | 
|  | VAR_LEN_ARRAY = 2, | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * elem_info - Data structure to specify information about an element | 
|  | *               in a data structure. An array of this data structure | 
|  | *               can be used to specify info about a complex data | 
|  | *               structure to be encoded/decoded. | 
|  | * | 
|  | * @data_type: Data type of this element. | 
|  | * @elem_len: Array length of this element, if an array. | 
|  | * @elem_size: Size of a single instance of this data type. | 
|  | * @is_array: Array type of this element. | 
|  | * @tlv_type: QMI message specific type to identify which element | 
|  | *            is present in an incoming message. | 
|  | * @offset: To identify the address of the first instance of this | 
|  | *          element in the data structure. | 
|  | * @ei_array: Array to provide information about the nested structure | 
|  | *            within a data structure to be encoded/decoded. | 
|  | */ | 
|  | struct elem_info { | 
|  | enum elem_type data_type; | 
|  | uint32_t elem_len; | 
|  | uint32_t elem_size; | 
|  | enum array_type is_array; | 
|  | uint8_t tlv_type; | 
|  | uint32_t offset; | 
|  | struct elem_info *ei_array; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * @msg_desc - Describe about the main/outer structure to be | 
|  | *		  encoded/decoded. | 
|  | * | 
|  | * @max_msg_len: Maximum possible length of the QMI message. | 
|  | * @ei_array: Array to provide information about a data structure. | 
|  | */ | 
|  | struct msg_desc { | 
|  | uint16_t msg_id; | 
|  | int max_msg_len; | 
|  | struct elem_info *ei_array; | 
|  | }; | 
|  |  | 
|  | struct qmi_header { | 
|  | unsigned char cntl_flag; | 
|  | uint16_t txn_id; | 
|  | uint16_t msg_id; | 
|  | uint16_t msg_len; | 
|  | } __attribute__((__packed__)); | 
|  |  | 
|  | static inline void encode_qmi_header(unsigned char *buf, | 
|  | unsigned char cntl_flag, uint16_t txn_id, | 
|  | uint16_t msg_id, uint16_t msg_len) | 
|  | { | 
|  | struct qmi_header *hdr = (struct qmi_header *)buf; | 
|  |  | 
|  | hdr->cntl_flag = cntl_flag; | 
|  | hdr->txn_id = txn_id; | 
|  | hdr->msg_id = msg_id; | 
|  | hdr->msg_len = msg_len; | 
|  | } | 
|  |  | 
|  | static inline void decode_qmi_header(unsigned char *buf, | 
|  | unsigned char *cntl_flag, uint16_t *txn_id, | 
|  | uint16_t *msg_id, uint16_t *msg_len) | 
|  | { | 
|  | struct qmi_header *hdr = (struct qmi_header *)buf; | 
|  |  | 
|  | *cntl_flag = hdr->cntl_flag; | 
|  | *txn_id = hdr->txn_id; | 
|  | *msg_id = hdr->msg_id; | 
|  | *msg_len = hdr->msg_len; | 
|  | } | 
|  |  | 
|  | #ifdef CONFIG_QMI_ENCDEC | 
|  | /** | 
|  | * qmi_kernel_encode() - Encode to QMI message wire format | 
|  | * @desc: Pointer to structure descriptor. | 
|  | * @out_buf: Buffer to hold the encoded QMI message. | 
|  | * @out_buf_len: Length of the out buffer. | 
|  | * @in_c_struct: C Structure to be encoded. | 
|  | * | 
|  | * @return: size of encoded message on success, < 0 on error. | 
|  | */ | 
|  | int qmi_kernel_encode(struct msg_desc *desc, | 
|  | void *out_buf, uint32_t out_buf_len, | 
|  | void *in_c_struct); | 
|  |  | 
|  | /** | 
|  | * qmi_kernel_decode() - Decode to C Structure format | 
|  | * @desc: Pointer to structure descriptor. | 
|  | * @out_c_struct: Buffer to hold the decoded C structure. | 
|  | * @in_buf: Buffer containg the QMI message to be decoded. | 
|  | * @in_buf_len: Length of the incoming QMI message. | 
|  | * | 
|  | * @return: 0 on success, < 0 on error. | 
|  | */ | 
|  | int qmi_kernel_decode(struct msg_desc *desc, void *out_c_struct, | 
|  | void *in_buf, uint32_t in_buf_len); | 
|  |  | 
|  | /** | 
|  | * qmi_verify_max_msg_len() - Verify the maximum length of a QMI message | 
|  | * @desc: Pointer to structure descriptor. | 
|  | * | 
|  | * @return: true if the maximum message length embedded in structure | 
|  | *          descriptor matches the calculated value, else false. | 
|  | */ | 
|  | bool qmi_verify_max_msg_len(struct msg_desc *desc); | 
|  |  | 
|  | #else | 
|  | static inline int qmi_kernel_encode(struct msg_desc *desc, | 
|  | void *out_buf, uint32_t out_buf_len, | 
|  | void *in_c_struct) | 
|  | { | 
|  | return -EOPNOTSUPP; | 
|  | } | 
|  |  | 
|  | static inline int qmi_kernel_decode(struct msg_desc *desc, | 
|  | void *out_c_struct, | 
|  | void *in_buf, uint32_t in_buf_len) | 
|  | { | 
|  | return -EOPNOTSUPP; | 
|  | } | 
|  |  | 
|  | static inline bool qmi_verify_max_msg_len(struct msg_desc *desc) | 
|  | { | 
|  | return false; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #endif |