Skip to content

Commit

Permalink
feat(transport): add DebugLink support to NodeUsbTransport and UdpTra…
Browse files Browse the repository at this point in the history
…nsport
  • Loading branch information
szymonlesisz committed Aug 19, 2024
1 parent 2a1c8a4 commit 8bd0e9b
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 10 deletions.
6 changes: 4 additions & 2 deletions packages/transport/src/api/udp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ export class UdpApi extends AbstractApi {

private enumerationTimeout: ReturnType<typeof setTimeout> | undefined;
private enumerateAbortController = new AbortController();
private debugLink?: boolean;

constructor({ logger }: AbstractApiConstructorParams) {
constructor({ logger, debugLink }: AbstractApiConstructorParams & { debugLink?: boolean }) {
super({ logger });
this.debugLink = debugLink;
}

listen() {
Expand Down Expand Up @@ -160,7 +162,7 @@ export class UdpApi extends AbstractApi {

public async enumerate(signal?: AbortSignal) {
// in theory we could support multiple devices, but we don't yet
const paths = ['127.0.0.1:21324'];
const paths = this.debugLink ? ['127.0.0.1:21325'] : ['127.0.0.1:21324'];

try {
const enumerateResult = await Promise.all(
Expand Down
26 changes: 21 additions & 5 deletions packages/transport/src/api/usb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
CONFIGURATION_ID,
ENDPOINT_ID,
INTERFACE_ID,
DEBUGLINK_ENDPOINT_ID,
DEBUGLINK_INTERFACE_ID,
T1_HID_VENDOR,
TREZOR_USB_DESCRIPTORS,
WEBUSB_BOOTLOADER_PRODUCT,
Expand All @@ -16,6 +18,7 @@ import * as ERRORS from '../errors';
interface ConstructorParams extends AbstractApiConstructorParams {
usbInterface: USB;
forceReadSerialOnConnect?: boolean;
debugLink?: boolean;
}

interface TransportInterfaceDevice {
Expand All @@ -36,12 +39,14 @@ export class UsbApi extends AbstractApi {
protected usbInterface: ConstructorParams['usbInterface'];
private forceReadSerialOnConnect?: boolean;
private abortController = new AbortController();
private debugLink?: boolean;

constructor({ usbInterface, logger, forceReadSerialOnConnect }: ConstructorParams) {
constructor({ usbInterface, logger, forceReadSerialOnConnect, debugLink }: ConstructorParams) {
super({ logger });

this.usbInterface = usbInterface;
this.forceReadSerialOnConnect = forceReadSerialOnConnect;
this.debugLink = debugLink;
}

public listen() {
Expand Down Expand Up @@ -183,7 +188,11 @@ export class UsbApi extends AbstractApi {
try {
this.logger?.debug('usb: device.transferIn');
const res = await this.abortableMethod(
() => device.transferIn(ENDPOINT_ID, this.chunkSize),
() =>
device.transferIn(
this.debugLink ? DEBUGLINK_ENDPOINT_ID : ENDPOINT_ID,
this.chunkSize,
),
{ signal, onAbort: () => device.reset() },
);
this.logger?.debug(
Expand Down Expand Up @@ -220,7 +229,11 @@ export class UsbApi extends AbstractApi {
// https://wicg.github.io/webusb/#ref-for-dom-usbdevice-transferout
this.logger?.debug('usb: device.transferOut');
const result = await this.abortableMethod(
() => device.transferOut(ENDPOINT_ID, newArray),
() =>
device.transferOut(
this.debugLink ? DEBUGLINK_ENDPOINT_ID : ENDPOINT_ID,
newArray,
),
{ signal, onAbort: () => device.reset() },
);
this.logger?.debug(
Expand Down Expand Up @@ -312,7 +325,10 @@ export class UsbApi extends AbstractApi {
try {
this.logger?.debug(`usb: device.claimInterface: ${INTERFACE_ID}`);
// claim device for exclusive access by this app
await this.abortableMethod(() => device.claimInterface(INTERFACE_ID), { signal });
await this.abortableMethod(
() => device.claimInterface(this.debugLink ? DEBUGLINK_INTERFACE_ID : INTERFACE_ID),
{ signal },
);
this.logger?.debug(
`usb: device.claimInterface done: ${INTERFACE_ID}. device: ${this.formatDeviceForLog(device)}`,
);
Expand Down Expand Up @@ -340,7 +356,7 @@ export class UsbApi extends AbstractApi {

if (device.opened) {
try {
const interfaceId = INTERFACE_ID;
const interfaceId = this.debugLink ? DEBUGLINK_INTERFACE_ID : INTERFACE_ID;
this.logger?.debug(`usb: device.releaseInterface: ${interfaceId}`);
await device.releaseInterface(interfaceId);
this.logger?.debug(
Expand Down
2 changes: 2 additions & 0 deletions packages/transport/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
export const CONFIGURATION_ID = 1;
export const INTERFACE_ID = 0;
export const ENDPOINT_ID = 1;
export const DEBUGLINK_INTERFACE_ID = 1;
export const DEBUGLINK_ENDPOINT_ID = 2;
export const T1_HID_VENDOR = 0x534c;

const T1_HID_PRODUCT = 0x0001;
Expand Down
1 change: 1 addition & 0 deletions packages/transport/src/transports/abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export interface AbstractTransportParams {
messages?: Record<string, any>;
signal: AbortSignal;
logger?: Logger;
debugLink?: boolean;
}

export const isTransportInstance = (transport?: AbstractTransport) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/transport/src/transports/nodeusb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class NodeUsbTransport extends AbstractApiTransport {
public name = 'NodeUsbTransport' as const;

constructor(params: AbstractTransportParams) {
const { messages, logger, signal } = params;
const { messages, logger, signal, debugLink } = params;
const sessionsBackground = new SessionsBackground({ signal });

// in nodeusb there is no synchronization yet. this is a followup and needs to be decided
Expand All @@ -34,6 +34,7 @@ export class NodeUsbTransport extends AbstractApiTransport {
allowAllDevices: true, // return all devices, not only authorized
}),
logger,
debugLink,
}),
sessionsClient,
signal,
Expand Down
4 changes: 2 additions & 2 deletions packages/transport/src/transports/udp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class UdpTransport extends AbstractApiTransport {
private enumerateTimeout: ReturnType<typeof setTimeout> | undefined;

constructor(params: AbstractTransportParams) {
const { messages, logger, signal } = params;
const { messages, logger, signal, debugLink } = params;
const sessionsBackground = new SessionsBackground({ signal });

// in udp there is no synchronization yet. it depends where this transport runs (node or browser)
Expand All @@ -26,7 +26,7 @@ export class UdpTransport extends AbstractApiTransport {

super({
messages,
api: new UdpApi({ logger }),
api: new UdpApi({ logger, debugLink }),
logger,
sessionsClient,
signal,
Expand Down

0 comments on commit 8bd0e9b

Please sign in to comment.