You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.1 KiB
177 lines
4.1 KiB
/* |
|
* Copyright (c) 2019 Intel corporation |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
/* Disable syscall tracing for all calls from this compilation unit to avoid |
|
* undefined symbols as the macros are not expanded recursively |
|
*/ |
|
#define DISABLE_SYSCALL_TRACING |
|
|
|
#include <zephyr/sys/util.h> |
|
#include <zephyr/sys/atomic.h> |
|
#include <zephyr/sys/__assert.h> |
|
#include <zephyr/sys/byteorder.h> |
|
#include <zephyr/usb/usb_device.h> |
|
#include <tracing_core.h> |
|
#include <tracing_buffer.h> |
|
#include <tracing_backend.h> |
|
|
|
#define USB_TRANSFER_ONGOING 1 |
|
#define USB_TRANSFER_FREE 0 |
|
|
|
#define TRACING_IF_IN_EP_ADDR 0x81 |
|
#define TRACING_IF_OUT_EP_ADDR 0x01 |
|
|
|
struct usb_device_desc { |
|
struct usb_if_descriptor if0; |
|
struct usb_ep_descriptor if0_in_ep; |
|
struct usb_ep_descriptor if0_out_ep; |
|
} __packed; |
|
|
|
static volatile int transfer_state; |
|
static enum usb_dc_status_code usb_device_status = USB_DC_UNKNOWN; |
|
|
|
USBD_CLASS_DESCR_DEFINE(primary, 0) struct usb_device_desc dev_desc = { |
|
/* |
|
* Interface descriptor 0 |
|
*/ |
|
.if0 = { |
|
.bLength = sizeof(struct usb_if_descriptor), |
|
.bDescriptorType = USB_DESC_INTERFACE, |
|
.bInterfaceNumber = 0, |
|
.bAlternateSetting = 0, |
|
.bNumEndpoints = 2, |
|
.bInterfaceClass = USB_BCC_VENDOR, |
|
.bInterfaceSubClass = 0, |
|
.bInterfaceProtocol = 0, |
|
.iInterface = 0, |
|
}, |
|
|
|
/* |
|
* Data Endpoint IN |
|
*/ |
|
.if0_in_ep = { |
|
.bLength = sizeof(struct usb_ep_descriptor), |
|
.bDescriptorType = USB_DESC_ENDPOINT, |
|
.bEndpointAddress = TRACING_IF_IN_EP_ADDR, |
|
.bmAttributes = USB_DC_EP_BULK, |
|
.wMaxPacketSize = sys_cpu_to_le16(CONFIG_TRACING_USB_MPS), |
|
.bInterval = 0x00, |
|
}, |
|
|
|
/* |
|
* Data Endpoint OUT |
|
*/ |
|
.if0_out_ep = { |
|
.bLength = sizeof(struct usb_ep_descriptor), |
|
.bDescriptorType = USB_DESC_ENDPOINT, |
|
.bEndpointAddress = TRACING_IF_OUT_EP_ADDR, |
|
.bmAttributes = USB_DC_EP_BULK, |
|
.wMaxPacketSize = sys_cpu_to_le16(CONFIG_TRACING_USB_MPS), |
|
.bInterval = 0x00, |
|
}, |
|
}; |
|
|
|
static void dev_status_cb(struct usb_cfg_data *cfg, |
|
enum usb_dc_status_code status, |
|
const uint8_t *param) |
|
{ |
|
ARG_UNUSED(cfg); |
|
ARG_UNUSED(param); |
|
|
|
usb_device_status = status; |
|
} |
|
|
|
static void tracing_ep_out_cb(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) |
|
{ |
|
uint8_t *cmd = NULL; |
|
uint32_t bytes_to_read, length; |
|
|
|
usb_read(ep, NULL, 0, &bytes_to_read); |
|
|
|
while (bytes_to_read) { |
|
length = tracing_cmd_buffer_alloc(&cmd); |
|
if (cmd) { |
|
length = MIN(length, bytes_to_read); |
|
usb_read(ep, cmd, length, NULL); |
|
tracing_cmd_handle(cmd, length); |
|
|
|
bytes_to_read -= length; |
|
} |
|
} |
|
|
|
/* |
|
* send ZLP to sync with host receive thread |
|
*/ |
|
usb_write(TRACING_IF_IN_EP_ADDR, NULL, 0, NULL); |
|
} |
|
|
|
static void tracing_ep_in_cb(uint8_t ep, enum usb_dc_ep_cb_status_code ep_status) |
|
{ |
|
ARG_UNUSED(ep); |
|
ARG_UNUSED(ep_status); |
|
|
|
transfer_state = USB_TRANSFER_FREE; |
|
} |
|
|
|
static struct usb_ep_cfg_data ep_cfg[] = { |
|
{ |
|
.ep_cb = tracing_ep_out_cb, |
|
.ep_addr = TRACING_IF_OUT_EP_ADDR, |
|
}, |
|
{ |
|
.ep_cb = tracing_ep_in_cb, |
|
.ep_addr = TRACING_IF_IN_EP_ADDR, |
|
}, |
|
}; |
|
|
|
USBD_DEFINE_CFG_DATA(tracing_backend_usb_config) = { |
|
.usb_device_description = NULL, |
|
.interface_descriptor = &dev_desc.if0, |
|
.cb_usb_status = dev_status_cb, |
|
.interface = { |
|
.class_handler = NULL, |
|
.custom_handler = NULL, |
|
.vendor_handler = NULL, |
|
}, |
|
.num_endpoints = ARRAY_SIZE(ep_cfg), |
|
.endpoint = ep_cfg, |
|
}; |
|
|
|
static void tracing_backend_usb_output(const struct tracing_backend *backend, |
|
uint8_t *data, uint32_t length) |
|
{ |
|
int ret = 0; |
|
uint32_t bytes; |
|
|
|
while (length > 0) { |
|
transfer_state = USB_TRANSFER_ONGOING; |
|
|
|
/* |
|
* make sure every USB transfer no need ZLP at all |
|
* because we are in lowest priority thread content |
|
* there are no deterministic time between real USB |
|
* packet and ZLP |
|
*/ |
|
ret = usb_write(TRACING_IF_IN_EP_ADDR, data, |
|
length >= CONFIG_TRACING_USB_MPS ? |
|
CONFIG_TRACING_USB_MPS - 1 : length, &bytes); |
|
if (ret) { |
|
continue; |
|
} |
|
|
|
data += bytes; |
|
length -= bytes; |
|
|
|
while (transfer_state == USB_TRANSFER_ONGOING) { |
|
} |
|
} |
|
} |
|
|
|
const struct tracing_backend_api tracing_backend_usb_api = { |
|
.output = tracing_backend_usb_output |
|
}; |
|
|
|
TRACING_BACKEND_DEFINE(tracing_backend_usb, tracing_backend_usb_api);
|
|
|