-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathloader.cpp
137 lines (113 loc) · 3.99 KB
/
loader.cpp
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
#include "argparse.hpp"
#include "uss/driver.hpp"
#include "uss/drivers/cdcacm/cdcacm.hpp"
#include "uss/drivers/ch34x/ch34x.hpp"
#include "uss/uss.hpp"
#include <cstdio>
#include <thread>
using namespace uss;
int main(int argc, char** argv) {
bool active = true;
argparse::ArgumentParser program("usbselfserial_creator");
program.add_argument("-v", "--vid", "--vendor-id")
.required()
.scan<'x', uint16_t>()
.help("specify the USB vendor ID.");
program.add_argument("-p", "--pid", "--product-id")
.required()
.scan<'x', uint16_t>()
.help("specify the USB product ID.");
program.add_argument("--bus")
.default_value<uint8_t>(0)
.scan<'u', uint8_t>()
.help("specify the USB bus.");
program.add_argument("--port")
.default_value<uint8_t>(0)
.scan<'u', uint8_t>()
.help("specify the USB port.");
program.add_argument("-d", "--driver")
.required()
.help("specify the driver (ch34x, cdcacm).");
program.add_argument("-o", "--output")
.required()
.help("specify the output location of the pty.");
program.add_argument("-r", "--baudrate")
.required()
.scan<'u', uint32_t>()
.default_value<uint32_t>(250000)
.help("specify the baudrate.");
try {
program.parse_args(argc, argv);
} catch (const std::runtime_error& err) {
std::cerr << err.what() << std::endl;
std::cerr << program;
std::exit(1);
}
uint16_t arg_vid = program.get<uint16_t>("-v");
uint16_t arg_pid = program.get<uint16_t>("-p");
uint8_t arg_bus = program.get<uint8_t>("--bus");
uint8_t arg_port = program.get<uint8_t>("--port");
uint32_t arg_baudrate = program.get<uint32_t>("-r");
std::string arg_driver = program.get<std::string>("-d");
std::string arg_output = program.get<std::string>("-o");
libusb_init(NULL);
// Create a driver
BaseDriver* driver;
if (arg_driver == "ch34x") {
// This is a driver for WinChipHead CH340/CH341/HL340 devices
driver = new driver::ch34x::Ch34xDriver;
} else if (arg_driver == "cdcacm") {
// This is a driver for CDC ACM devices
driver = new driver::cdcacm::CdcAcmDriver;
} else {
printf("Unknown driver type. Please use cdcacm or ch34x.\n");
return 1;
}
printf("-> driver %s to pty %s\n", arg_driver.c_str(), arg_output.c_str());
// Create an output
// This outputs to a virtual serial port / PTY at /tmp/uss0
uss::output::pty::PtyOutput output(NULL, arg_output.c_str(), true);
// Set output transfer completion callback
output.SetTransferCompletionCallback(
[&output](int result) { output.RemoveDevice(); });
// Create a device
// This uses the device 1a86:7523 and supports hotplug
uss::ctl::Hotpluggable ctl(
{arg_vid, arg_pid, arg_bus, arg_port},
[&output](uss::ctl::Hotpluggable* device) {
output.SetDevice(device);
}, // Device connected event
[&output](uss::ctl::Hotpluggable* device) {
output.EndTransfers();
}); // Device disconnected event
// Set device baud rate (250000)
ctl.baud_rate = arg_baudrate;
// Set the device driver to the CH34x one from before
ctl.SetDriver(driver);
std::thread output_thread([&output, &active]() {
while (active) {
output.HandleEvents();
}
});
struct timeval tv = {1L, 0L};
while (active) {
// For each loop iteration...
try {
// Handle LibUSB events
int ret = libusb_handle_events_timeout_completed(NULL, &tv, NULL);
if (ret < 0)
goto clean;
// Update device
ctl.Update();
} catch (const char* error) {
printf("Error caught during main loop: %s\n", error);
goto clean;
}
}
clean:
active = false;
output_thread.join();
libusb_exit(NULL);
delete driver;
return 2;
}