This repository was archived by the owner on Oct 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 236
/
Copy pathdebuggerManager.ts
156 lines (144 loc) · 6.88 KB
/
debuggerManager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import * as fs from "fs";
import * as path from "path";
import * as vscode from "vscode";
import { IArduinoSettings } from "../arduino/arduinoSettings";
import { BoardManager } from "../arduino/boardManager";
import * as platform from "../common/platform";
import * as util from "../common/util";
import { DeviceContext } from "../deviceContext";
export class DebuggerManager {
private _usbDetector;
private _debugServerPath: string;
private _miDebuggerPath: string;
private _debuggerMappings: any = {};
private _debuggerBoardMappings: any = {};
constructor(
private _extensionRoot: string,
private _arduinoSettings: IArduinoSettings,
private _boardManager: BoardManager) {
}
public initialize() {
const debugFileContent = fs.readFileSync(path.join(this._extensionRoot, "misc", "debuggerUsbMapping.json"), "utf8");
const usbFileContent = fs.readFileSync(path.join(this._extensionRoot, "misc", "usbmapping.json"), "utf8");
for (const _debugger of JSON.parse(debugFileContent)) {
if (Array.isArray(_debugger.pid)) {
for (const pid of _debugger.pid) {
this._debuggerMappings[`${pid}%${_debugger.vid}`] = { ..._debugger, pid, vid: _debugger.vid };
}
} else {
this._debuggerMappings[`${_debugger.pid}%${_debugger.vid}`] = { ..._debugger, pid: _debugger.pid, vid: _debugger.vid };
}
}
for (const config of JSON.parse(usbFileContent)) {
for (const board of config.boards) {
if (board.interface || board.target) {
this._debuggerBoardMappings[[board.package, board.architecture, board.id].join(":")] = board;
}
}
}
this._usbDetector = require("../../vendor/node-usb-native").detector;
this._debugServerPath = platform.findFile(platform.getExecutableFileName("openocd"),
path.join(this._arduinoSettings.packagePath, "packages"));
if (!util.fileExistsSync(this._debugServerPath)) {
this._debugServerPath = "";
}
this._miDebuggerPath = platform.findFile(platform.getExecutableFileName("arm-none-eabi-gdb"),
path.join(this._arduinoSettings.packagePath, "packages"));
if (!util.fileExistsSync(this._miDebuggerPath)) {
this._miDebuggerPath = "";
}
}
public get miDebuggerPath(): string {
return this._miDebuggerPath;
}
public get debugServerPath(): string {
return this._debugServerPath;
}
public async listDebuggers(): Promise<any[]> {
const usbDeviceList = await this._usbDetector.find();
const keys = [];
const results = [];
usbDeviceList.forEach((device) => {
if (device.vendorId && device.productId) {
/* tslint:disable:max-line-length*/
const key = util.convertToHex(device.productId, 4) + "%" + util.convertToHex(device.vendorId, 4);
const relatedDebugger = this._debuggerMappings[key];
if (relatedDebugger && keys.indexOf(key) < 0) {
keys.push(key);
results.push(relatedDebugger);
}
}
});
return results;
}
public async resolveOpenOcdOptions(config): Promise<string> {
const board = this._boardManager.currentBoard.key;
const debugConfig = this._debuggerBoardMappings[board];
const dc = DeviceContext.getInstance();
const debuggerConfigured: string = dc.debugger_;
if (!debugConfig) {
throw new Error(`Debug for board ${this._boardManager.currentBoard.name} is not supported by now.`);
}
let resolvedDebugger;
const debuggers = await this.listDebuggers();
if (!debuggers.length) {
throw new Error(`No supported debuggers are connected.`);
}
// rule 1: if this board has debuggers, use its own debugger
if (debugConfig.interface) {
resolvedDebugger = debuggers.find((_debugger) => {
return _debugger.short_name === debugConfig.interface || _debugger.config_file === debugConfig.interface;
});
if (!resolvedDebugger) {
throw new Error(`Debug port for board ${this._boardManager.currentBoard.name} is not connected.`);
}
}
// rule 2: if there is only one debugger, use the only debugger
if (!resolvedDebugger && !debuggerConfigured && debuggers.length === 1) {
resolvedDebugger = debuggers[0];
}
// rule 3: if there is any configuration about debugger, use this configuration
if (!resolvedDebugger && debuggerConfigured) {
resolvedDebugger = debuggers.find((_debugger) => {
return _debugger.short_name === debuggerConfigured || _debugger.config_file === debuggerConfigured;
});
}
if (!resolvedDebugger) {
const chosen = await vscode.window.showQuickPick(<vscode.QuickPickItem[]>debuggers.map((l): vscode.QuickPickItem => {
return {
description: `(0x${l.vid}:0x${l.pid})`,
label: l.name,
};
}).sort((a, b): number => {
return a.label === b.label ? 0 : (a.label > b.label ? 1 : -1);
}), { placeHolder: "Select a debugger" });
if (chosen && chosen.label) {
resolvedDebugger = debuggers.find((_debugger) => _debugger.name === chosen.label);
if (resolvedDebugger) {
dc.debugger_ = resolvedDebugger.config_file;
}
}
if (!resolvedDebugger) {
return "";
}
}
const debugServerPath = config.debugServerPath;
let scriptsFolder = path.join(path.dirname(debugServerPath), "../scripts/");
if (!util.directoryExistsSync(scriptsFolder)) {
scriptsFolder = path.join(path.dirname(debugServerPath), "../share/openocd/scripts/");
}
if (!util.directoryExistsSync(scriptsFolder)) {
throw new Error("Cannot find scripts folder from openocd.");
}
// TODO: need to config gdb port other than hard-coded 3333
if (resolvedDebugger.config_file.includes("jlink")) {
// only swd is supported now
/* tslint:disable:max-line-length*/
return `-s ${scriptsFolder} -f interface/${resolvedDebugger.config_file} -c "transport select swd" -f target/${debugConfig.target} -c "telnet_port disabled" -c "tcl_port disabled"`;
}
/* tslint:disable:max-line-length*/
return `-s ${scriptsFolder} -f interface/${resolvedDebugger.config_file} -f target/${debugConfig.target} -c "telnet_port disabled" -c "tcl_port disabled"`;
}
}