mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-08-14 02:30:28 +03:00
firmware: Implement debug command via USB control vendor class
Allows to collect talloc reports and other debug information from a script while the remsim-client is still running. Change-Id: I1f4d29335eb0d2feef376b8ecdfe57a0162914d6
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2026 sysmocom -s.f.m.c. GmbH, Author: Alexander Couzens <lynxis@fe80.eu>
|
||||
# License: MIT
|
||||
|
||||
import sys
|
||||
import usb.util
|
||||
from usb.core import USBError
|
||||
|
||||
TIMEOUT = 3
|
||||
|
||||
# simtrace2 vendor requets
|
||||
SIMTRACER_VENDOR_REQ_GET_DEBUG_INFO = 0
|
||||
|
||||
def vendor_get_debug(device: usb.core.Device):
|
||||
return vendor_req_in(device, bRequest = SIMTRACER_VENDOR_REQ_GET_DEBUG_INFO, wValue = 0, wIndex = 0, length = 32)
|
||||
|
||||
def vendor_req_in(device: usb.core.Device, bRequest: int, wValue: int, wIndex: int, length: int = 8):
|
||||
""" do a vendor request in (device -> host)
|
||||
@param bRequest: usb single byte
|
||||
@param wIndex: short index
|
||||
"""
|
||||
return device.ctrl_transfer(
|
||||
bmRequestType=usb.util.ENDPOINT_IN
|
||||
| usb.util.CTRL_TYPE_VENDOR
|
||||
| usb.util.CTRL_RECIPIENT_DEVICE,
|
||||
bRequest=bRequest,
|
||||
wValue=wValue,
|
||||
wIndex=wIndex,
|
||||
data_or_wLength=length,
|
||||
timeout=TIMEOUT,
|
||||
)
|
||||
|
||||
def find_simtrace(vendor = 0x1d50, product = 0x60e3, find_all = False):
|
||||
return usb.core.find(find_all=find_all, idVendor=vendor, idProduct=product)
|
||||
|
||||
def get_path(device: usb.core.Device):
|
||||
ports = ".".join([str(x) for x in device.port_numbers])
|
||||
return f"{device.bus}-{ports}"
|
||||
|
||||
def per_device(device: usb.core.Device, args: argparse.Namespace):
|
||||
if args.get_debug:
|
||||
result = vendor_get_debug(device)
|
||||
print(f"{get_path(device)} / {device.serial_number}: {result}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(prog='simtrace-util')
|
||||
# actions
|
||||
parser.add_argument(
|
||||
"--get-debug",
|
||||
action='store_true',
|
||||
help="Get debug")
|
||||
|
||||
# device selection
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--all",
|
||||
action='store_true',
|
||||
help="Run the request against all simtrace2 devices.")
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--serial",
|
||||
help="Select the simtrace2 by serial")
|
||||
parser.add_argument(
|
||||
"--vendor",
|
||||
type=int,
|
||||
help="Use a different USB vendor. Default Openmoko 0x1d50.")
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--product",
|
||||
type=int,
|
||||
help="Use a different USB product. Default simtrace2 0x60e3.\n"
|
||||
"qmod: 0x4004")
|
||||
|
||||
args = parser.parse_args()
|
||||
# no action given
|
||||
if not args.get_debug:
|
||||
parser.print_usage()
|
||||
sys.exit(1)
|
||||
|
||||
vendor = 0x1d50
|
||||
product = 0x60e3
|
||||
if args.product:
|
||||
product = args.product
|
||||
if args.vendor:
|
||||
vendor = args.vendor
|
||||
if args.serial:
|
||||
device = find_simtrace(vendor=vendor, product=product, find_all=args.all, serial_number=args.serial_number)
|
||||
else:
|
||||
device = find_simtrace(vendor=vendor, product=product, find_all=args.all)
|
||||
|
||||
if not device:
|
||||
print("Could not find a single board", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if type(device) == usb.core.Device:
|
||||
per_device(device, args)
|
||||
else:
|
||||
for dev in device:
|
||||
per_device(dev, args)
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "board.h"
|
||||
#include "simtrace.h"
|
||||
#include "talloc.h"
|
||||
#include "utils.h"
|
||||
#include "main_common.h"
|
||||
#include <osmocom/core/timer.h>
|
||||
@@ -39,6 +40,8 @@ typedef struct {
|
||||
void (*usart0_irq) (void);
|
||||
/* Interrupt handler for USART1 */
|
||||
void (*usart1_irq) (void);
|
||||
/* ctrl vendor request handler */
|
||||
void (*ctrl_vendor_req) (const USBGenericRequest *request);
|
||||
} conf_func;
|
||||
|
||||
static const conf_func config_func_ptrs[] = {
|
||||
@@ -74,6 +77,7 @@ static const conf_func config_func_ptrs[] = {
|
||||
.usart0_irq = mode_cardemu_usart0_irq,
|
||||
.usart1_irq = mode_cardemu_usart1_irq,
|
||||
#endif
|
||||
.ctrl_vendor_req = mode_cardemu_ctrl_vendor_req,
|
||||
},
|
||||
#endif
|
||||
#ifdef HAVE_MITM
|
||||
@@ -137,6 +141,26 @@ static void check_exec_dbg_cmd(void)
|
||||
board_exec_dbg_cmd(ch);
|
||||
}
|
||||
|
||||
void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
|
||||
{
|
||||
if (USBGenericRequest_GetType(request) != USBGenericRequest_VENDOR)
|
||||
return USBDDriver_RequestHandler(USBD_GetDriver(), request);
|
||||
|
||||
|
||||
if (config_func_ptrs[simtrace_config].ctrl_vendor_req)
|
||||
config_func_ptrs[simtrace_config].ctrl_vendor_req(request);
|
||||
else {
|
||||
/* only ctrl in is supported */
|
||||
if (USBGenericRequest_GetDirection(request) == USBGenericRequest_IN)
|
||||
/* Return ZLP */
|
||||
USBD_Write(0, NULL, 0, NULL, NULL);
|
||||
else /* stall Ctrl out vendor requests */
|
||||
USBD_Stall(0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Main
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
@@ -120,6 +120,9 @@ extern void Sniffer_usart1_irq(void);
|
||||
extern void mode_cardemu_usart0_irq(void);
|
||||
extern void mode_cardemu_usart1_irq(void);
|
||||
|
||||
/* Vendor request functions */
|
||||
void mode_cardemu_ctrl_vendor_req(const USBGenericRequest *request);
|
||||
|
||||
/* Timer helper function */
|
||||
void Timer_Init( void );
|
||||
void TC0_Counter_Reset( void );
|
||||
|
||||
@@ -86,6 +86,12 @@ enum simtrace_msg_type_sniff {
|
||||
SIMTRACE_MSGT_SNIFF_TPDU,
|
||||
};
|
||||
|
||||
/* Simtrace ctrl vendor requests */
|
||||
enum simtrace_vendor_req {
|
||||
/* get debug infos */
|
||||
SIMTRACER_VENDOR_REQ_GET_DEBUG_INFO = 0,
|
||||
};
|
||||
|
||||
/* common message header */
|
||||
struct simtrace_msg_hdr {
|
||||
uint8_t msg_class; /* simtrace_msg_class */
|
||||
|
||||
@@ -689,6 +689,42 @@ void mode_cardemu_exit(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void mode_cardemu_ctrl_vendor_req(const USBGenericRequest *request)
|
||||
{
|
||||
if (USBGenericRequest_GetRecipient(request) != USBGenericRequest_DEVICE) {
|
||||
USBD_Stall(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (USBGenericRequest_GetDirection(request) != USBGenericRequest_IN) {
|
||||
USBD_Stall(0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t req = USBGenericRequest_GetRequest(request);
|
||||
uint8_t buf[32] = {};
|
||||
uint8_t len = 0;
|
||||
unsigned int used, i;
|
||||
switch (req) {
|
||||
case SIMTRACER_VENDOR_REQ_GET_DEBUG_INFO:
|
||||
/* don't use msgb here to prevent an additional allocation */
|
||||
used = talloc_report_buf(&buf[0], 16);
|
||||
/* add queues */
|
||||
for (i = 0; i < ARRAY_SIZE(cardem_inst); i++) {
|
||||
struct cardem_inst *ci = &cardem_inst[i];
|
||||
buf[used++] = i + 1;
|
||||
buf[used++] = usb_get_buf_ep(ci->ep_in)->queue_len;
|
||||
buf[used++] = usb_get_buf_ep(ci->ep_out)->queue_len;
|
||||
buf[used++] = usb_get_buf_ep(ci->ep_int)->queue_len;
|
||||
}
|
||||
USBD_Write(0, &buf, used, 0, 0);
|
||||
break;
|
||||
default:
|
||||
USBD_Stall(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle a single USB command as received from the USB host */
|
||||
static void dispatch_usb_command_generic(struct msgb *msg, struct cardem_inst *ci)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user