mirror of
https://github.com/joel16/android_kernel_sony_msm8994.git
synced 2024-11-23 20:20:21 +00:00
lib: qmi_encdec: Add support for string data type
Add support to encode and decode string data type into a QMI message. If a string has a <Type>:<Length>:<Value> information associated with it, then the length information holds the length of the string. If the string is part of a nested structure, then the length of the string is explicitly encoded into the QMI message. Change-Id: If488d25eaf6d97cd9422848e7bfdfd17cdb68fa0 Signed-off-by: Karthikeyan Ramasubramanian <kramasub@codeaurora.org>
This commit is contained in:
parent
384894c9b2
commit
72d7224084
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
||||
/* 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
|
||||
@ -39,6 +39,7 @@ enum elem_type {
|
||||
QMI_SIGNED_2_BYTE_ENUM,
|
||||
QMI_SIGNED_4_BYTE_ENUM,
|
||||
QMI_STRUCT,
|
||||
QMI_STRING,
|
||||
QMI_EOTI,
|
||||
};
|
||||
|
||||
|
144
lib/qmi_encdec.c
144
lib/qmi_encdec.c
@ -24,6 +24,7 @@
|
||||
|
||||
#define TLV_LEN_SIZE sizeof(uint16_t)
|
||||
#define TLV_TYPE_SIZE sizeof(uint8_t)
|
||||
#define U8_MAX 255
|
||||
|
||||
#ifdef CONFIG_QMI_ENCDEC_DEBUG
|
||||
|
||||
@ -120,6 +121,11 @@ static int qmi_calc_max_msg_len(struct elem_info *ei_array,
|
||||
max_msg_len += (temp_ei->elem_len *
|
||||
qmi_calc_max_msg_len(temp_ei->ei_array,
|
||||
(level + 1)));
|
||||
} else if (temp_ei->data_type == QMI_STRING) {
|
||||
if (level > 1)
|
||||
max_msg_len += temp_ei->elem_len <= U8_MAX ?
|
||||
sizeof(uint8_t) : sizeof(uint16_t);
|
||||
max_msg_len += temp_ei->elem_len * temp_ei->elem_size;
|
||||
} else {
|
||||
max_msg_len += (temp_ei->elem_len * temp_ei->elem_size);
|
||||
}
|
||||
@ -166,6 +172,12 @@ static int qmi_calc_min_msg_len(struct elem_info *ei_array,
|
||||
min_msg_len += qmi_calc_min_msg_len(temp_ei->ei_array,
|
||||
(level + 1));
|
||||
temp_ei++;
|
||||
} else if (temp_ei->data_type == QMI_STRING) {
|
||||
if (level > 1)
|
||||
min_msg_len += temp_ei->elem_len <= U8_MAX ?
|
||||
sizeof(uint8_t) : sizeof(uint16_t);
|
||||
min_msg_len += temp_ei->elem_len * temp_ei->elem_size;
|
||||
temp_ei++;
|
||||
} else {
|
||||
min_msg_len += (temp_ei->elem_len * temp_ei->elem_size);
|
||||
temp_ei++;
|
||||
@ -326,6 +338,66 @@ static int qmi_encode_struct_elem(struct elem_info *ei_array,
|
||||
return encoded_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* qmi_encode_string_elem() - Encodes elements of string data type
|
||||
* @ei_array: Struct info array descibing the string element.
|
||||
* @buf_dst: Buffer to store the encoded information.
|
||||
* @buf_src: Buffer containing the elements to be encoded.
|
||||
* @out_buf_len: Available space in the encode buffer.
|
||||
* @enc_level: Depth of the string element from the main structure.
|
||||
*
|
||||
* @return: Mumber of bytes of encoded information, on success.
|
||||
* < 0 on error.
|
||||
*
|
||||
* This function encodes a string element of maximum length "ei_array->elem_len"
|
||||
* bytes from the source buffer "buf_src" and stores the encoded information in
|
||||
* the destination buffer "buf_dst". This function returns the number of bytes
|
||||
* of encoded information.
|
||||
*/
|
||||
static int qmi_encode_string_elem(struct elem_info *ei_array,
|
||||
void *buf_dst, void *buf_src,
|
||||
uint32_t out_buf_len, int enc_level)
|
||||
{
|
||||
int rc;
|
||||
int encoded_bytes = 0;
|
||||
struct elem_info *temp_ei = ei_array;
|
||||
uint32_t string_len;
|
||||
uint32_t string_len_sz;
|
||||
|
||||
string_len = strlen(buf_src);
|
||||
string_len_sz = temp_ei->elem_len <= U8_MAX ?
|
||||
sizeof(uint8_t) : sizeof(uint16_t);
|
||||
if (string_len > temp_ei->elem_len) {
|
||||
pr_err("%s: String to be encoded is longer - %d > %d\n",
|
||||
__func__, string_len, temp_ei->elem_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (enc_level == 1) {
|
||||
if (string_len + TLV_LEN_SIZE + TLV_TYPE_SIZE >
|
||||
out_buf_len) {
|
||||
pr_err("%s: Output len %d > Out Buf len %d\n",
|
||||
__func__, string_len, out_buf_len);
|
||||
return -ETOOSMALL;
|
||||
}
|
||||
} else {
|
||||
if (string_len + string_len_sz > out_buf_len) {
|
||||
pr_err("%s: Output len %d > Out Buf len %d\n",
|
||||
__func__, string_len, out_buf_len);
|
||||
return -ETOOSMALL;
|
||||
}
|
||||
rc = qmi_encode_basic_elem(buf_dst, &string_len,
|
||||
1, string_len_sz);
|
||||
encoded_bytes += rc;
|
||||
}
|
||||
|
||||
rc = qmi_encode_basic_elem(buf_dst + encoded_bytes, buf_src,
|
||||
string_len, temp_ei->elem_size);
|
||||
encoded_bytes += rc;
|
||||
QMI_ENCODE_LOG_ELEM(enc_level, string_len, temp_ei->elem_size, buf_src);
|
||||
return encoded_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* skip_to_next_elem() - Skip to next element in the structure to be encoded
|
||||
* @ei_array: Struct info describing the element to be skipped.
|
||||
@ -466,6 +538,14 @@ static int _qmi_kernel_encode(struct elem_info *ei_array,
|
||||
encoded_bytes, tlv_len, encode_tlv, rc);
|
||||
break;
|
||||
|
||||
case QMI_STRING:
|
||||
rc = qmi_encode_string_elem(temp_ei, buf_dst, buf_src,
|
||||
out_buf_len - encoded_bytes, enc_level);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
UPDATE_ENCODE_VARIABLES(temp_ei, buf_dst,
|
||||
encoded_bytes, tlv_len, encode_tlv, rc);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: Unrecognized data type\n", __func__);
|
||||
return -EINVAL;
|
||||
@ -593,6 +673,61 @@ static int qmi_decode_struct_elem(struct elem_info *ei_array, void *buf_dst,
|
||||
return decoded_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* qmi_decode_string_elem() - Decodes elements of string data type
|
||||
* @ei_array: Struct info array descibing the string element.
|
||||
* @buf_dst: Buffer to store the decoded element.
|
||||
* @buf_src: Buffer containing the elements in QMI wire format.
|
||||
* @tlv_len: Total size of the encoded inforation corresponding to
|
||||
* this string element.
|
||||
* @dec_level: Depth of the string element from the main structure.
|
||||
*
|
||||
* @return: Total size of the decoded data elements, on success.
|
||||
* < 0 on error.
|
||||
*
|
||||
* This function decodes the string element of maximum length
|
||||
* "ei_array->elem_len" from the source buffer "buf_src" and puts it into
|
||||
* the destination buffer "buf_dst". This function returns number of bytes
|
||||
* decoded from the input buffer.
|
||||
*/
|
||||
static int qmi_decode_string_elem(struct elem_info *ei_array, void *buf_dst,
|
||||
void *buf_src, uint32_t tlv_len,
|
||||
int dec_level)
|
||||
{
|
||||
int rc;
|
||||
int decoded_bytes = 0;
|
||||
uint32_t string_len;
|
||||
uint32_t string_len_sz;
|
||||
struct elem_info *temp_ei = ei_array;
|
||||
|
||||
if (dec_level == 1) {
|
||||
string_len = tlv_len;
|
||||
} else {
|
||||
string_len_sz = temp_ei->elem_len <= U8_MAX ?
|
||||
sizeof(uint8_t) : sizeof(uint16_t);
|
||||
rc = qmi_decode_basic_elem(&string_len, buf_src,
|
||||
1, string_len_sz);
|
||||
decoded_bytes += rc;
|
||||
}
|
||||
|
||||
if (string_len > temp_ei->elem_len) {
|
||||
pr_err("%s: String len %d > Max Len %d\n",
|
||||
__func__, string_len, temp_ei->elem_len);
|
||||
return -ETOOSMALL;
|
||||
} else if (string_len > tlv_len) {
|
||||
pr_err("%s: String len %d > Input Buffer Len %d\n",
|
||||
__func__, string_len, tlv_len);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = qmi_decode_basic_elem(buf_dst, buf_src + decoded_bytes,
|
||||
string_len, temp_ei->elem_size);
|
||||
*((char *)buf_dst + string_len) = '\0';
|
||||
decoded_bytes += rc;
|
||||
QMI_DECODE_LOG_ELEM(dec_level, string_len, temp_ei->elem_size, buf_dst);
|
||||
return decoded_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_ei() - Find element info corresponding to TLV Type
|
||||
* @ei_array: Struct info array of the message being decoded.
|
||||
@ -720,6 +855,15 @@ static int _qmi_kernel_decode(struct elem_info *ei_array,
|
||||
return rc;
|
||||
UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
|
||||
break;
|
||||
|
||||
case QMI_STRING:
|
||||
rc = qmi_decode_string_elem(temp_ei, buf_dst, buf_src,
|
||||
tlv_len, dec_level);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
UPDATE_DECODE_VARIABLES(buf_src, decoded_bytes, rc);
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("%s: Unrecognized data type\n", __func__);
|
||||
return -EINVAL;
|
||||
|
Loading…
Reference in New Issue
Block a user