[ndebug] Move NDebug from main LK tree to Coral tree.
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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 ndebug_await_connection(const channel_t ch, const lk_time_t timeout);
|
||||
|
||||
status_t msg_host(const channel_t ch, const uint32_t message,
|
||||
const lk_time_t timeout, uint8_t *buf);
|
||||
__END_CDECLS
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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)
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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 ndebug_await_connection_usr(lk_time_t timeout);
|
||||
|
||||
__END_CDECLS
|
||||
@@ -1,292 +0,0 @@
|
||||
/*
|
||||
* 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 <lib/ndebug/shared_structs.h>
|
||||
#include <string.h>
|
||||
#include <trace.h>
|
||||
|
||||
#define LOCAL_TRACE 0
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
status_t msg_host(
|
||||
const channel_t ch, const uint32_t message,
|
||||
const lk_time_t timeout, uint8_t *buf
|
||||
)
|
||||
{
|
||||
LTRACEF("message: %d\n", message);
|
||||
|
||||
ndebug_ctrl_packet_t *pkt = (ndebug_ctrl_packet_t *)buf;
|
||||
pkt->magic = NDEBUG_CTRL_PACKET_MAGIC;
|
||||
pkt->type = message;
|
||||
|
||||
ssize_t res =
|
||||
ndebug_usb_write(ch, sizeof(ndebug_ctrl_packet_t), timeout, buf);
|
||||
|
||||
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 ndebug_await_connection(const channel_t ch, const lk_time_t timeout)
|
||||
{
|
||||
LTRACEF("channel: %u, timeout: %u\n", ch, timeout);
|
||||
|
||||
uint8_t buf[NDEBUG_MAX_PACKET_SIZE];
|
||||
|
||||
status_t result = event_wait_timeout(&usb_online_event, timeout);
|
||||
if (result != NO_ERROR) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ssize_t bytes =
|
||||
ndebug_usb_read(ch, NDEBUG_MAX_PACKET_SIZE, timeout, buf);
|
||||
|
||||
if (bytes < 0) return bytes;
|
||||
if (bytes < (ssize_t)sizeof(ndebug_ctrl_packet_t)) continue;
|
||||
if (!is_valid_connection_request(bytes, buf)) {
|
||||
msg_host(ch, NDEBUG_CTRL_CMD_RESET, timeout, buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg_host(ch, NDEBUG_CTRL_CMD_ESTABLISHED, timeout, buf) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
# MODULE_DEPS := \
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/ndebug.c \
|
||||
$(LOCAL_DIR)/user.c \
|
||||
|
||||
|
||||
include make/module.mk
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* 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];
|
||||
|
||||
status_t ndebug_await_connection_usr(lk_time_t timeout)
|
||||
{
|
||||
LTRACEF("timeout: %u\n", timeout);
|
||||
|
||||
status_t result = ndebug_await_connection(NDEBUG_CHANNEL_USR, timeout);
|
||||
|
||||
if (result == NO_ERROR) {
|
||||
connected = true;
|
||||
} else {
|
||||
connected = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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) {
|
||||
msg_host(NDEBUG_CHANNEL_USR, NDEBUG_CTRL_CMD_RESET, timeout,
|
||||
scratch_buffer);
|
||||
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;
|
||||
|
||||
ndebug_ctrl_packet_t *pkt = (ndebug_ctrl_packet_t *)cursor;
|
||||
pkt->magic = NDEBUG_CTRL_PACKET_MAGIC;
|
||||
pkt->type = NDEBUG_CTRL_CMD_DATA;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
1
tools/.gitignore
vendored
1
tools/.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
lkboot
|
||||
mkimage
|
||||
ndbg
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
all: lkboot mkimage ndbg
|
||||
all: lkboot mkimage
|
||||
|
||||
LKBOOT_SRCS := lkboot.c liblkboot.c network.c
|
||||
LKBOOT_DEPS := network.h liblkboot.h ../app/lkboot/lkboot_protocol.h
|
||||
@@ -13,11 +13,5 @@ MKIMAGE_INCS := -I../external/lib/mincrypt/include -I../lib/bootimage/include
|
||||
mkimage: $(MKIMAGE_SRCS) $(MKIMAGE_DEPS)
|
||||
gcc -Wall -g -o $@ $(MKIMAGE_INCS) $(MKIMAGE_SRCS)
|
||||
|
||||
NDEBUG_DEPS :=
|
||||
NDEBUG_SRCS := ndebug/ndebug.cc ndebug/usbionode.cc ndebug/tcpionode.cc
|
||||
NDEBUG_INCS := -I./ndebug/include -I../lib/ndebug/include
|
||||
ndbg: $(NDEBUG_SRCS) $(NDEBUG_DEPS)
|
||||
c++ -Wall -Werror -g -std=c++11 -o $@ $(NDEBUG_INCS) $(NDEBUG_SRCS) -lusb-1.0
|
||||
|
||||
clean::
|
||||
rm -f lkboot mkimage ndbg
|
||||
rm -f lkboot mkimage
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace NDebug {
|
||||
|
||||
enum class IONodeResult {
|
||||
Failure, // I/O op failed
|
||||
Success, // I/O op succeeded
|
||||
Finished, // No more I/O ops remaining, perform graceful shutdown
|
||||
NotConnected
|
||||
};
|
||||
|
||||
class IONode {
|
||||
public:
|
||||
virtual IONodeResult readBuf(std::vector<uint8_t> *buf) = 0;
|
||||
virtual IONodeResult writeBuf(const std::vector<uint8_t> &buf) = 0;
|
||||
};
|
||||
|
||||
} // namespace NDebug
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <ionode.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace NDebug {
|
||||
|
||||
class TCPIONode : public IONode {
|
||||
public:
|
||||
TCPIONode(uint16_t port);
|
||||
virtual ~TCPIONode();
|
||||
|
||||
IONodeResult readBuf(std::vector<uint8_t> *buf) override;
|
||||
IONodeResult writeBuf(const std::vector<uint8_t> &buf) override;
|
||||
|
||||
bool listenAndAccept();
|
||||
bool open();
|
||||
|
||||
private:
|
||||
void swapConnectionSocket(const int newSocket);
|
||||
|
||||
// All public methods are protected by this global lock.
|
||||
std::mutex lock_;
|
||||
|
||||
const uint16_t port_;
|
||||
int connectionSocket_;
|
||||
int listenerSocket_;
|
||||
};
|
||||
|
||||
} // namespace ndebug
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <ionode.h>
|
||||
|
||||
struct libusb_context;
|
||||
struct libusb_device_handle;
|
||||
|
||||
namespace NDebug {
|
||||
|
||||
class USBIONode : public IONode {
|
||||
public:
|
||||
USBIONode(const uint16_t vendorId, const uint16_t productId);
|
||||
virtual ~USBIONode();
|
||||
|
||||
IONodeResult readBuf(std::vector<uint8_t> *buf) override;
|
||||
IONodeResult writeBuf(const std::vector<uint8_t> &buf) override;
|
||||
|
||||
bool connect();
|
||||
|
||||
private:
|
||||
bool openDeviceByParams(const uint16_t vid, const uint16_t pid,
|
||||
const uint8_t interfaceClass,
|
||||
const uint8_t interfaceSubClass,
|
||||
const uint8_t interfaceProtocol);
|
||||
|
||||
const uint16_t vendorId_;
|
||||
const uint16_t productId_;
|
||||
|
||||
uint8_t epOut_;
|
||||
uint8_t epIn_;
|
||||
uint8_t iface_;
|
||||
|
||||
libusb_context *ctx_;
|
||||
libusb_device_handle *dev_;
|
||||
};
|
||||
|
||||
} // namespace ndebug
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* 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 <cstdint>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "ionode.h"
|
||||
#include "tcpionode.h"
|
||||
#include "usbionode.h"
|
||||
|
||||
const uint16_t kVendorId = 0x9999;
|
||||
const uint16_t kProductId = 0x9999;
|
||||
|
||||
const uint16_t kListenPort = 9091;
|
||||
|
||||
void IOWorkerThread(NDebug::IONode *in, NDebug::IONode *out)
|
||||
{
|
||||
std::vector<uint8_t> buf;
|
||||
NDebug::IONodeResult res;
|
||||
while (true) {
|
||||
res = in->readBuf(&buf);
|
||||
if (res == NDebug::IONodeResult::Finished) {
|
||||
break;
|
||||
} else if (res == NDebug::IONodeResult::Failure) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res = out->writeBuf(buf);
|
||||
if (res == NDebug::IONodeResult::Finished) {
|
||||
break;
|
||||
} else if (res == NDebug::IONodeResult::Failure) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
NDebug::USBIONode usb(kVendorId, kProductId);
|
||||
if (!usb.connect()) {
|
||||
std::cerr << "Could not connect to USB device." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
NDebug::TCPIONode tcp(kListenPort);
|
||||
if (!tcp.open()) {
|
||||
std::cerr << "Could not open TCP connection." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::thread deviceToHost(IOWorkerThread, &usb, &tcp);
|
||||
std::thread hostToDevice;
|
||||
|
||||
while (true) {
|
||||
tcp.listenAndAccept();
|
||||
|
||||
hostToDevice = std::thread(IOWorkerThread, &tcp, &usb);
|
||||
hostToDevice.join();
|
||||
}
|
||||
|
||||
deviceToHost.join();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* 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 "tcpionode.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace NDebug {
|
||||
|
||||
const int kSockFdClosed = -1;
|
||||
|
||||
TCPIONode::TCPIONode(uint16_t port)
|
||||
: port_(port),
|
||||
connectionSocket_(kSockFdClosed),
|
||||
listenerSocket_(kSockFdClosed) {}
|
||||
|
||||
TCPIONode::~TCPIONode()
|
||||
{
|
||||
if (connectionSocket_ >= 0) {
|
||||
shutdown(connectionSocket_, SHUT_RDWR);
|
||||
close(connectionSocket_);
|
||||
connectionSocket_ = kSockFdClosed;
|
||||
}
|
||||
if (listenerSocket_ >= 0) {
|
||||
shutdown(listenerSocket_, SHUT_RDWR);
|
||||
close(listenerSocket_);
|
||||
listenerSocket_ = kSockFdClosed;
|
||||
}
|
||||
}
|
||||
|
||||
IONodeResult TCPIONode::readBuf(std::vector<uint8_t> *buf)
|
||||
{
|
||||
std::lock_guard<std::mutex> g(lock_);
|
||||
|
||||
if (connectionSocket_ == kSockFdClosed) {
|
||||
return IONodeResult::NotConnected;
|
||||
}
|
||||
|
||||
buf->clear();
|
||||
buf->resize(64);
|
||||
|
||||
ssize_t bytes = read(connectionSocket_, &(*buf)[0], 64);
|
||||
if (bytes == 0) {
|
||||
return IONodeResult::Finished;
|
||||
} else if (bytes > 0) {
|
||||
buf->resize(bytes);
|
||||
return IONodeResult::Success;
|
||||
}
|
||||
|
||||
return IONodeResult::Failure;
|
||||
}
|
||||
|
||||
IONodeResult TCPIONode::writeBuf(const std::vector<uint8_t> &buf)
|
||||
{
|
||||
std::lock_guard<std::mutex> g(lock_);
|
||||
|
||||
if (connectionSocket_ == kSockFdClosed) {
|
||||
return IONodeResult::NotConnected;
|
||||
}
|
||||
|
||||
size_t written = 0;
|
||||
do {
|
||||
ssize_t bytes = write(connectionSocket_, &buf[written], buf.size() - written);
|
||||
if (bytes < 0) {
|
||||
return IONodeResult::Failure;
|
||||
} else if (bytes == 0) {
|
||||
return IONodeResult::Finished;
|
||||
}
|
||||
written += bytes;
|
||||
} while (written < buf.size());
|
||||
|
||||
return IONodeResult::Success;
|
||||
}
|
||||
|
||||
bool TCPIONode::open()
|
||||
{
|
||||
struct sockaddr_in sa;
|
||||
listenerSocket_ = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (listenerSocket_ == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&sa, 0, sizeof sa);
|
||||
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port_);
|
||||
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
|
||||
if (bind(listenerSocket_, (struct sockaddr *)&sa, sizeof sa) == -1) {
|
||||
close(listenerSocket_);
|
||||
listenerSocket_ = kSockFdClosed;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TCPIONode::swapConnectionSocket(const int newSocket)
|
||||
{
|
||||
std::lock_guard<std::mutex> g(lock_);
|
||||
|
||||
if (connectionSocket_ != -1) {
|
||||
// Drop the previous connection.
|
||||
shutdown(connectionSocket_, SHUT_RDWR);
|
||||
close(connectionSocket_);
|
||||
}
|
||||
|
||||
connectionSocket_ = newSocket;
|
||||
}
|
||||
|
||||
bool TCPIONode::listenAndAccept()
|
||||
{
|
||||
if (kSockFdClosed == listenerSocket_)
|
||||
return false;
|
||||
|
||||
if (listen(listenerSocket_, 1) == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int client = accept(listenerSocket_, NULL, NULL);
|
||||
if (client < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
swapConnectionSocket(client);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace NDebug
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* 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 "usbionode.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
#include "lib/ndebug/shared_structs.h"
|
||||
|
||||
namespace NDebug {
|
||||
|
||||
const size_t kConnectRetryLimit = 5;
|
||||
const unsigned int kDefaultUSBTimeoutMS = 5000;
|
||||
const size_t kMaxUSBPacketSize = 64;
|
||||
|
||||
USBIONode::USBIONode(const uint16_t vendorId, const uint16_t productId)
|
||||
: vendorId_(vendorId),
|
||||
productId_(productId),
|
||||
ctx_(nullptr),
|
||||
dev_(nullptr) {}
|
||||
|
||||
USBIONode::~USBIONode()
|
||||
{
|
||||
if (dev_) {
|
||||
libusb_release_interface(dev_, 0);
|
||||
libusb_close(dev_);
|
||||
dev_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IONodeResult USBIONode::readBuf(std::vector<uint8_t> *buf)
|
||||
{
|
||||
assert(buf != nullptr);
|
||||
|
||||
if (dev_ == nullptr) {
|
||||
return IONodeResult::NotConnected;
|
||||
}
|
||||
|
||||
// Create a buffer long enough to hold the USB packet.
|
||||
std::vector<uint8_t> readBuffer(kMaxUSBPacketSize);
|
||||
|
||||
int xfer = kMaxUSBPacketSize;
|
||||
int rc = libusb_bulk_transfer(dev_, epIn_, &readBuffer[0],
|
||||
kMaxUSBPacketSize, &xfer,
|
||||
kDefaultUSBTimeoutMS);
|
||||
if (rc < 0) {
|
||||
return IONodeResult::Failure;
|
||||
}
|
||||
|
||||
// Packet must be long enought to contain at least the header.
|
||||
if (xfer < (int)sizeof(ndebug_ctrl_packet_t)) {
|
||||
return IONodeResult::Failure;
|
||||
}
|
||||
|
||||
// Make sure the packet is well formed.
|
||||
ndebug_ctrl_packet_t *pkt =
|
||||
reinterpret_cast<ndebug_ctrl_packet_t *>(&readBuffer[0]);
|
||||
if (pkt->magic != NDEBUG_CTRL_PACKET_MAGIC) {
|
||||
return IONodeResult::Failure;
|
||||
}
|
||||
|
||||
if (pkt->type == NDEBUG_CTRL_CMD_RESET) {
|
||||
return IONodeResult::Finished;
|
||||
} else if (pkt->type != NDEBUG_CTRL_CMD_DATA) {
|
||||
return IONodeResult::Failure;
|
||||
}
|
||||
|
||||
buf->clear();
|
||||
buf->reserve(xfer);
|
||||
|
||||
std::copy(readBuffer.begin() + sizeof(ndebug_ctrl_packet_t),
|
||||
readBuffer.begin() + xfer, std::back_inserter(*buf));
|
||||
|
||||
return IONodeResult::Success;
|
||||
}
|
||||
|
||||
IONodeResult USBIONode::writeBuf(const std::vector<uint8_t> &buf)
|
||||
{
|
||||
if (dev_ == nullptr) {
|
||||
return IONodeResult::NotConnected;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> writeBuffer(kMaxUSBPacketSize);
|
||||
|
||||
ndebug_ctrl_packet_t pkt;
|
||||
pkt.magic = NDEBUG_CTRL_PACKET_MAGIC;
|
||||
pkt.type = NDEBUG_CTRL_CMD_DATA;
|
||||
uint8_t *packetCursor = reinterpret_cast<uint8_t *>(&pkt);
|
||||
|
||||
std::copy(packetCursor, packetCursor + sizeof(pkt), writeBuffer.begin());
|
||||
|
||||
size_t stride = 0;
|
||||
for (size_t bufCursor = 0; bufCursor < buf.size(); bufCursor += stride) {
|
||||
stride =
|
||||
std::min(kMaxUSBPacketSize - sizeof(pkt), buf.size() - bufCursor);
|
||||
std::copy(buf.begin() + bufCursor, buf.begin() + bufCursor + stride,
|
||||
writeBuffer.begin() + sizeof(pkt));
|
||||
int xfer = stride + sizeof(pkt);
|
||||
int rc =
|
||||
libusb_bulk_transfer(dev_, epOut_, &writeBuffer[0],
|
||||
stride + sizeof(pkt), &xfer,
|
||||
kDefaultUSBTimeoutMS);
|
||||
if (rc < 0) {
|
||||
return IONodeResult::Failure;
|
||||
}
|
||||
}
|
||||
|
||||
return IONodeResult::Success;
|
||||
}
|
||||
|
||||
bool USBIONode::connect()
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
rc = libusb_init(&ctx_);
|
||||
if (rc < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = openDeviceByParams(
|
||||
vendorId_, productId_, NDEBUG_USB_CLASS_USER_DEFINED,
|
||||
NDEBUG_SUBCLASS, NDEBUG_PROTOCOL_SERIAL_PIPE);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rc = libusb_claim_interface(dev_, iface_);
|
||||
if (rc < 0) {
|
||||
libusb_close(dev_);
|
||||
dev_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
ndebug_ctrl_packet_t pkt;
|
||||
uint8_t *buf = reinterpret_cast<uint8_t *>(&pkt);
|
||||
|
||||
for (size_t i = 0; i < kConnectRetryLimit; i++) {
|
||||
// Send a connection RESET packet to the device.
|
||||
int xfer = sizeof(pkt);
|
||||
|
||||
pkt.magic = NDEBUG_CTRL_PACKET_MAGIC;
|
||||
pkt.type = NDEBUG_CTRL_CMD_RESET;
|
||||
rc = libusb_bulk_transfer(dev_, epOut_, buf, sizeof(pkt), &xfer,
|
||||
kDefaultUSBTimeoutMS);
|
||||
|
||||
// Allow the device to ACK the connection request.
|
||||
rc = libusb_bulk_transfer(dev_, epIn_, buf, sizeof(pkt), &xfer,
|
||||
kDefaultUSBTimeoutMS);
|
||||
|
||||
if (pkt.magic == NDEBUG_CTRL_PACKET_MAGIC &&
|
||||
pkt.type == NDEBUG_CTRL_CMD_ESTABLISHED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USBIONode::openDeviceByParams(const uint16_t vid, const uint16_t pid,
|
||||
const uint8_t interfaceClass,
|
||||
const uint8_t interfaceSubClass,
|
||||
const uint8_t interfaceProtocol)
|
||||
{
|
||||
libusb_device *device = nullptr;
|
||||
bool success = false;
|
||||
|
||||
struct libusb_device **deviceList;
|
||||
size_t numDevices = libusb_get_device_list(ctx_, &deviceList);
|
||||
|
||||
for (size_t i = 0; i < numDevices; i++) {
|
||||
libusb_device_descriptor desc = {0};
|
||||
libusb_get_device_descriptor(deviceList[i], &desc);
|
||||
|
||||
if (desc.idVendor != vid || desc.idProduct != pid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < desc.bNumConfigurations; j++) {
|
||||
struct libusb_config_descriptor *cfg;
|
||||
libusb_get_config_descriptor(deviceList[i], j, &cfg);
|
||||
|
||||
for (size_t k = 0; k < cfg->bNumInterfaces; k++) {
|
||||
libusb_interface_descriptor iface =
|
||||
cfg->interface[k].altsetting[0];
|
||||
if (iface.bInterfaceClass == interfaceClass &&
|
||||
iface.bInterfaceSubClass == interfaceSubClass &&
|
||||
iface.bInterfaceProtocol == interfaceProtocol) {
|
||||
iface_ = k;
|
||||
device = deviceList[i];
|
||||
for (size_t l = 0; l < iface.bNumEndpoints; l++) {
|
||||
if (iface.endpoint[l].bEndpointAddress & 0x80) {
|
||||
epIn_ = iface.endpoint[l].bEndpointAddress;
|
||||
} else {
|
||||
epOut_ = iface.endpoint[l].bEndpointAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
libusb_free_config_descriptor(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (device != nullptr) {
|
||||
int rc = libusb_open(device, &dev_);
|
||||
if (rc == 0) {
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_device_list(deviceList, 0);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
} // namespace NDebug;
|
||||
Reference in New Issue
Block a user