/* 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 #include #include #include #include #include #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