blob: 66c3d84485eda6eddd1bbfb4a2de91fcc391f9e1 [file] [log] [blame]
/* 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