[tel][qmi] Switch codegen to using a type instead of a raw size
fixes dBm to be a signed number
Change-Id: I765c440c97189753cd2eee41386f7012ad1318ec
diff --git a/src/connectivity/telephony/lib/qmi-protocol/protocol/ctl.json b/src/connectivity/telephony/lib/qmi-protocol/protocol/ctl.json
index 6a2c345..9016bca 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/protocol/ctl.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/protocol/ctl.json
@@ -13,14 +13,14 @@
{
"param": "host_driver",
"id": "0x01",
- "size": 1
+ "type": "uint8"
}
],
"response": [
{
"param": "link_id",
"id": "0x01",
- "size": 2
+ "type": "uint16"
}
]
},
@@ -32,21 +32,21 @@
{
"param": "svc_type",
"id": "0x01",
- "size": 1
+ "type": "uint8"
}
],
"response": [
{
"param": "client_id",
"id": "0x01",
- "size": 2,
+ "type": "uint16",
"subparams": [
{
- "size": 1,
+ "type": "uint8",
"param": "svc_type"
},
{
- "size": 1,
+ "type": "uint8",
"param": "client_id"
}
]
diff --git a/src/connectivity/telephony/lib/qmi-protocol/protocol/dms.json b/src/connectivity/telephony/lib/qmi-protocol/protocol/dms.json
index 1308d35..69c40fc 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/protocol/dms.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/protocol/dms.json
@@ -14,7 +14,8 @@
"response": [
{
"param": "device_manufacturer",
- "id": "0x01"
+ "id": "0x01",
+ "type": "string"
}
]
},
@@ -26,18 +27,22 @@
"response": [
{
"param": "esn",
- "id": "0x10"
+ "id": "0x10",
+ "type": "string"
},
{
"param": "imei",
- "id": "0x11"
+ "id": "0x11",
+ "type": "string"
},
{
"param": "meid",
+ "type": "string",
"id": "0x12"
},
{
"param": "imeisv_svn",
+ "type": "string",
"id": "0x13"
}
]
@@ -51,14 +56,14 @@
{
"param": "power",
"id": "0x01",
- "size": 2,
+ "type": "uint16",
"subparams": [
{
- "size": 1,
+ "type": "uint8",
"param": "power_status"
},
{
- "size": 1,
+ "type": "uint8",
"param": "battery_lvl"
}
]
@@ -74,19 +79,19 @@
{
"param": "operating_mode",
"id": "0x01",
- "size": 1
+ "type": "uint8"
},
{
"param": "offline_reason",
"id": "0x10",
"optional": true,
- "size": 2
+ "type": "uint16"
},
{
"param": "hardware_controlled_mode",
"id": "0x11",
"optional": true,
- "size": 1
+ "type": "uint8"
}
]
}
diff --git a/src/connectivity/telephony/lib/qmi-protocol/protocol/nas.json b/src/connectivity/telephony/lib/qmi-protocol/protocol/nas.json
index f8a9e74..5086fca 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/protocol/nas.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/protocol/nas.json
@@ -15,15 +15,15 @@
{
"param": "signal_strength",
"id": "0x01",
- "size": 2,
+ "type": "uint16",
"subparams": [
{
"param": "signal_strength",
- "size": 1
+ "type": "int8"
},
{
"param": "radio_interface",
- "size": 1
+ "type": "uint8"
}
]
}
diff --git a/src/connectivity/telephony/lib/qmi-protocol/protocol/wda.json b/src/connectivity/telephony/lib/qmi-protocol/protocol/wda.json
index 9428c58..b68d34c 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/protocol/wda.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/protocol/wda.json
@@ -13,13 +13,13 @@
{
"param": "qos_format",
"id": "0x10",
- "size": 1,
+ "type": "uint8",
"optional": true
},
{
"param": "link_layer_prot",
"id": "0x11",
- "size": 4,
+ "type": "uint32",
"optional": true
}
],
@@ -27,13 +27,13 @@
{
"param": "qos_format",
"id": "0x10",
- "size": 1,
+ "type": "uint8",
"optional": true
},
{
"param": "link_layer_prot",
"id": "0x11",
- "size": 4,
+ "type": "uint32",
"optional": true
}
]
diff --git a/src/connectivity/telephony/lib/qmi-protocol/protocol/wds.json b/src/connectivity/telephony/lib/qmi-protocol/protocol/wds.json
index 1ce587b..0909936 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/protocol/wds.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/protocol/wds.json
@@ -14,12 +14,13 @@
{
"param": "apn",
"id": "0x14",
+ "type": "string",
"optional": true
},
{
"param": "ip_family_preference",
"id": "0x19",
- "size": 1,
+ "type": "uint8",
"optional": true
}
],
@@ -27,7 +28,7 @@
{
"param": "packet_data_handle",
"id": "0x01",
- "size": 4
+ "type": "uint32"
}
]
},
@@ -39,38 +40,38 @@
{
"param": "requested_settings",
"id": "0x10",
- "size": 4
+ "type": "uint32"
}
],
"response": [
{
"param": "ipv4_addr",
"id": "0x1E",
- "size": 4,
+ "type": "uint32",
"optional": true
},
{
"param": "ipv4_subnet",
"id": "0x21",
- "size": 4,
+ "type": "uint32",
"optional": true
},
{
"param": "ipv4_gateway",
"id": "0x20",
- "size": 4,
+ "type": "uint32",
"optional": true
},
{
"param": "ipv4_dns",
"id": "0x15",
- "size": 4,
+ "type": "uint32",
"optional": true
},
{
"param": "mtu",
"id": "0x29",
- "size": 4,
+ "type": "uint32",
"optional": true
}
]
diff --git a/src/connectivity/telephony/lib/qmi-protocol/src/ast.rs b/src/connectivity/telephony/lib/qmi-protocol/src/ast.rs
index 57d5d90..e39e036 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/src/ast.rs
+++ b/src/connectivity/telephony/lib/qmi-protocol/src/ast.rs
@@ -12,7 +12,53 @@
#[derive(Debug, Serialize, Deserialize)]
pub struct SubParam {
pub param: String,
- pub size: u16,
+ #[serde(rename = "type")]
+ pub ty: QmiType,
+}
+
+#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
+pub enum QmiType {
+ #[serde(rename = "int8")]
+ Int8,
+ #[serde(rename = "uint8")]
+ Uint8,
+ #[serde(rename = "int16")]
+ Int16,
+ #[serde(rename = "uint16")]
+ Uint16,
+ #[serde(rename = "int32")]
+ Int32,
+ #[serde(rename = "uint32")]
+ Uint32,
+ #[serde(rename = "string")]
+ Str,
+}
+
+impl QmiType {
+ pub fn to_size(&self) -> Option<u16> {
+ match self {
+ QmiType::Int8 => Some(1),
+ QmiType::Uint8 => Some(1),
+ QmiType::Int16 => Some(2),
+ QmiType::Uint16 => Some(2),
+ QmiType::Int32 => Some(4),
+ QmiType::Uint32 => Some(4),
+ QmiType::Str => None,
+ }
+ }
+
+ pub fn to_rust_str(&self) -> String {
+ match self {
+ QmiType::Int8 => "i8",
+ QmiType::Uint8 => "u8",
+ QmiType::Int16 => "i16",
+ QmiType::Uint16 => "u16",
+ QmiType::Int32 => "i32",
+ QmiType::Uint32 => "u32",
+ QmiType::Str => "String",
+ }
+ .to_string()
+ }
}
#[derive(Debug, Serialize, Deserialize)]
@@ -20,7 +66,8 @@
pub param: String,
#[serde(deserialize_with = "from_hex_str")]
pub id: u16,
- pub size: Option<u16>,
+ #[serde(rename = "type")]
+ pub ty: QmiType,
#[serde(default)]
pub optional: bool,
#[serde(default, rename = "subparams")]
diff --git a/src/connectivity/telephony/lib/qmi-protocol/src/codegen.rs b/src/connectivity/telephony/lib/qmi-protocol/src/codegen.rs
index 26402b9..dfe1c77 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/src/codegen.rs
+++ b/src/connectivity/telephony/lib/qmi-protocol/src/codegen.rs
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-use crate::ast::{Message, Service, ServiceSet, Structure, SubParam, TLV};
-use failure::Error;
+use crate::ast::{Message, QmiType, Service, ServiceSet, Structure, SubParam, TLV};
+use failure::{format_err, Error};
use std::io;
pub struct Codegen<'a, W: io::Write> {
@@ -11,17 +11,8 @@
depth: usize,
}
-fn type_fmt(ty: Option<u16>, optional: bool) -> String {
- let ty = match ty {
- Some(size) => match size {
- 1 => "u8",
- 2 => "u16",
- 4 => "u32",
- _ => panic!("Invalid size to type conversion: {}", size),
- },
- None => "String",
- }
- .to_string();
+fn type_fmt(ty: QmiType, optional: bool) -> String {
+ let ty = ty.to_rust_str();
if optional {
format!("Option<{}>", ty)
@@ -60,11 +51,7 @@
Codegen { w, depth: 0 }
}
- pub fn codegen_svc_tlv_encode(
- &mut self,
- field: &TLV,
- _structure: &Structure,
- ) -> Result<(), Error> {
+ fn codegen_svc_tlv_encode(&mut self, field: &TLV, _structure: &Structure) -> Result<(), Error> {
if field.optional {
writeln_indent!(self, "if let Some(ref {}) = self.{} {{", field.param, field.param);
indent!(self);
@@ -82,44 +69,62 @@
// service msg type
writeln_indent!(self, "buf.put_u8({});", field.id);
- match field.size {
- None => {
+ match field.ty {
+ QmiType::Str => {
// service msg length (variable)
writeln_indent!(self, "buf.put_u16_le({}.as_bytes().len() as u16);", field.param);
// service msg value
writeln_indent!(self, "buf.put_slice({}.as_bytes());", field.param);
}
- Some(size) => {
+ sized_type => {
// service msg length (fixed size)
- writeln_indent!(self, "buf.put_u16_le({});", size);
+ writeln_indent!(self, "buf.put_u16_le({});", sized_type.to_size().unwrap());
// service msg value
if field.has_sub_params() {
for param in field.sub_params.iter() {
- match param.size {
- 1 => {
- writeln_indent!(self, "buf.put_u8(*{});", param.param);
+ match param.ty {
+ QmiType::Str => {
+ return Err(format_err!(
+ "No way to handle an unsized type in a subparam"
+ ))
}
- 2 => {
- writeln_indent!(self, "buf.put_u16_le(*{});", param.param);
+ QmiType::Uint8 | QmiType::Int8 => {
+ writeln_indent!(
+ self,
+ "buf.put_{}(*{});",
+ param.ty.to_rust_str(),
+ param.param
+ );
}
- 4 => {
- writeln_indent!(self, "buf.put_u32_le(*{});", param.param);
+ _ => {
+ writeln_indent!(
+ self,
+ "buf.put_{}_le(*{});",
+ param.ty.to_rust_str(),
+ param.param
+ );
}
- _ => panic!("invalid field size: {}", size),
}
}
} else {
- match size {
- 1 => {
- writeln_indent!(self, "buf.put_u8(*{});", field.param);
+ match sized_type {
+ QmiType::Uint8 | QmiType::Int8 => {
+ writeln_indent!(
+ self,
+ "buf.put_{}(*{});",
+ sized_type.to_rust_str(),
+ field.param
+ );
}
- 2 => {
- writeln_indent!(self, "buf.put_u16_le(*{});", field.param);
+ QmiType::Str => unreachable!("handled above"),
+ _ => {
+ writeln_indent!(
+ self,
+ "buf.put_{}_le(*{});",
+ sized_type.to_rust_str(),
+ field.param
+ );
}
- 4 => {
- writeln_indent!(self, "buf.put_u32_le(*{});", field.param);
- }
- _ => panic!("invalid field size: {}", size),
}
}
}
@@ -133,25 +138,23 @@
Ok(())
}
- pub fn codegen_svc_decode_subfield(&mut self, field: &SubParam) -> Result<(), Error> {
- match field.size {
- 1 => {
- writeln_indent!(self, "{} = buf.get_u8();", field.param);
+ // This function should not decrement the total size
+ fn codegen_svc_decode_subfield(&mut self, field: &SubParam) -> Result<(), Error> {
+ match field.ty {
+ QmiType::Str => return Err(format_err!("Cannot have unsized types in subparams")),
+ QmiType::Uint8 | QmiType::Int8 => {
+ writeln_indent!(self, "{} = buf.get_{}();", field.param, field.ty.to_rust_str());
+ },
+ _ => {
+ writeln_indent!(self, "{} = buf.get_{}_le();", field.param, field.ty.to_rust_str());
}
- 2 => {
- writeln_indent!(self, "{} = buf.get_u16_le();", field.param);
- }
- 4 => {
- writeln_indent!(self, "{} = buf.get_u32_le();", field.param);
- }
- _ => panic!("invalid field size: {}", field.size),
}
Ok(())
}
- pub fn codegen_svc_decode_field(&mut self, field: &TLV) -> Result<(), Error> {
- match field.size {
- None => {
+ fn codegen_svc_decode_field(&mut self, field: &TLV) -> Result<(), Error> {
+ match field.ty {
+ QmiType::Str => {
writeln_indent!(self, "let dst = buf.by_ref().take(tlv_len as usize).collect();");
writeln_indent!(self, "total_len -= tlv_len;");
if field.optional {
@@ -164,48 +167,51 @@
writeln_indent!(self, "{} = String::from_utf8(dst).unwrap();", field.param);
}
}
- Some(size) => {
- match size {
- 1 => {
- if field.optional {
- writeln_indent!(self, "{} = Some(buf.get_u8());", field.param);
- } else {
- writeln_indent!(self, "{} = buf.get_u8();", field.param);
- }
- writeln_indent!(self, "total_len -= 1;");
+ sized_type => {
+ if field.has_sub_params() {
+ // TODO check the subparam size is equal to the whole type
+ for param in field.sub_params.iter() {
+ self.codegen_svc_decode_subfield(param)?;
}
- 2 => {
- if field.has_sub_params() {
- // TODO check the subparam size is equal to the whole type
- for param in field.sub_params.iter() {
- self.codegen_svc_decode_subfield(param)?;
- }
- } else {
+ } else {
+ match sized_type {
+ QmiType::Uint8 | QmiType::Int8 => {
if field.optional {
- writeln_indent!(self, "{} = Some(buf.get_u16_le());", field.param);
+ writeln_indent!(
+ self,
+ "{} = Some(buf.get_{}());",
+ field.param,
+ field.ty.to_rust_str()
+ );
} else {
- writeln_indent!(self, "{} = buf.get_u16_le();", field.param);
+ writeln_indent!(
+ self,
+ "{} = buf.get_{}();",
+ field.param,
+ field.ty.to_rust_str()
+ );
}
}
- writeln_indent!(self, "total_len -= 2;");
- }
- 4 => {
- if field.has_sub_params() {
- // TODO check the subparam size is equal to the whole type
- for param in field.sub_params.iter() {
- self.codegen_svc_decode_subfield(param)?;
- }
- } else {
+ _ => {
if field.optional {
- writeln_indent!(self, "{} = Some(buf.get_u32_le());", field.param);
+ writeln_indent!(
+ self,
+ "{} = Some(buf.get_{}_le());",
+ field.param,
+ field.ty.to_rust_str()
+ );
} else {
- writeln_indent!(self, "{} = buf.get_u32_le();", field.param);
+ writeln_indent!(
+ self,
+ "{} = buf.get_{}_le();",
+ field.param,
+ field.ty.to_rust_str()
+ );
}
- writeln_indent!(self, "total_len -= 4;");
}
}
- _ => panic!("invalid field size: {}", size),
}
+ writeln_indent!(self, "total_len -= {};", sized_type.to_size().unwrap());
}
}
Ok(())
@@ -346,7 +352,7 @@
writeln_indent!(self, "// svc length calculation");
writeln_indent!(self, "let mut {}_len = 0u16;", msg.name);
for field in msg.get_request_fields() {
- let field_name = match field.size {
+ let field_name = match field.ty.to_size() {
Some(_) => format!("_{}", field.param),
None => field.param.clone(),
};
@@ -360,7 +366,7 @@
writeln_indent!(self, "{}_len += 2; // tlv length length;", msg.name);
writeln_indent!(self, "let {} = &self.{};", field_name, field.param);
}
- if let Some(size) = field.size {
+ if let Some(size) = field.ty.to_size() {
writeln_indent!(self, "{}_len += {};", msg.name, size);
} else {
writeln_indent!(
@@ -397,7 +403,7 @@
Ok(())
}
- pub fn codegen_svc_msg(&mut self, msg: &Message) -> Result<(), Error> {
+ fn codegen_svc_msg(&mut self, msg: &Message) -> Result<(), Error> {
// define the request struct
writeln_indent!(self, "pub struct {}Req {{", msg.name);
indent!(self);
@@ -408,7 +414,7 @@
self,
"pub {param}: {ty},",
param = param.param,
- ty = type_fmt(Some(param.size), field.optional)
+ ty = type_fmt(param.ty, field.optional)
);
}
} else {
@@ -416,7 +422,7 @@
self,
"pub {param}: {ty},",
param = field.param,
- ty = type_fmt(field.size, field.optional)
+ ty = type_fmt(field.ty, field.optional)
);
}
}
@@ -430,15 +436,10 @@
for field in msg.get_request_fields() {
if field.has_sub_params() {
for param in field.sub_params.iter() {
- write!(
- self.w,
- "{}: {},",
- param.param,
- type_fmt(Some(param.size), field.optional)
- )?;
+ write!(self.w, "{}: {},", param.param, type_fmt(param.ty, field.optional))?;
}
} else {
- write!(self.w, "{}: {},", field.param, type_fmt(field.size, field.optional))?;
+ write!(self.w, "{}: {},", field.param, type_fmt(field.ty, field.optional))?;
}
}
writeln!(self.w, ") -> Self {{")?;
@@ -476,7 +477,7 @@
self,
"pub {param}: {ty},",
param = param.param,
- ty = type_fmt(Some(param.size), false)
+ ty = type_fmt(param.ty, false)
);
}
} else {
@@ -484,7 +485,7 @@
self,
"pub {param}: {ty},",
param = field.param,
- ty = type_fmt(field.size, field.optional)
+ ty = type_fmt(field.ty, field.optional)
);
}
}
@@ -494,7 +495,7 @@
Ok(())
}
- pub fn codegen_service(&mut self, svc: &Service, structure: &Structure) -> Result<(), Error> {
+ fn codegen_service(&mut self, svc: &Service, structure: &Structure) -> Result<(), Error> {
writeln!(self.w, "pub mod {} {{", svc.name)?;
indent!(self);
writeln_indent!(self, "use crate::{{Decodable, Encodable}};");
diff --git a/src/connectivity/telephony/lib/qmi-protocol/tests/optional_response.test.json b/src/connectivity/telephony/lib/qmi-protocol/tests/optional_response.test.json
index c6b4c7f..614bdfb 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/tests/optional_response.test.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/tests/optional_response.test.json
@@ -20,7 +20,7 @@
{
"param": "blah",
"id": "0x01",
- "size": 2,
+ "type": "uint16",
"optional": true
}
]
diff --git a/src/connectivity/telephony/lib/qmi-protocol/tests/simple_request.test.json b/src/connectivity/telephony/lib/qmi-protocol/tests/simple_request.test.json
index ad2be6a..740b188 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/tests/simple_request.test.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/tests/simple_request.test.json
@@ -19,7 +19,7 @@
{
"param": "blah",
"id": "0x01",
- "size": 2
+ "type": "uint16"
}
],
"response": []
diff --git a/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.json b/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.json
index a6fa8c7..645d4e3 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.json
@@ -18,9 +18,14 @@
"request": [],
"response": [
{
- "param": "blah",
+ "param": "uint_blah",
"id": "0x01",
- "size": 2
+ "type": "uint16"
+ },
+ {
+ "param": "int_blah",
+ "id": "0x03",
+ "type": "int16"
}
]
}
diff --git a/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.rs b/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.rs
index 506122c..7768774 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.rs
+++ b/src/connectivity/telephony/lib/qmi-protocol/tests/simple_response.test.rs
@@ -13,7 +13,8 @@
}
#[derive(Debug)]
pub struct TestResp {
- pub blah: u16,
+ pub uint_blah: u16,
+ pub int_blah: i16,
}
impl Encodable for TestReq {
fn transaction_id_len(&self) -> u8 {
@@ -47,7 +48,8 @@
} else {
assert_eq!(0x00, buf.get_u16_le()); // this must be zero if no error from above check
}
- let mut blah = Default::default();
+ let mut uint_blah = Default::default();
+ let mut int_blah = Default::default();
while total_len > 0 {
let msg_id = buf.get_u8();
total_len -= 1;
@@ -55,7 +57,11 @@
total_len -= 2;
match msg_id {
1 => {
- blah = buf.get_u16_le();
+ uint_blah = buf.get_u16_le();
+ total_len -= 2;
+ }
+ 3 => {
+ int_blah = buf.get_i16_le();
total_len -= 2;
}
0 => { eprintln!("Found a type of 0, modem gave a bad TLV, trying to recover"); break; }
@@ -66,7 +72,8 @@
}
}
Ok(TestResp {
- blah,
+ uint_blah,
+ int_blah,
})
}
}
diff --git a/src/connectivity/telephony/lib/qmi-protocol/tests/string_request_decode.test.json b/src/connectivity/telephony/lib/qmi-protocol/tests/string_request_decode.test.json
index 33fe0e5..07f39a8 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/tests/string_request_decode.test.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/tests/string_request_decode.test.json
@@ -19,7 +19,8 @@
"response": [
{
"param": "blah",
- "id": "0x01"
+ "id": "0x01",
+ "type": "string"
}
]
}
diff --git a/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_request.test.json b/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_request.test.json
index f3b82a2..2510fa5 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_request.test.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_request.test.json
@@ -19,14 +19,14 @@
{
"param": "blah",
"id": "0x01",
- "size": 2,
+ "type": "uint16",
"subparams": [
{
- "size": 1,
+ "type": "uint8",
"param": "part_a"
},
{
- "size": 1,
+ "type": "uint8",
"param": "part_b"
}
]
diff --git a/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_response.test.json b/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_response.test.json
index 28ddcfb..8a260fd 100644
--- a/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_response.test.json
+++ b/src/connectivity/telephony/lib/qmi-protocol/tests/subparam_response.test.json
@@ -20,14 +20,14 @@
{
"param": "blah",
"id": "0x01",
- "size": 2,
+ "type": "uint16",
"subparams": [
{
- "size": 1,
+ "type": "uint8",
"param": "part_a"
},
{
- "size": 1,
+ "type": "uint8",
"param": "part_b"
}
]