184 lines
5 KiB
C
184 lines
5 KiB
C
/* 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
|