[tel][qmi-snoop] CLI for snoop QMI messages
Change-Id: I724d6853abaf97c483f5ed276f811d35b961c9c0
diff --git a/src/connectivity/telephony/BUILD.gn b/src/connectivity/telephony/BUILD.gn
index 07a01ff..930fcd3 100644
--- a/src/connectivity/telephony/BUILD.gn
+++ b/src/connectivity/telephony/BUILD.gn
@@ -8,6 +8,7 @@
"//src/connectivity/telephony/config",
"//src/connectivity/telephony/ril-qmi",
"//src/connectivity/telephony/telephony",
+ "//src/connectivity/telephony/tools/qmi-snoop",
"//src/connectivity/telephony/tools/ril-ctl",
]
}
diff --git a/src/connectivity/telephony/drivers/qmi-usb-transport/BUILD.gn b/src/connectivity/telephony/drivers/qmi-usb-transport/BUILD.gn
index 0c9e91f..48ed430 100644
--- a/src/connectivity/telephony/drivers/qmi-usb-transport/BUILD.gn
+++ b/src/connectivity/telephony/drivers/qmi-usb-transport/BUILD.gn
@@ -31,13 +31,14 @@
"//garnet/public/lib/fsl",
"//zircon/public/banjo/ddk.protocol.ethernet",
"//zircon/public/banjo/ddk.protocol.usb",
+ "//zircon/public/fidl/fuchsia-hardware-telephony-transport:fuchsia-hardware-telephony-transport_c",
+ "//zircon/public/fidl/fuchsia-telephony-snoop:fuchsia-telephony-snoop_c",
"//zircon/public/lib/ddk",
"//zircon/public/lib/driver",
"//zircon/public/lib/fit",
"//zircon/public/lib/sync",
"//zircon/public/lib/usb",
"//zircon/public/lib/zx",
- "//zircon/public/fidl/fuchsia-hardware-telephony-transport:fuchsia-hardware-telephony-transport_c",
]
configs += [ "//build/config/fuchsia:enable_zircon_asserts" ]
diff --git a/src/connectivity/telephony/drivers/qmi-usb-transport/qmi-usb-transport.c b/src/connectivity/telephony/drivers/qmi-usb-transport/qmi-usb-transport.c
index e012f56..120989e 100644
--- a/src/connectivity/telephony/drivers/qmi-usb-transport/qmi-usb-transport.c
+++ b/src/connectivity/telephony/drivers/qmi-usb-transport/qmi-usb-transport.c
@@ -12,6 +12,7 @@
#include <usb/usb.h>
#include <fuchsia/hardware/telephony/transport/c/fidl.h>
+#include <fuchsia/telephony/snoop/c/fidl.h>
#include <zircon/device/qmi-transport.h>
#include <zircon/hw/usb/cdc.h>
@@ -59,6 +60,10 @@
zx_handle_t channel_port;
zx_handle_t channel;
+ // Port for snoop QMI messages
+ zx_handle_t snoop_channel_port;
+ zx_handle_t snoop_channel;
+
usb_protocol_t usb;
zx_device_t* usb_device;
zx_device_t* zxdev;
@@ -242,6 +247,46 @@
return status;
}
+static zx_status_t set_snoop_channel(qmi_ctx_t* qmi_ctx, zx_handle_t channel) {
+ zx_status_t result = ZX_OK;
+ zx_port_packet_t packet;
+ zx_status_t status;
+ // Initialize a port to watch whether the other handle of snoop channel has closed
+ if (qmi_ctx->snoop_channel_port == ZX_HANDLE_INVALID) {
+ status = zx_port_create(0, &qmi_ctx->snoop_channel_port);
+ if (status != ZX_OK) {
+ zxlogf(ERROR,
+ "qmi-usb-transport: failed to create a port to watch snoop channel: "
+ "%s\n",
+ zx_status_get_string(status));
+ return status;
+ }
+ } else {
+ status = zx_port_wait(qmi_ctx->snoop_channel_port, 0, &packet);
+ if (status == ZX_ERR_TIMED_OUT) {
+ zxlogf(ERROR, "qmi-usb-transport: timed out: %s\n",
+ zx_status_get_string(status));
+ } else if (packet.signal.observed & ZX_CHANNEL_PEER_CLOSED) {
+ zxlogf(INFO, "qmi-usb-transport: snoop channel peer closed\n");
+ qmi_ctx->snoop_channel = ZX_HANDLE_INVALID;
+ }
+ }
+
+ if (qmi_ctx->snoop_channel != ZX_HANDLE_INVALID) {
+ zxlogf(ERROR, "snoop channel already connected\n");
+ result = ZX_ERR_ALREADY_BOUND;
+ } else if (channel == ZX_HANDLE_INVALID) {
+ zxlogf(ERROR, "get invalid snoop channel handle\n");
+ result = ZX_ERR_BAD_HANDLE;
+ } else {
+ qmi_ctx->snoop_channel = channel;
+ zx_object_wait_async(
+ qmi_ctx->snoop_channel, qmi_ctx->snoop_channel_port, 0,
+ ZX_CHANNEL_PEER_CLOSED, ZX_WAIT_ASYNC_ONCE);
+ }
+ return result;
+}
+
#define REPLY(x) fuchsia_hardware_telephony_transport_Qmi##x##_reply
static zx_status_t fidl_SetChannel(void* ctx, zx_handle_t transport, fidl_txn_t* txn) {
@@ -275,11 +320,27 @@
qmi_update_online_status(qmi_ctx, connected);
return REPLY(SetNetwork)(txn);
}
+
+static zx_status_t fidl_SetSnoopChannel(void* ctx, zx_handle_t snoop_channel, fidl_txn_t* txn) {
+ qmi_ctx_t* qmi_ctx = ctx;
+ zx_status_t set_snoop_channel_res;
+ fuchsia_hardware_telephony_transport_Qmi_SetSnoopChannel_Result res;
+ set_snoop_channel_res = set_snoop_channel(qmi_ctx, snoop_channel);
+ if (set_snoop_channel_res == ZX_OK) {
+ res.tag = 0;
+ res.response._reserved = 0;
+ } else {
+ res.tag = 1;
+ res.err = set_snoop_channel_res;
+ }
+ return REPLY(SetSnoopChannel)(txn, &res);
+}
#undef REPLY
static fuchsia_hardware_telephony_transport_Qmi_ops_t fidl_ops = {
.SetChannel = fidl_SetChannel,
.SetNetwork = fidl_SetNetworkStatus,
+ .SetSnoopChannel = fidl_SetSnoopChannel,
};
static zx_status_t qmi_message(void* ctx, fidl_msg_t* msg, fidl_txn_t* txn) {
@@ -439,6 +500,23 @@
"qmi-usb-transport: failed to write message to channel: %s\n",
zx_status_get_string(status));
}
+ if (qmi_ctx->snoop_channel) {
+ fuchsia_telephony_snoop_Message snoop_msg;
+ snoop_msg.tag = 0;
+ uint32_t current_length;
+ if (sizeof(buffer) > sizeof(snoop_msg.qmi_message.opaque_bytes)) {
+ current_length = sizeof(snoop_msg.qmi_message.opaque_bytes);
+ snoop_msg.qmi_message.is_partial_copy = true;
+ } else {
+ current_length = sizeof(buffer);
+ snoop_msg.qmi_message.is_partial_copy = false;
+ }
+ snoop_msg.qmi_message.direction = fuchsia_telephony_snoop_Direction_FROM_MODEM;
+ snoop_msg.qmi_message.timestamp = zx_clock_get_monotonic();
+ memcpy(snoop_msg.qmi_message.opaque_bytes, buffer, current_length);
+ fuchsia_telephony_snoop_PublisherSendMessage(
+ qmi_ctx->snoop_channel, &snoop_msg);
+ }
return;
default:
zxlogf(ERROR,
@@ -508,6 +586,23 @@
if (status != ZX_OK) {
return status;
}
+ if (ctx->snoop_channel) {
+ fuchsia_telephony_snoop_Message snoop_msg;
+ snoop_msg.tag = 0;
+ uint32_t current_length;
+ if (sizeof(buffer) > sizeof(snoop_msg.qmi_message.opaque_bytes)) {
+ current_length = sizeof(snoop_msg.qmi_message.opaque_bytes);
+ snoop_msg.qmi_message.is_partial_copy = true;
+ } else {
+ current_length = sizeof(buffer);
+ snoop_msg.qmi_message.is_partial_copy = false;
+ }
+ snoop_msg.qmi_message.direction = fuchsia_telephony_snoop_Direction_TO_MODEM;
+ snoop_msg.qmi_message.timestamp = zx_clock_get_monotonic();
+ memcpy(snoop_msg.qmi_message.opaque_bytes, buffer, current_length);
+ fuchsia_telephony_snoop_PublisherSendMessage(
+ ctx->snoop_channel, &snoop_msg);
+ }
} else if (packet.key == INTERRUPT_MSG) {
if (txn->response.status == ZX_OK) {
qmi_handle_interrupt(ctx, txn);
diff --git a/src/connectivity/telephony/lib/qmi/BUILD.gn b/src/connectivity/telephony/lib/qmi/BUILD.gn
index a2738380..2579cc7 100644
--- a/src/connectivity/telephony/lib/qmi/BUILD.gn
+++ b/src/connectivity/telephony/lib/qmi/BUILD.gn
@@ -8,10 +8,12 @@
rustc_library("qmi") {
edition = "2018"
deps = [
+ "//garnet/public/lib/fidl/rust/fidl",
"//garnet/public/rust/fdio",
"//garnet/public/rust/fuchsia-async",
"//garnet/public/rust/fuchsia-zircon",
"//third_party/rust_crates:failure",
"//zircon/public/fidl/fuchsia-hardware-telephony-transport:fuchsia-hardware-telephony-transport-rustc",
+ "//zircon/public/fidl/fuchsia-telephony-snoop:fuchsia-telephony-snoop-rustc",
]
}
diff --git a/src/connectivity/telephony/lib/qmi/src/lib.rs b/src/connectivity/telephony/lib/qmi/src/lib.rs
index 1a48ca1..0b59b9c 100644
--- a/src/connectivity/telephony/lib/qmi/src/lib.rs
+++ b/src/connectivity/telephony/lib/qmi/src/lib.rs
@@ -3,11 +3,28 @@
// found in the LICENSE file.
#![feature(async_await, await_macro)]
+use fidl::endpoints::{create_endpoints, ServerEnd};
use fidl_fuchsia_hardware_telephony_transport::QmiProxy;
+use fidl_fuchsia_telephony_snoop::PublisherMarker as QmiSnoopMarker;
use fuchsia_async as fasync;
use fuchsia_zircon as zx;
use std::fs::File;
+/// Connect to transport driver, and pass a channel handle for snoop Qmi messages
+pub async fn connect_snoop_channel(
+ device: &File,
+) -> Result<ServerEnd<QmiSnoopMarker>, failure::Error> {
+ let qmi_channel: fasync::Channel = fasync::Channel::from_channel(fdio::clone_channel(device)?)?;
+ let interface = QmiProxy::new(qmi_channel);
+ let (client_side, server_side) = create_endpoints::<QmiSnoopMarker>()?;
+ match await!(interface.set_snoop_channel(client_side)) {
+ Ok(_r) => Ok(server_side),
+ Err(e) => Err(e.into()),
+ }
+}
+
+/// Connect to transport driver, and pass a channel handle for Tx/Rx Qmi messages
+/// to/from ril-qmi
pub async fn connect_transport_device(device: &File) -> Result<zx::Channel, failure::Error> {
let qmi_channel: fasync::Channel = fasync::Channel::from_channel(fdio::clone_channel(device)?)?;
let interface = QmiProxy::new(qmi_channel);
diff --git a/src/connectivity/telephony/tools/BUILD.gn b/src/connectivity/telephony/tools/BUILD.gn
index 339907f..d1bfea5 100644
--- a/src/connectivity/telephony/tools/BUILD.gn
+++ b/src/connectivity/telephony/tools/BUILD.gn
@@ -5,6 +5,7 @@
group("tools") {
testonly = true
deps = [
+ "qmi-snoop",
"ril-ctl",
]
}
diff --git a/src/connectivity/telephony/tools/qmi-snoop/BUILD.gn b/src/connectivity/telephony/tools/qmi-snoop/BUILD.gn
new file mode 100644
index 0000000..c4f3179
--- /dev/null
+++ b/src/connectivity/telephony/tools/qmi-snoop/BUILD.gn
@@ -0,0 +1,36 @@
+# Copyright 2018 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/package.gni")
+import("//build/rust/rustc_binary.gni")
+
+rustc_binary("bin") {
+ name = "qmi_snoop"
+ edition = "2018"
+
+ deps = [
+ "//garnet/public/lib/fidl/rust/fidl",
+ "//garnet/public/rust/fuchsia-async",
+ "//src/connectivity/telephony/lib/qmi",
+ "//third_party/rust_crates:failure",
+ "//third_party/rust_crates:futures-preview",
+ "//third_party/rust_crates:structopt",
+ "//zircon/public/fidl/fuchsia-telephony-snoop:fuchsia-telephony-snoop-rustc",
+ ]
+}
+
+package("qmi-snoop") {
+ deps = [
+ ":bin",
+ ]
+
+ binaries = [
+ {
+ name = "qmi_snoop"
+ dest = "qmi-snoop"
+ path = "rust_crates/qmi_snoop"
+ shell = true
+ },
+ ]
+}
diff --git a/src/connectivity/telephony/tools/qmi-snoop/src/main.rs b/src/connectivity/telephony/tools/qmi-snoop/src/main.rs
new file mode 100644
index 0000000..1b62a15
--- /dev/null
+++ b/src/connectivity/telephony/tools/qmi-snoop/src/main.rs
@@ -0,0 +1,70 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//! qmi-snoop is used for snooping Qmi messages sent/received by transport driver
+
+#![feature(async_await, await_macro)]
+
+use {
+ failure::{Error, ResultExt},
+ fidl::endpoints::ServerEnd,
+ fidl_fuchsia_telephony_snoop::{
+ Message as SnoopMessage, PublisherMarker as QmiSnoopMarker,
+ PublisherRequest as QmiSnoopRequest, PublisherRequestStream as QmiSnoopRequestStream,
+ },
+ fuchsia_async as fasync, futures,
+ futures::stream::TryStreamExt,
+ qmi,
+ std::fs::File,
+ std::path::PathBuf,
+ structopt::StructOpt,
+};
+
+#[derive(StructOpt, Debug)]
+#[structopt(name = "qmi-snoop")]
+struct Opt {
+ /// Device path (e.g. /dev/class/qmi-transport/000)
+ #[structopt(short = "d", long = "device", parse(from_os_str))]
+ device: Option<PathBuf>,
+}
+
+pub fn main() -> Result<(), Error> {
+ let mut exec = fasync::Executor::new().context("error creating event loop")?;
+ let args = Opt::from_args();
+ let device = match args.device {
+ Some(device_path) => device_path,
+ None => PathBuf::from("/dev/class/qmi-transport/000"),
+ };
+ let fut = async move {
+ eprintln!("Connecting with exclusive access to {}..", device.display());
+ let file: File = File::open(device)?;
+ let snoop_endpoint_server_side: ServerEnd<QmiSnoopMarker> =
+ await!(qmi::connect_snoop_channel(&file))?;
+ let mut request_stream: QmiSnoopRequestStream = snoop_endpoint_server_side.into_stream()?;
+ while let Ok(Some(QmiSnoopRequest::SendMessage { msg, control_handle: _ })) =
+ await!(request_stream.try_next())
+ {
+ let qmi_message = match msg {
+ SnoopMessage::QmiMessage(m) => Some(m),
+ };
+ match qmi_message {
+ Some(message) => {
+ let slice = &message.opaque_bytes;
+ eprint!(
+ "Received msg direction: {:?}, timestamp: {}, msg:",
+ message.direction, message.timestamp
+ );
+ for element in slice.iter() {
+ eprint!(" {}", element);
+ }
+ eprint!("\n");
+ }
+ None => {}
+ }
+ }
+ eprintln!("unexpected msg received");
+ Ok::<_, Error>(())
+ };
+ exec.run_singlethreaded(fut)
+}
diff --git a/zircon/system/fidl/BUILD.gn b/zircon/system/fidl/BUILD.gn
index 5202474..5800afe 100644
--- a/zircon/system/fidl/BUILD.gn
+++ b/zircon/system/fidl/BUILD.gn
@@ -74,6 +74,7 @@
"fuchsia-sysmem",
"fuchsia-tee",
"fuchsia-tee-manager",
+ "fuchsia-telephony-snoop",
"fuchsia-tracelink",
"fuchsia-tracing-kernel",
"fuchsia-usb-debug",
diff --git a/zircon/system/fidl/fuchsia-hardware-telephony-transport/BUILD.gn b/zircon/system/fidl/fuchsia-hardware-telephony-transport/BUILD.gn
index 29fdc15..cb1b8d7 100644
--- a/zircon/system/fidl/fuchsia-hardware-telephony-transport/BUILD.gn
+++ b/zircon/system/fidl/fuchsia-hardware-telephony-transport/BUILD.gn
@@ -8,4 +8,8 @@
sources = [
"qmi.fidl",
]
+
+ public_deps = [
+ "$zx/system/fidl/fuchsia-telephony-snoop:fuchsia-telephony-snoop",
+ ]
}
diff --git a/zircon/system/fidl/fuchsia-hardware-telephony-transport/qmi.fidl b/zircon/system/fidl/fuchsia-hardware-telephony-transport/qmi.fidl
index dc6556e..56cd55f 100644
--- a/zircon/system/fidl/fuchsia-hardware-telephony-transport/qmi.fidl
+++ b/zircon/system/fidl/fuchsia-hardware-telephony-transport/qmi.fidl
@@ -5,6 +5,7 @@
library fuchsia.hardware.telephony.transport;
using zx;
+using fuchsia.telephony.snoop as qmi_snoop;
[Layout = "Simple"]
protocol Qmi {
@@ -14,4 +15,7 @@
/// Configure the network used by the transport
/// Currently only sets network up/down
SetNetwork(bool connected) -> ();
+
+ /// Pass an interface for QMI message snooping
+ SetSnoopChannel(qmi_snoop.Publisher interface) -> () error zx.status;
};
diff --git a/zircon/system/fidl/fuchsia-telephony-snoop/BUILD.gn b/zircon/system/fidl/fuchsia-telephony-snoop/BUILD.gn
new file mode 100644
index 0000000..efff89e
--- /dev/null
+++ b/zircon/system/fidl/fuchsia-telephony-snoop/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("$zx/public/gn/fidl.gni")
+
+fidl_library("fuchsia-telephony-snoop") {
+ sources = [
+ "tel-snoop.fidl",
+ ]
+}
diff --git a/zircon/system/fidl/fuchsia-telephony-snoop/tel-snoop.fidl b/zircon/system/fidl/fuchsia-telephony-snoop/tel-snoop.fidl
new file mode 100644
index 0000000..7f6ad1e
--- /dev/null
+++ b/zircon/system/fidl/fuchsia-telephony-snoop/tel-snoop.fidl
@@ -0,0 +1,30 @@
+// Copyright 2019 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+library fuchsia.telephony.snoop;
+
+using zx;
+
+enum Direction {
+ FROM_MODEM = 1;
+ TO_MODEM = 2;
+};
+
+struct QmiMessage {
+ zx.time timestamp;
+ Direction direction;
+ bool is_partial_copy;
+ array<uint8>:256 opaque_bytes;
+};
+
+//TODO(jiamingw): change it to xunion after transport driver is converted to llcpp
+union Message {
+ QmiMessage qmi_message;
+};
+
+/// Protocol for forwarding QMI messages from driver to Snoop CLI
+[Layout = "Simple"]
+protocol Publisher {
+ SendMessage(Message msg);
+};