[ndebug] Setup NDebug endpoints and create a bidirectional serial pipe over USB.
This commit is contained in:
0
lib/ndebug/README.md
Normal file
0
lib/ndebug/README.md
Normal file
51
lib/ndebug/include/lib/ndebug/ndebug.h
Normal file
51
lib/ndebug/include/lib/ndebug/ndebug.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc. All Rights Reserved.
|
||||
* Author: gkalsi@google.com (Gurjant Kalsi)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <compiler.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define NDEBUG_MAX_PACKET_SIZE (64)
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
typedef enum {
|
||||
NDEBUG_CHANNEL_SYS,
|
||||
NDEBUG_CHANNEL_USR,
|
||||
|
||||
NDEBUG_CHANNEL_COUNT, // Count: always last.
|
||||
} channel_t;
|
||||
|
||||
void ndebug_init(void);
|
||||
|
||||
ssize_t ndebug_usb_read(const channel_t ch, const size_t n,
|
||||
const lk_time_t timeout, uint8_t *buf);
|
||||
ssize_t ndebug_usb_write(const channel_t ch, const size_t n,
|
||||
const lk_time_t timeout, uint8_t *buf);
|
||||
|
||||
status_t await_usb_online(lk_time_t timeout);
|
||||
|
||||
__END_CDECLS
|
||||
44
lib/ndebug/include/lib/ndebug/shared_structs.h
Normal file
44
lib/ndebug/include/lib/ndebug/shared_structs.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc. All Rights Reserved.
|
||||
* Author: gkalsi@google.com (Gurjant Kalsi)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint32_t magic;
|
||||
uint32_t type;
|
||||
} ndebug_ctrl_packet_t;
|
||||
|
||||
#define NDEBUG_CTRL_PACKET_MAGIC (0x4354524C)
|
||||
|
||||
#define NDEBUG_CTRL_CMD_RESET (0x01)
|
||||
#define NDEBUG_CTRL_CMD_DATA (0x02)
|
||||
#define NDEBUG_CTRL_CMD_ESTABLISHED (0x03)
|
||||
|
||||
#define NDEBUG_USB_CLASS_USER_DEFINED (0xFF)
|
||||
#define NDEBUG_SUBCLASS (0x02)
|
||||
|
||||
#define NDEBUG_PROTOCOL_LK_SYSTEM (0x01)
|
||||
#define NDEBUG_PROTOCOL_SERIAL_PIPE (0x02)
|
||||
43
lib/ndebug/include/lib/ndebug/user.h
Normal file
43
lib/ndebug/include/lib/ndebug/user.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc. All Rights Reserved.
|
||||
* Author: gkalsi@google.com (Gurjant Kalsi)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <compiler.h>
|
||||
#include <lib/ndebug/ndebug.h>
|
||||
#include <lib/ndebug/shared_structs.h>
|
||||
|
||||
__BEGIN_CDECLS
|
||||
|
||||
#define NDEBUG_USR_MAX_PACKET_SIZE (NDEBUG_MAX_PACKET_SIZE - sizeof(ndebug_ctrl_packet_t))
|
||||
|
||||
// Read and write to the NDebug user channel.
|
||||
ssize_t ndebug_read_usr(uint8_t *buf, const lk_time_t timeout);
|
||||
ssize_t ndebug_write_usr(uint8_t *buf, const size_t n, const lk_time_t timeout);
|
||||
|
||||
|
||||
// Wait for the host to establish a connection on the usr channel.
|
||||
status_t ndebugusr_await_host(lk_time_t timeout);
|
||||
|
||||
__END_CDECLS
|
||||
225
lib/ndebug/ndebug.c
Normal file
225
lib/ndebug/ndebug.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc. All Rights Reserved.
|
||||
* Author: gkalsi@google.com (Gurjant Kalsi)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <lib/ndebug/ndebug.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <dev/udc.h>
|
||||
#include <dev/usb.h>
|
||||
#include <dev/usbc.h>
|
||||
#include <err.h>
|
||||
#include <kernel/event.h>
|
||||
#include <string.h>
|
||||
|
||||
#define W(w) (w & 0xff), (w >> 8)
|
||||
#define W3(w) (w & 0xff), ((w >> 8) & 0xff), ((w >> 16) & 0xff)
|
||||
|
||||
#define IFACE_SUBCLASS_IDX (0x06)
|
||||
#define IFACE_PROTOCOL_IDX (0x07)
|
||||
#define IFACE_IN_ADDR_IDX (0x0B)
|
||||
#define IFACE_OUT_ADDR_IDX (0x12)
|
||||
|
||||
#define CH_TO_ADDR(CH) ((CH) + 1)
|
||||
#define CHECK_CHANNEL(CH) \
|
||||
do { DEBUG_ASSERT((CH) < NDEBUG_CHANNEL_COUNT); } while (false);
|
||||
|
||||
#define SYS_EP_ADDR (CH_TO_ADDR(NDEBUG_CHANNEL_SYS))
|
||||
#define USR_EP_ADDR (CH_TO_ADDR(NDEBUG_CHANNEL_USR))
|
||||
|
||||
#define NDEBUG_SUBCLASS (0x02)
|
||||
|
||||
#define NDEBUG_PROTOCOL_LK_SYSTEM (0x01)
|
||||
#define NDEBUG_PROTOCOL_SERIAL_PIPE (0x02)
|
||||
|
||||
static usbc_transfer_t rx_transfer[NDEBUG_CHANNEL_COUNT];
|
||||
static usbc_transfer_t tx_transfer[NDEBUG_CHANNEL_COUNT];
|
||||
|
||||
static event_t rx_event[NDEBUG_CHANNEL_COUNT];
|
||||
static event_t tx_event[NDEBUG_CHANNEL_COUNT];
|
||||
|
||||
static event_t usb_online_event;
|
||||
|
||||
static const uint8_t bulk_pair_descriptor_template[] = {
|
||||
0x09, /* length */
|
||||
INTERFACE, /* type */
|
||||
0x00, /* interface num - Unused, patched in by dev/usb */
|
||||
0x00, /* alternates */
|
||||
0x02, /* endpoint count */
|
||||
0xff, /* interface class - User Deficned */
|
||||
0x00, /* interface subclass - Patched by client */
|
||||
0x00, /* interface protocol - Patched by client */
|
||||
0x00, /* string index */
|
||||
|
||||
/* endpoint 1 IN */
|
||||
0x07, /* length */
|
||||
ENDPOINT, /* type */
|
||||
0x80, /* address - Patched by Client */
|
||||
0x02, /* type: bulk */
|
||||
W(64), /* max packet size: 64 */
|
||||
00, /* interval - unused for bulk */
|
||||
|
||||
/* endpoint 1 OUT */
|
||||
0x07, /* length */
|
||||
ENDPOINT, /* type */
|
||||
0x00, /* address - Patched by client */
|
||||
0x02, /* type: bulk */
|
||||
W(64), /* max packet size: 64 */
|
||||
00, /* interval - unused for bulk */
|
||||
};
|
||||
|
||||
static void init_channel(uint8_t subclass, uint8_t protocol, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t desc[sizeof(bulk_pair_descriptor_template)];
|
||||
|
||||
// Make a copy of the template descriptor and fill in the missing fields.
|
||||
memcpy(desc, bulk_pair_descriptor_template,
|
||||
sizeof(bulk_pair_descriptor_template));
|
||||
|
||||
desc[IFACE_SUBCLASS_IDX] = subclass;
|
||||
desc[IFACE_PROTOCOL_IDX] = protocol;
|
||||
desc[IFACE_IN_ADDR_IDX] = ep_addr | 0x80;
|
||||
desc[IFACE_OUT_ADDR_IDX] = ep_addr;
|
||||
|
||||
// Append the interfaces.
|
||||
usb_append_interface_lowspeed(desc, sizeof(desc));
|
||||
usb_append_interface_highspeed(desc, sizeof(desc));
|
||||
}
|
||||
|
||||
static void setup_usb_endpoint(uint8_t ep_num)
|
||||
{
|
||||
usbc_setup_endpoint(ep_num, USB_IN, 0x40, USB_BULK);
|
||||
usbc_setup_endpoint(ep_num, USB_OUT, 0x40, USB_BULK);
|
||||
}
|
||||
|
||||
static status_t ndebug_register_cb(
|
||||
void *cookie,
|
||||
usb_callback_op_t op,
|
||||
const union usb_callback_args *args
|
||||
)
|
||||
{
|
||||
if (op == USB_CB_ONLINE) {
|
||||
for (channel_t ch = 0; ch < NDEBUG_CHANNEL_COUNT; ++ch) {
|
||||
setup_usb_endpoint(CH_TO_ADDR(ch));
|
||||
}
|
||||
event_signal(&usb_online_event, false);
|
||||
} else if (op == USB_CB_RESET || op == USB_CB_DISCONNECT ||
|
||||
op == USB_CB_OFFLINE) {
|
||||
event_unsignal(&usb_online_event);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void ndebug_init(void)
|
||||
{
|
||||
for (channel_t ch = 0; ch < NDEBUG_CHANNEL_COUNT; ++ch) {
|
||||
event_init(&rx_event[ch], 0, EVENT_FLAG_AUTOUNSIGNAL);
|
||||
event_init(&tx_event[ch], 0, EVENT_FLAG_AUTOUNSIGNAL);
|
||||
}
|
||||
|
||||
init_channel(NDEBUG_SUBCLASS, NDEBUG_PROTOCOL_LK_SYSTEM, SYS_EP_ADDR);
|
||||
init_channel(NDEBUG_SUBCLASS, NDEBUG_PROTOCOL_SERIAL_PIPE, USR_EP_ADDR);
|
||||
|
||||
event_init(&usb_online_event, 0, 0);
|
||||
|
||||
usb_register_callback(&ndebug_register_cb, NULL);
|
||||
}
|
||||
|
||||
static status_t usb_xmit_cplt_cb(ep_t endpoint, usbc_transfer_t *t)
|
||||
{
|
||||
uint32_t channel = (uint32_t)t->extra;
|
||||
CHECK_CHANNEL(channel);
|
||||
|
||||
event_signal(&tx_event[channel], false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static status_t usb_recv_cplt_cb(ep_t endpoint, usbc_transfer_t *t)
|
||||
{
|
||||
uint32_t channel = (uint32_t)t->extra;
|
||||
CHECK_CHANNEL(channel);
|
||||
|
||||
event_signal(&rx_event[channel], false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t ndebug_usb_read(const channel_t ch, const size_t n,
|
||||
const lk_time_t timeout, uint8_t *buf)
|
||||
{
|
||||
CHECK_CHANNEL(ch);
|
||||
|
||||
usbc_transfer_t *transfer = &rx_transfer[ch];
|
||||
|
||||
transfer->callback = &usb_recv_cplt_cb;
|
||||
transfer->result = 0;
|
||||
transfer->buf = buf;
|
||||
transfer->buflen = n;
|
||||
transfer->bufpos = 0;
|
||||
transfer->extra = (void *)ch;
|
||||
|
||||
usbc_queue_rx(CH_TO_ADDR(ch), transfer);
|
||||
status_t res = event_wait_timeout(&rx_event[ch], timeout);
|
||||
|
||||
if (res != NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (transfer->result != NO_ERROR) {
|
||||
return transfer->result;
|
||||
}
|
||||
|
||||
return transfer->bufpos;
|
||||
}
|
||||
|
||||
ssize_t ndebug_usb_write(const channel_t ch, const size_t n,
|
||||
const lk_time_t timeout, uint8_t *buf)
|
||||
{
|
||||
CHECK_CHANNEL(ch);
|
||||
|
||||
usbc_transfer_t *transfer = &tx_transfer[ch];
|
||||
|
||||
transfer->callback = &usb_xmit_cplt_cb,
|
||||
transfer->result = 0,
|
||||
transfer->buf = buf,
|
||||
transfer->buflen = n,
|
||||
transfer->bufpos = 0,
|
||||
transfer->extra = (void *)ch,
|
||||
|
||||
usbc_queue_tx(CH_TO_ADDR(ch), transfer);
|
||||
status_t res = event_wait_timeout(&tx_event[ch], timeout);
|
||||
|
||||
if (res != NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (transfer->result != NO_ERROR) {
|
||||
return transfer->result;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
status_t await_usb_online(lk_time_t timeout)
|
||||
{
|
||||
return event_wait_timeout(&usb_online_event, timeout);
|
||||
}
|
||||
12
lib/ndebug/rules.mk
Normal file
12
lib/ndebug/rules.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
# MODULE_DEPS := \
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/ndebug.c \
|
||||
$(LOCAL_DIR)/user.c \
|
||||
|
||||
|
||||
include make/module.mk
|
||||
216
lib/ndebug/user.c
Normal file
216
lib/ndebug/user.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright 2016 Google Inc. All Rights Reserved.
|
||||
* Author: gkalsi@google.com (Gurjant Kalsi)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <lib/ndebug/ndebug.h>
|
||||
#include <lib/ndebug/shared_structs.h>
|
||||
#include <lib/ndebug/user.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <kernel/mutex.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <trace.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
#define HOST_MSG_TIMEOUT (1000) // 1 Second
|
||||
|
||||
static volatile bool connected = false;
|
||||
|
||||
static mutex_t usr_mutex = MUTEX_INITIAL_VALUE(usr_mutex);
|
||||
|
||||
static uint8_t scratch_buffer[NDEBUG_MAX_PACKET_SIZE];
|
||||
|
||||
static bool is_valid_connection_request(ssize_t n, const uint8_t *buf)
|
||||
{
|
||||
LTRACEF("length: %ld, buf: 0x%p\n", n, buf);
|
||||
|
||||
if (n < (ssize_t)sizeof(ndebug_ctrl_packet_t)) {
|
||||
dprintf(INFO, "Malformed Packet. Expected at least %u bytes, got %ld\n",
|
||||
sizeof(ndebug_ctrl_packet_t), n);
|
||||
return false;
|
||||
}
|
||||
|
||||
ndebug_ctrl_packet_t *pkt = (ndebug_ctrl_packet_t *)buf;
|
||||
|
||||
return pkt->magic == NDEBUG_CTRL_PACKET_MAGIC &&
|
||||
pkt->type == NDEBUG_CTRL_CMD_RESET;
|
||||
}
|
||||
|
||||
static void write_buffer(const uint32_t message, uint8_t *buf)
|
||||
{
|
||||
ndebug_ctrl_packet_t *pkt = (ndebug_ctrl_packet_t *)scratch_buffer;
|
||||
|
||||
pkt->magic = NDEBUG_CTRL_PACKET_MAGIC;
|
||||
pkt->type = message;
|
||||
}
|
||||
|
||||
static status_t send_message_to_host(const uint32_t message)
|
||||
{
|
||||
LTRACEF("message: %d\n", message);
|
||||
|
||||
write_buffer(message, scratch_buffer);
|
||||
|
||||
ssize_t res = ndebug_usb_write(NDEBUG_CHANNEL_USR,
|
||||
sizeof(ndebug_ctrl_packet_t),
|
||||
HOST_MSG_TIMEOUT,
|
||||
scratch_buffer);
|
||||
|
||||
if (res == ERR_TIMED_OUT) {
|
||||
dprintf(INFO, "send message %d timed out\n", message);
|
||||
} else if (res < 0) {
|
||||
dprintf(INFO, "send message %d failed with error %ld\n", message, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
status_t ndebugusr_await_host(lk_time_t timeout)
|
||||
{
|
||||
LTRACEF("timeout: %u\n", timeout);
|
||||
|
||||
status_t result = await_usb_online(timeout);
|
||||
if (result != NO_ERROR) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ssize_t bytes = ndebug_usb_read(NDEBUG_CHANNEL_USR,
|
||||
NDEBUG_MAX_PACKET_SIZE,
|
||||
timeout, scratch_buffer);
|
||||
if (bytes < 0) {
|
||||
return bytes;
|
||||
} else if (bytes < (ssize_t)sizeof(ndebug_ctrl_packet_t)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_valid_connection_request(bytes, scratch_buffer)) {
|
||||
// Connection established.
|
||||
if (send_message_to_host(NDEBUG_CTRL_CMD_ESTABLISHED) < 0) {
|
||||
continue;
|
||||
}
|
||||
connected = true;
|
||||
return NO_ERROR;
|
||||
} else {
|
||||
// Tell the host that it needs to reset the connection before
|
||||
// attempting any further communication.
|
||||
send_message_to_host(NDEBUG_CTRL_CMD_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t ndebug_read_usr(uint8_t *buf, const lk_time_t timeout)
|
||||
{
|
||||
LTRACEF("buf: 0x%p, timeout: %u\n", buf, timeout);
|
||||
|
||||
if (!connected) {
|
||||
// User must call ndebugusr_await_host and establish a connection
|
||||
// before continuing.
|
||||
return ERR_CHANNEL_CLOSED;
|
||||
}
|
||||
|
||||
mutex_acquire(&usr_mutex);
|
||||
|
||||
// Retry Loop
|
||||
while (true) {
|
||||
ssize_t result = ndebug_usb_read(NDEBUG_CHANNEL_USR,
|
||||
NDEBUG_MAX_PACKET_SIZE,
|
||||
timeout, scratch_buffer);
|
||||
if (result < (ssize_t)sizeof(ndebug_ctrl_packet_t)) {
|
||||
dprintf(INFO, "Short Packet. Len = %ld\n", result);
|
||||
continue;
|
||||
}
|
||||
|
||||
ndebug_ctrl_packet_t *ctrl = (ndebug_ctrl_packet_t *)scratch_buffer;
|
||||
if (ctrl->magic != NDEBUG_CTRL_PACKET_MAGIC) {
|
||||
dprintf(INFO, "Bad Packet Magic = %u\n", ctrl->magic);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctrl->type == NDEBUG_CTRL_CMD_RESET) {
|
||||
send_message_to_host(NDEBUG_CTRL_CMD_RESET);
|
||||
connected = false;
|
||||
mutex_release(&usr_mutex);
|
||||
return ERR_CHANNEL_CLOSED;
|
||||
} else if (ctrl->type == NDEBUG_CTRL_CMD_DATA) {
|
||||
const ssize_t n_data_bytes = result - sizeof(ndebug_ctrl_packet_t);
|
||||
memcpy(buf, scratch_buffer + sizeof(ndebug_ctrl_packet_t),
|
||||
n_data_bytes);
|
||||
mutex_release(&usr_mutex);
|
||||
return n_data_bytes;
|
||||
} else {
|
||||
dprintf(INFO, "Unexpected packet type = %u\n", ctrl->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t ndebug_write_usr(uint8_t *buf, const size_t n, const lk_time_t timeout)
|
||||
{
|
||||
LTRACEF("buf = 0x%p, n = %u, timeout = %u\n", buf, n, timeout);
|
||||
|
||||
if (!connected) {
|
||||
// User must call ndebugusr_await_host and establish a connection
|
||||
// before continuing.
|
||||
return ERR_CHANNEL_CLOSED;
|
||||
}
|
||||
|
||||
mutex_acquire(&usr_mutex);
|
||||
|
||||
uint8_t *cursor = scratch_buffer;
|
||||
|
||||
write_buffer(NDEBUG_CTRL_CMD_DATA, cursor);
|
||||
|
||||
cursor += sizeof(ndebug_ctrl_packet_t);
|
||||
|
||||
ssize_t res;
|
||||
size_t bytes_remaining = n;
|
||||
do {
|
||||
size_t bytes_to_copy = MIN(NDEBUG_USR_MAX_PACKET_SIZE, bytes_remaining);
|
||||
|
||||
memcpy(cursor, buf, bytes_to_copy);
|
||||
|
||||
buf += bytes_to_copy;
|
||||
bytes_remaining -= bytes_to_copy;
|
||||
|
||||
res = ndebug_usb_write(
|
||||
NDEBUG_CHANNEL_USR,
|
||||
bytes_to_copy + sizeof(ndebug_ctrl_packet_t),
|
||||
timeout,
|
||||
scratch_buffer
|
||||
);
|
||||
|
||||
if (res < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
} while (bytes_remaining > 0);
|
||||
|
||||
mutex_release(&usr_mutex);
|
||||
|
||||
if (res < 0) {
|
||||
return res;
|
||||
} else {
|
||||
return (ssize_t)n;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user