radio_tool 0.2.1
Loading...
Searching...
No Matches
dfu.cpp
1
18#include <radio_tool/dfu/dfu.hpp>
19#include <radio_tool/dfu/dfu_exception.hpp>
20
21#include <exception>
22#include <thread>
23#include <chrono>
24
25using namespace radio_tool::dfu;
26
27auto DFU::SetAddress(const uint32_t &addr) const -> void
28{
29 std::vector<uint8_t> data = {
30 static_cast<uint8_t>(0x21),
31 static_cast<uint8_t>(addr & 0xFF),
32 static_cast<uint8_t>((addr >> 8) & 0xFF),
33 static_cast<uint8_t>((addr >> 16) & 0xFF),
34 static_cast<uint8_t>((addr >> 24) & 0xFF)};
35
36 Download(data);
37}
38
39auto DFU::Erase(const uint32_t &addr) const -> void
40{
41 std::vector<uint8_t> data = {
42 static_cast<uint8_t>(0x41),
43 static_cast<uint8_t>(addr & 0xFF),
44 static_cast<uint8_t>((addr >> 8) & 0xFF),
45 static_cast<uint8_t>((addr >> 16) & 0xFF),
46 static_cast<uint8_t>((addr >> 24) & 0xFF)};
47
48 Download(data);
49}
50
51auto DFU::Download(const std::vector<uint8_t> &data, const uint16_t &wValue) const -> void
52{
53 InitDownload();
54 // tehnically we shouldnt const_cast here but libusb *?WONT?* modify this data
55 auto err = libusb_control_transfer(device, 0x21, static_cast<uint8_t>(DFURequest::DNLOAD), wValue, 0, const_cast<unsigned char *>(data.data()), data.size(), this->timeout);
56 if (err < LIBUSB_SUCCESS)
57 {
58 throw DFUException(libusb_error_name(err));
59 }
60
61 //execute command by calling GetStatus
62 auto status = GetStatus();
63 if (status.state != DFUState::DFU_DOWNLOAD_BUSY)
64 {
65 throw DFUException("Command execution failed");
66 }
67 else if (status.timeout > 0)
68 {
69 //std::this_thread::sleep_for(std::chrono::nanoseconds(status.timeout));
70 }
71
72 //check the command executed ok
73 auto status2 = GetStatus();
74 if (status2.state != DFUState::DFU_DOWNLOAD_IDLE)
75 {
76 throw DFUException("Command execution failed");
77 }
78}
79
80auto DFU::Upload(const uint16_t &size, const uint8_t &wValue) const -> std::vector<uint8_t>
81{
82 InitUpload();
83 auto data = std::vector<uint8_t>(size);
84 auto err = libusb_control_transfer(device, 0xa1, static_cast<uint8_t>(DFURequest::UPLOAD), wValue, 0, data.data(), data.size(), this->timeout);
85 if (err < LIBUSB_SUCCESS)
86 {
87 throw DFUException(libusb_error_name(err));
88 }
89 else
90 {
91 data.resize(err);
92 }
93 return data;
94}
95
96auto DFU::GetState() const -> DFUState
97{
98 CheckDevice();
99 unsigned char state;
100 auto err = libusb_control_transfer(device, 0xa1, static_cast<uint8_t>(DFURequest::GETSTATE), 0, 0, &state, 1, this->timeout);
101 if (err < LIBUSB_SUCCESS)
102 {
103 throw DFUException(libusb_error_name(err));
104 }
105 else
106 {
107 auto s = static_cast<DFUState>((int)state);
108 //std::cerr << "State: " << ::ToString(s) << std::endl;
109 return s;
110 }
111}
112
113auto DFU::GetStatus() const -> const DFUStatusReport
114{
115 CheckDevice();
116 auto constexpr StatusSize = 6;
117
118 unsigned char data[StatusSize];
119 auto err = libusb_control_transfer(device, 0xa1, static_cast<uint8_t>(DFURequest::GETSTATUS), 0, 0, data, StatusSize, this->timeout);
120 if (err < LIBUSB_SUCCESS)
121 {
122 throw DFUException(libusb_error_name(err));
123 }
124 else
125 {
126 return DFUStatusReport::Parse(data);
127 }
128 return DFUStatusReport::Empty();
129}
130
131auto DFU::Abort() const -> void
132{
133 CheckDevice();
134 auto err = libusb_control_transfer(device, 0x21, static_cast<uint8_t>(DFURequest::ABORT), 0, 0, nullptr, 0, this->timeout);
135 if (err < LIBUSB_SUCCESS)
136 {
137 throw DFUException(libusb_error_name(err));
138 }
139}
140
141auto DFU::Detach() const -> void
142{
143 CheckDevice();
144 auto err = libusb_control_transfer(device, 0x21, static_cast<uint8_t>(DFURequest::DETACH), 0, 0, nullptr, 0, this->timeout);
145 if (err < LIBUSB_SUCCESS)
146 {
147 throw DFUException(libusb_error_name(err));
148 }
149}
150
151auto DFU::CheckDevice() const -> void
152{
153 if (this->device == nullptr)
154 throw std::runtime_error("Device is not opened");
155}
156
157auto DFU::InitDownload() const -> void
158{
159 CheckDevice();
160 while (1)
161 {
162 auto state = GetState();
163 switch (state)
164 {
165 case DFUState::DFU_DOWNLOAD_IDLE:
166 case DFUState::DFU_IDLE:
167 return;
168 default:
169 {
170 Abort();
171 break;
172 }
173 }
174 }
175}
176
177auto DFU::InitUpload() const -> void
178{
179 CheckDevice();
180 while (1)
181 {
182 auto state = GetState();
183 switch (state)
184 {
185 case DFUState::DFU_UPLOAD_IDLE:
186 case DFUState::DFU_IDLE:
187 return;
188 default:
189 {
190 Abort();
191 break;
192 }
193 }
194 }
195}
auto InitUpload() const -> void
Definition: dfu.cpp:177
auto InitDownload() const -> void
Definition: dfu.cpp:157