Skip to content

Commit 7654d47

Browse files
committed
usb: implement transfer cancellation
Signed-off-by: Benedek Kupper <kupper.benedek@gmail.com>
1 parent 6a87d4c commit 7654d47

14 files changed

Lines changed: 154 additions & 118 deletions

File tree

c2usb/port/nxp/mcux_mac.cpp

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,29 @@ static IRQn_Type usb_irqn(int index)
101101
extern "C" usb_status_t _USB_DeviceNotificationTrigger(void* handle, void* msg);
102102
#endif
103103

104+
static constexpr c2usb::result to_result(usb_status_t status)
105+
{
106+
switch (status)
107+
{
108+
case kStatus_USB_Success:
109+
return c2usb::result::ok;
110+
case kStatus_USB_Error:
111+
return std::errc::io_error;
112+
case kStatus_USB_Busy:
113+
return std::errc::device_or_resource_busy;
114+
case kStatus_USB_InvalidHandle:
115+
return std::errc::no_such_device;
116+
case kStatus_USB_ControllerNotFound:
117+
return std::errc::no_such_device_or_address;
118+
case kStatus_USB_InvalidParameter:
119+
return std::errc::invalid_argument;
120+
case kStatus_USB_InvalidRequest:
121+
return std::errc::operation_not_supported;
122+
default:
123+
return std::errc::function_not_supported;
124+
}
125+
}
126+
104127
void mcux_mac::init(const speeds& speeds)
105128
{
106129
#if CONFIG_C2USB_MCUX_USB_COEXISTENCE
@@ -123,32 +146,29 @@ void mcux_mac::deinit()
123146

124147
bool mcux_mac::set_attached(bool attached)
125148
{
126-
driver_.device_control(handle(), attached ? kUSB_DeviceControlRun : kUSB_DeviceControlStop);
149+
[[maybe_unused]] auto status =
150+
driver_.device_control(handle(), attached ? kUSB_DeviceControlRun : kUSB_DeviceControlStop);
151+
assert(status == kStatus_USB_Success);
127152
return attached;
128153
}
129154

130155
usb::result mcux_mac::signal_remote_wakeup()
131156
{
132-
auto status = driver_.device_control(handle(), kUSB_DeviceControlResume);
133-
switch (status)
134-
{
135-
case kStatus_USB_Success:
136-
return usb::result::ok;
137-
default:
138-
return usb::result::io_error;
139-
}
157+
return to_result(driver_.device_control(handle(), kUSB_DeviceControlResume));
140158
}
141159

142160
void mcux_mac::set_address_early()
143161
{
144-
driver_.device_control(handle(), kUSB_DeviceControlPreSetDeviceAddress,
145-
&request().wValue.low_byte());
162+
[[maybe_unused]] auto status = driver_.device_control(
163+
handle(), kUSB_DeviceControlPreSetDeviceAddress, &request().wValue.low_byte());
164+
assert(status == kStatus_USB_Success);
146165
}
147166

148167
void mcux_mac::set_address_timely()
149168
{
150-
driver_.device_control(handle(), kUSB_DeviceControlSetDeviceAddress,
151-
&request().wValue.low_byte());
169+
[[maybe_unused]] auto status = driver_.device_control(
170+
handle(), kUSB_DeviceControlSetDeviceAddress, &request().wValue.low_byte());
171+
assert(status == kStatus_USB_Success);
152172
}
153173

154174
usb::speed mcux_mac::speed() const
@@ -178,7 +198,9 @@ void mcux_mac::control_ep_open()
178198
void mcux_mac::control_ep_stall()
179199
{
180200
auto addr = endpoint::address::control_out();
181-
driver_.device_control(handle(), kUSB_DeviceControlEndpointStall, &addr);
201+
[[maybe_unused]] auto status =
202+
driver_.device_control(handle(), kUSB_DeviceControlEndpointStall, &addr);
203+
assert(status == kStatus_USB_Success);
182204
}
183205

184206
bool mcux_mac::ep_init(usb::endpoint::address addr, usb::endpoint::type type, uint16_t mps,
@@ -211,9 +233,8 @@ usb::result mcux_mac::ep_send(ep_handle eph, const std::span<const uint8_t>& dat
211233
{
212234
return usb::result::device_or_resource_busy;
213235
}
214-
auto status =
215-
driver_.deviceSend(handle(), addr, const_cast<uint8_t*>(data.data()), data.size());
216-
return (status == kStatus_USB_Success) ? usb::result::ok : usb::result::not_connected;
236+
return to_result(
237+
driver_.deviceSend(handle(), addr, const_cast<uint8_t*>(data.data()), data.size()));
217238
}
218239

219240
usb::result mcux_mac::ep_receive(ep_handle eph, const std::span<uint8_t>& data)
@@ -223,24 +244,23 @@ usb::result mcux_mac::ep_receive(ep_handle eph, const std::span<uint8_t>& data)
223244
{
224245
return usb::result::device_or_resource_busy;
225246
}
226-
auto status = driver_.deviceRecv(handle(), addr, data.data(), data.size());
227-
return (status == kStatus_USB_Success) ? usb::result::ok : usb::result::not_connected;
247+
return to_result(driver_.deviceRecv(handle(), addr, data.data(), data.size()));
228248
}
229249

230250
usb::result mcux_mac::ep_cancel(ep_handle eph)
231251
{
232252
auto addr = ep_handle_to_address(eph);
233-
auto status = driver_.deviceCancel(handle(), addr);
234-
busy_flags_.clear(addr);
235-
return (status == kStatus_USB_Success) ? usb::result::ok : usb::result::not_connected;
253+
return to_result(driver_.deviceCancel(handle(), addr));
236254
}
237255

238-
usb::result mcux_mac::ep_close(ep_handle eph)
256+
usb::result mcux_mac::ep_close(ep_handle& eph)
239257
{
240258
auto addr = ep_handle_to_address(eph);
241-
auto status = driver_.device_control(handle(), kUSB_DeviceControlEndpointDeinit, &addr);
242-
busy_flags_.clear(addr);
243-
return (status == kStatus_USB_Success) ? usb::result::ok : usb::result::not_connected;
259+
eph = {};
260+
auto result =
261+
to_result(driver_.device_control(handle(), kUSB_DeviceControlEndpointDeinit, &addr));
262+
// busy flag is cleared in cancel callback
263+
return result;
244264
}
245265

246266
bool mcux_mac::ep_is_stalled(ep_handle eph) const
@@ -269,10 +289,6 @@ void mcux_mac::process_ep_notification(const _usb_device_callback_message_struct
269289
{
270290
// wrong mapping
271291
}
272-
else if (message.length == UINT32_MAX)
273-
{
274-
// callback due to ep_cancel()
275-
}
276292
else if (addr.number() == 0)
277293
{
278294
transfer t{};
@@ -328,11 +344,13 @@ void mcux_mac::process_ep_notification(const _usb_device_callback_message_struct
328344
(t.size() == 0)); // work around bug in NXP code
329345
}
330346
}
331-
else
347+
else // other endpoints
332348
{
333349
busy_flags_.clear(addr);
334-
ep_transfer_complete(addr, create_ep_handle(addr),
335-
transfer(message.buffer, message.length));
350+
351+
bool success = (message.length != USB_CANCELLED_TRANSFER_LENGTH);
352+
ep_transfer_complete(addr, transfer(message.buffer, message.length * success, success,
353+
ep_address_to_handle(addr)));
336354
}
337355
}
338356

c2usb/port/nxp/mcux_mac.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ class mcux_mac : public df::address_handle_mac
9191
usb::df::ep_handle ep_open(const usb::df::config::endpoint& ep) override;
9292
usb::result ep_send(usb::df::ep_handle eph, const std::span<const uint8_t>& data) override;
9393
usb::result ep_receive(usb::df::ep_handle eph, const std::span<uint8_t>& data) override;
94-
usb::result ep_close(usb::df::ep_handle eph) override;
95-
usb::result ep_cancel(usb::df::ep_handle eph);
94+
usb::result ep_close(usb::df::ep_handle& eph) override;
95+
usb::result ep_cancel(usb::df::ep_handle eph) override;
9696

9797
bool ep_is_stalled(usb::df::ep_handle eph) const override;
9898
usb::result ep_change_stall(usb::df::ep_handle eph, bool stall) override;

c2usb/port/zephyr/udc_mac.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -739,22 +739,19 @@ void udc_mac::process_ep_event(net_buf* buf)
739739
{
740740
busy_flags_.clear(addr);
741741

742-
if (info.err == 0)
742+
if (info.err != 0)
743743
{
744-
for (uint8_t i = 0; i < ep_bufs_.size(); ++i)
745-
{
746-
if (ep_bufs_[i] == buf)
747-
{
748-
return ep_transfer_complete(addr, create_ep_handle(i + 1),
749-
transfer(buf->data, buf->len));
750-
}
751-
}
752-
assert(ep_bufs_.size() == 0); // a net_buf was issued out of c2usb scope
744+
LOG_ERR("EP %x error:%d", info.ep, info.err);
753745
}
754-
else
746+
for (uint8_t i = 0; i < ep_bufs_.size(); ++i)
755747
{
756-
LOG_ERR("EP %x error:%d", info.ep, info.err);
748+
if (ep_bufs_[i] == buf)
749+
{
750+
return ep_transfer_complete(
751+
addr, transfer(buf->data, buf->len, info.err == 0, create_ep_handle(i + 1)));
752+
}
757753
}
754+
assert(ep_bufs_.size() == 0); // a net_buf was issued out of c2usb scope
758755
}
759756
}
760757

@@ -896,7 +893,7 @@ usb::result udc_mac::ep_receive(usb::df::ep_handle eph, const std::span<uint8_t>
896893
return ep_transfer(eph, data, direction::OUT);
897894
}
898895

899-
usb::result udc_mac::ep_close(usb::df::ep_handle eph)
896+
usb::result udc_mac::ep_close(usb::df::ep_handle& eph)
900897
{
901898
auto& info = *udc_get_buf_info(ep_handle_to_buf(eph));
902899
auto addr = endpoint::address(info.ep);
@@ -907,13 +904,14 @@ usb::result udc_mac::ep_close(usb::df::ep_handle eph)
907904
{
908905
return usb::result(ret);
909906
}
907+
eph = {};
910908
ret = udc_ep_dequeue(dev_, addr);
911909
if (ret != 0)
912910
{
913911
return usb::result(ret);
914912
}
915913
k_yield();
916-
return usb::result::OK;
914+
return usb::result::ok;
917915
}
918916

919917
usb::result udc_mac::ep_cancel(usb::df::ep_handle eph)

c2usb/port/zephyr/udc_mac.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ class udc_mac : public df::mac
8181
usb::df::ep_handle ep_open(const usb::df::config::endpoint& ep) override;
8282
usb::result ep_send(usb::df::ep_handle eph, const std::span<const uint8_t>& data) override;
8383
usb::result ep_receive(usb::df::ep_handle eph, const std::span<uint8_t>& data) override;
84-
usb::result ep_close(usb::df::ep_handle eph) override;
85-
usb::result ep_cancel(usb::df::ep_handle eph);
84+
usb::result ep_close(usb::df::ep_handle& eph) override;
85+
usb::result ep_cancel(usb::df::ep_handle eph) override;
8686
bool ep_is_stalled(usb::df::ep_handle eph) const override;
8787
usb::result ep_change_stall(usb::df::ep_handle eph, bool stall) override;
8888
};

c2usb/usb/df/class/cdc_acm.cpp

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -130,36 +130,16 @@ void function::disable(const config::interface& iface)
130130
cdc::function::disable(iface);
131131
}
132132

133-
void function::transfer_complete(ep_handle eph, const transfer& t)
133+
void function::ep_callback(const transfer& t)
134134
{
135-
if (eph == ep_out_handle())
135+
if (t.endpoint() == ep_out_handle())
136136
{
137-
return data_received(t);
137+
return data_received(std::span<uint8_t>(t.data(), t.size() * t.success()));
138138
}
139-
if (eph == ep_in_handle())
139+
if (t.endpoint() == ep_in_handle())
140140
{
141-
#if 0
142-
auto len = t.size();
143-
if (len == 0)
144-
{
145-
if (tx_len_ > 0)
146-
{
147-
// if ZLP is finished, substitute original length
148-
len = tx_len_;
149-
tx_len_ = 0;
150-
}
151-
}
152-
else if ((len % in_ep_mps_) == 0)
153-
{
154-
// if length mod MPS == 0, split the transfer by sending ZLP
155-
tx_len_ = len;
156-
send_ep(eph, {});
157-
return;
158-
}
159-
return data_sent({const_cast<const uint8_t*>(t.data()), len});
160-
#endif
161141
bool needs_zlp = t.size() and (t.size() % in_ep_mps_) == 0;
162-
return data_sent(t, needs_zlp);
142+
return data_sent(std::span<const uint8_t>(t.data(), t.size() * t.success()), needs_zlp);
163143
}
164144
// notification sent
165145
}

c2usb/usb/df/class/cdc_acm.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class function : public cdc::function
7676
void control_data_complete(message& msg, const config::interface& iface) override;
7777
void enable(const config::interface& iface, uint8_t alt_sel) override;
7878
void disable(const config::interface& iface) override;
79-
void transfer_complete(ep_handle eph, const transfer& t) override;
79+
void ep_callback(const transfer& t) override;
8080

8181
auto& line_coding() const
8282
{

c2usb/usb/df/class/hid.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,15 +84,16 @@ usb::result app_base_function::receive_report(const std::span<uint8_t>& data, re
8484
}
8585
}
8686

87-
void app_base_function::transfer_complete(ep_handle eph, const transfer& t)
87+
void app_base_function::ep_callback(const transfer& t)
8888
{
89-
if (eph == ep_in_handle())
89+
if (t.endpoint() == ep_in_handle())
9090
{
91-
app_.in_report_sent(t);
91+
return app_.in_report_sent(std::span<const uint8_t>(t.data(), t.size() * t.success()));
9292
}
93-
else
93+
if (t.endpoint() == ep_out_handle())
9494
{
95-
app_.set_report(report::type::OUTPUT, t);
95+
return app_.set_report(report::type::OUTPUT,
96+
std::span<const uint8_t>(t.data(), t.size() * t.success()));
9697
}
9798
}
9899

@@ -242,7 +243,7 @@ void function::control_data_complete(message& msg, [[maybe_unused]] const config
242243
{
243244
auto type = static_cast<report::type>(msg.request().wValue.high_byte());
244245
rx_buffers_[type] = {};
245-
app_.set_report(type, msg.data());
246+
app_.set_report(type, msg.data().to_span());
246247
break;
247248
}
248249
default:

c2usb/usb/df/class/hid.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class app_base_function : public df::named_function, public ::hid::transport
3838
result receive_report(const std::span<uint8_t>& data, ::hid::report::type type) override;
3939
::hid::transport::type transport_type() const override { return ::hid::transport::type::USB; }
4040

41-
void transfer_complete(ep_handle eph, const transfer& t) override;
41+
void ep_callback(const transfer& t) override;
4242

4343
::hid::application& app_;
4444
::hid::reports_receiver rx_buffers_{};

c2usb/usb/df/function.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ void function::close_ep(ep_handle& eph)
172172
{
173173
mac_->ep_close(eph);
174174
}
175-
eph = {};
176175
}
177176

178177
usb::result function::send_ep(ep_handle eph, const std::span<const uint8_t>& data)
@@ -211,6 +210,18 @@ usb::result function::stall_ep(ep_handle eph, bool stall)
211210
}
212211
}
213212

213+
usb::result function::cancel_ep(ep_handle eph)
214+
{
215+
if ((mac_ != nullptr) and eph.valid())
216+
{
217+
return mac_->ep_cancel(eph);
218+
}
219+
else
220+
{
221+
return usb::result::connection_reset;
222+
}
223+
}
224+
214225
message* function::pending_message()
215226
{
216227
if (mac_ != nullptr)

c2usb/usb/df/function.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,7 @@ class function : public polymorphic
5151

5252
virtual std::string_view ms_compatible_id() const { return {}; }
5353

54-
virtual void transfer_complete([[maybe_unused]] ep_handle eph,
55-
[[maybe_unused]] const transfer& t)
56-
{}
54+
virtual void ep_callback([[maybe_unused]] const transfer& t) {}
5755

5856
protected:
5957
ep_handle open_ep(const config::endpoint& ep);
@@ -80,6 +78,7 @@ class function : public polymorphic
8078
result send_ep(ep_handle eph, const std::span<const uint8_t>& data);
8179
result receive_ep(ep_handle eph, const std::span<uint8_t>& data);
8280
result stall_ep(ep_handle eph, bool stall);
81+
result cancel_ep(ep_handle eph);
8382

8483
message* pending_message();
8584

0 commit comments

Comments
 (0)