mirror of https://github.com/ARMmbed/mbed-os.git
Update USBHID and USBCDC for new AsyncOp
Update USB classes to use the new AsyncOp API.feature-hal-spec-usb-device
parent
bfa9992c7d
commit
6984060b9f
|
@ -21,24 +21,91 @@
|
||||||
|
|
||||||
class USBHID::AsyncSend: public AsyncOp {
|
class USBHID::AsyncSend: public AsyncOp {
|
||||||
public:
|
public:
|
||||||
AsyncSend(const HID_REPORT *report): AsyncOp(NULL), report(report), result(false)
|
AsyncSend(USBHID *hid, const HID_REPORT *report): hid(hid), report(report), result(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~AsyncSend()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool process()
|
||||||
|
{
|
||||||
|
if (!hid->configured()) {
|
||||||
|
result = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hid->send_nb(report)) {
|
||||||
|
result = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBHID *hid;
|
||||||
const HID_REPORT *report;
|
const HID_REPORT *report;
|
||||||
bool result;
|
bool result;
|
||||||
};
|
};
|
||||||
|
|
||||||
class USBHID::AsyncRead: public AsyncOp {
|
class USBHID::AsyncRead: public AsyncOp {
|
||||||
public:
|
public:
|
||||||
AsyncRead(HID_REPORT *report): AsyncOp(NULL), report(report), result(false)
|
AsyncRead(USBHID *hid, HID_REPORT *report): hid(hid), report(report), result(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~AsyncRead()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool process()
|
||||||
|
{
|
||||||
|
if (!hid->configured()) {
|
||||||
|
result = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hid->read_nb(report)) {
|
||||||
|
result = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBHID *hid;
|
||||||
HID_REPORT *report;
|
HID_REPORT *report;
|
||||||
bool result;
|
bool result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class USBHID::AsyncWait: public AsyncOp {
|
||||||
|
public:
|
||||||
|
AsyncWait(USBHID *hid): hid(hid)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncWait()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool process()
|
||||||
|
{
|
||||||
|
if (hid->configured()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBHID *hid;
|
||||||
|
};
|
||||||
|
|
||||||
USBHID::USBHID(bool connect_blocking, uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
USBHID::USBHID(bool connect_blocking, uint8_t output_report_length, uint8_t input_report_length, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
||||||
: USBDevice(get_usb_phy(), vendor_id, product_id, product_release)
|
: USBDevice(get_usb_phy(), vendor_id, product_id, product_release)
|
||||||
|
@ -88,15 +155,12 @@ void USBHID::wait_ready()
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
AsyncOp wait_op(NULL);
|
AsyncWait wait_op(this);
|
||||||
wait_op.start(&_connect_list);
|
_connect_list.add(&wait_op);
|
||||||
if (configured()) {
|
|
||||||
wait_op.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
wait_op.wait();
|
wait_op.wait(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,23 +168,12 @@ bool USBHID::send(const HID_REPORT *report)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
if (!configured()) {
|
AsyncSend send_op(this, report);
|
||||||
unlock();
|
_send_list.add(&send_op);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send_nb(report)) {
|
|
||||||
unlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncSend send_op(report);
|
|
||||||
send_op.start(&_send_list);
|
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
send_op.wait();
|
send_op.wait(NULL);
|
||||||
|
|
||||||
return send_op.result;
|
return send_op.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,23 +202,12 @@ bool USBHID::read(HID_REPORT *report)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
if (!configured()) {
|
AsyncRead read_op(this, report);
|
||||||
unlock();
|
_read_list.add(&read_op);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_nb(report)) {
|
|
||||||
unlock();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncRead read_op(report);
|
|
||||||
read_op.start(&_read_list);
|
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
read_op.wait();
|
read_op.wait(NULL);
|
||||||
|
|
||||||
return read_op.result;
|
return read_op.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,13 +240,8 @@ void USBHID::_send_isr(usb_ep_t endpoint)
|
||||||
write_finish(_int_in);
|
write_finish(_int_in);
|
||||||
_send_idle = true;
|
_send_idle = true;
|
||||||
|
|
||||||
AsyncSend *send_op = _send_list.head();
|
_send_list.process();
|
||||||
if (send_op != NULL) {
|
if (_send_idle) {
|
||||||
if (send_nb(send_op->report)) {
|
|
||||||
send_op->result = true;
|
|
||||||
send_op->complete();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
report_tx();
|
report_tx();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,60 +254,12 @@ void USBHID::_read_isr(usb_ep_t endpoint)
|
||||||
_output_report.length = read_finish(_int_out);
|
_output_report.length = read_finish(_int_out);
|
||||||
_read_idle = true;
|
_read_idle = true;
|
||||||
|
|
||||||
AsyncRead *read_op = _read_list.head();
|
_read_list.process();
|
||||||
if (read_op != NULL) {
|
if (_read_idle) {
|
||||||
if (read_nb(read_op->report)) {
|
|
||||||
read_op->result = true;
|
|
||||||
read_op->complete();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
report_rx();
|
report_rx();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void USBHID::_connect_wake_all()
|
|
||||||
{
|
|
||||||
assert_locked();
|
|
||||||
|
|
||||||
AsyncOp *wait_op = _connect_list.head();
|
|
||||||
while (wait_op != NULL) {
|
|
||||||
wait_op->complete();
|
|
||||||
wait_op = _connect_list.head();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void USBHID::_send_abort_all()
|
|
||||||
{
|
|
||||||
assert_locked();
|
|
||||||
|
|
||||||
if (!_send_idle) {
|
|
||||||
endpoint_abort(_int_in);
|
|
||||||
_send_idle = true;
|
|
||||||
}
|
|
||||||
AsyncSend *tx_cur = _send_list.head();
|
|
||||||
while (tx_cur != NULL) {
|
|
||||||
tx_cur->result = false;
|
|
||||||
tx_cur->complete();
|
|
||||||
tx_cur = _send_list.head();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void USBHID::_read_abort_all()
|
|
||||||
{
|
|
||||||
assert_locked();
|
|
||||||
|
|
||||||
if (!_read_idle) {
|
|
||||||
endpoint_abort(_int_out);
|
|
||||||
_read_idle = true;
|
|
||||||
}
|
|
||||||
AsyncRead *rx_cur = _read_list.head();
|
|
||||||
while (rx_cur != NULL) {
|
|
||||||
rx_cur->result = false;
|
|
||||||
rx_cur->complete();
|
|
||||||
rx_cur = _read_list.head();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t USBHID::report_desc_length()
|
uint16_t USBHID::report_desc_length()
|
||||||
{
|
{
|
||||||
report_desc();
|
report_desc();
|
||||||
|
@ -280,12 +269,19 @@ uint16_t USBHID::report_desc_length()
|
||||||
|
|
||||||
void USBHID::callback_state_change(DeviceState new_state)
|
void USBHID::callback_state_change(DeviceState new_state)
|
||||||
{
|
{
|
||||||
if (new_state == Configured) {
|
if (new_state != Configured) {
|
||||||
_connect_wake_all();
|
if (!_send_idle) {
|
||||||
} else {
|
endpoint_abort(_int_in);
|
||||||
_send_abort_all();
|
_send_idle = true;
|
||||||
_read_abort_all();
|
|
||||||
}
|
}
|
||||||
|
if (!_read_idle) {
|
||||||
|
endpoint_abort(_int_out);
|
||||||
|
_read_idle = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_send_list.process();
|
||||||
|
_read_list.process();
|
||||||
|
_connect_list.process();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -22,8 +22,7 @@
|
||||||
#include "USBDevice.h"
|
#include "USBDevice.h"
|
||||||
|
|
||||||
#include "USBHID_Types.h"
|
#include "USBHID_Types.h"
|
||||||
#include "AsyncOp.h"
|
#include "OperationList.h"
|
||||||
#include "LinkedList.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -249,17 +248,14 @@ private:
|
||||||
void _send_isr(usb_ep_t endpoint);
|
void _send_isr(usb_ep_t endpoint);
|
||||||
void _read_isr(usb_ep_t endpoint);
|
void _read_isr(usb_ep_t endpoint);
|
||||||
|
|
||||||
void _connect_wake_all();
|
|
||||||
void _send_abort_all();
|
|
||||||
void _read_abort_all();
|
|
||||||
|
|
||||||
class AsyncSend;
|
class AsyncSend;
|
||||||
class AsyncRead;
|
class AsyncRead;
|
||||||
|
class AsyncWait;
|
||||||
|
|
||||||
LinkedList<AsyncOp> _connect_list;
|
OperationList<AsyncWait> _connect_list;
|
||||||
LinkedList<AsyncSend> _send_list;
|
OperationList<AsyncSend> _send_list;
|
||||||
bool _send_idle;
|
bool _send_idle;
|
||||||
LinkedList<AsyncRead> _read_list;
|
OperationList<AsyncRead> _read_list;
|
||||||
bool _read_idle;
|
bool _read_idle;
|
||||||
|
|
||||||
uint8_t _configuration_descriptor[41];
|
uint8_t _configuration_descriptor[41];
|
||||||
|
|
|
@ -36,10 +36,39 @@ static const uint8_t cdc_line_coding_default[7] = {0x80, 0x25, 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
class USBCDC::AsyncWrite: public AsyncOp {
|
class USBCDC::AsyncWrite: public AsyncOp {
|
||||||
public:
|
public:
|
||||||
AsyncWrite(uint8_t *buf, uint32_t size): AsyncOp(NULL), tx_buf(buf), tx_size(size), result(false)
|
AsyncWrite(USBCDC *serial, uint8_t *buf, uint32_t size):
|
||||||
|
serial(serial), tx_buf(buf), tx_size(size), result(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~AsyncWrite()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool process()
|
||||||
|
{
|
||||||
|
if (!serial->_terminal_connected) {
|
||||||
|
result = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t actual_size = 0;
|
||||||
|
serial->send_nb(tx_buf, tx_size, &actual_size, true);
|
||||||
|
tx_size -= actual_size;
|
||||||
|
tx_buf += actual_size;
|
||||||
|
if (tx_size == 0) {
|
||||||
|
result = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start transfer if it hasn't been
|
||||||
|
serial->_send_isr_start();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBCDC *serial;
|
||||||
uint8_t *tx_buf;
|
uint8_t *tx_buf;
|
||||||
uint32_t tx_size;
|
uint32_t tx_size;
|
||||||
bool result;
|
bool result;
|
||||||
|
@ -47,11 +76,40 @@ public:
|
||||||
|
|
||||||
class USBCDC::AsyncRead: public AsyncOp {
|
class USBCDC::AsyncRead: public AsyncOp {
|
||||||
public:
|
public:
|
||||||
AsyncRead(uint8_t *buf, uint32_t size, uint32_t *size_read, bool read_all)
|
AsyncRead(USBCDC *serial, uint8_t *buf, uint32_t size, uint32_t *size_read, bool read_all)
|
||||||
: AsyncOp(NULL), rx_buf(buf), rx_size(size), rx_actual(size_read), all(read_all), result(false)
|
: serial(serial), rx_buf(buf), rx_size(size), rx_actual(size_read), all(read_all), result(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual ~AsyncRead()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool process()
|
||||||
|
{
|
||||||
|
if (!serial->_terminal_connected) {
|
||||||
|
result = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t actual_size = 0;
|
||||||
|
serial->receive_nb(rx_buf, rx_size, &actual_size);
|
||||||
|
rx_buf += actual_size;
|
||||||
|
*rx_actual += actual_size;
|
||||||
|
rx_size -= actual_size;
|
||||||
|
if ((!all && *rx_actual > 0) || (rx_size == 0)) {
|
||||||
|
// Wake thread if request is done
|
||||||
|
result = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial->_receive_isr_start();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBCDC *serial;
|
||||||
uint8_t *rx_buf;
|
uint8_t *rx_buf;
|
||||||
uint32_t rx_size;
|
uint32_t rx_size;
|
||||||
uint32_t *rx_actual;
|
uint32_t *rx_actual;
|
||||||
|
@ -59,6 +117,31 @@ public:
|
||||||
bool result;
|
bool result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class USBCDC::AsyncWait: public AsyncOp {
|
||||||
|
public:
|
||||||
|
AsyncWait(USBCDC *serial)
|
||||||
|
: serial(serial)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~AsyncWait()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool process()
|
||||||
|
{
|
||||||
|
if (serial->_terminal_connected) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
USBCDC *serial;
|
||||||
|
};
|
||||||
|
|
||||||
USBCDC::USBCDC(bool connect_blocking, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
USBCDC::USBCDC(bool connect_blocking, uint16_t vendor_id, uint16_t product_id, uint16_t product_release)
|
||||||
: USBDevice(get_usb_phy(), vendor_id, product_id, product_release)
|
: USBDevice(get_usb_phy(), vendor_id, product_id, product_release)
|
||||||
|
|
||||||
|
@ -230,13 +313,30 @@ void USBCDC::_change_terminal_connected(bool connected)
|
||||||
{
|
{
|
||||||
assert_locked();
|
assert_locked();
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
_connect_wake_all();
|
|
||||||
} else {
|
|
||||||
_send_abort_all();
|
|
||||||
_receive_abort_all();
|
|
||||||
}
|
|
||||||
_terminal_connected = connected;
|
_terminal_connected = connected;
|
||||||
|
if (!_terminal_connected) {
|
||||||
|
// Abort TX
|
||||||
|
if (_tx_in_progress) {
|
||||||
|
endpoint_abort(_bulk_in);
|
||||||
|
_tx_in_progress = false;
|
||||||
|
}
|
||||||
|
_tx_buf = _tx_buffer;
|
||||||
|
_tx_size = 0;
|
||||||
|
_tx_list.process();
|
||||||
|
MBED_ASSERT(_tx_list.empty());
|
||||||
|
|
||||||
|
// Abort RX
|
||||||
|
if (_rx_in_progress) {
|
||||||
|
endpoint_abort(_bulk_in);
|
||||||
|
_rx_in_progress = false;
|
||||||
|
}
|
||||||
|
_rx_buf = _rx_buffer;
|
||||||
|
_rx_size = 0;
|
||||||
|
_rx_list.process();
|
||||||
|
MBED_ASSERT(_rx_list.empty());
|
||||||
|
|
||||||
|
}
|
||||||
|
_connected_list.process();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USBCDC::ready()
|
bool USBCDC::ready()
|
||||||
|
@ -253,89 +353,27 @@ void USBCDC::wait_ready()
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
AsyncOp wait_op(NULL);
|
AsyncWait wait_op(this);
|
||||||
wait_op.start(&_connected_list);
|
_connected_list.add(&wait_op);
|
||||||
if (_terminal_connected) {
|
|
||||||
wait_op.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
wait_op.wait();
|
wait_op.wait(NULL);
|
||||||
}
|
|
||||||
|
|
||||||
void USBCDC::_connect_wake_all()
|
|
||||||
{
|
|
||||||
AsyncOp *wait_op = _connected_list.head();
|
|
||||||
while (wait_op != NULL) {
|
|
||||||
wait_op->complete();
|
|
||||||
wait_op = _connected_list.head();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool USBCDC::send(uint8_t *buffer, uint32_t size)
|
bool USBCDC::send(uint8_t *buffer, uint32_t size)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
if (!_terminal_connected) {
|
AsyncWrite write_op(this, buffer, size);
|
||||||
unlock();
|
_tx_list.add(&write_op);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
AsyncWrite write_op(buffer, size);
|
|
||||||
write_op.start(&_tx_list);
|
|
||||||
_send_next();
|
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
write_op.wait();
|
write_op.wait(NULL);
|
||||||
return write_op.result;
|
return write_op.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void USBCDC::_send_next()
|
|
||||||
{
|
|
||||||
assert_locked();
|
|
||||||
|
|
||||||
uint32_t actual_size;
|
|
||||||
do {
|
|
||||||
// Set current TX operation or return if there are none left
|
|
||||||
AsyncWrite *tx_cur = _tx_list.head();
|
|
||||||
if (tx_cur == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
actual_size = 0;
|
|
||||||
send_nb(tx_cur->tx_buf, tx_cur->tx_size, &actual_size, false);
|
|
||||||
tx_cur->tx_size -= actual_size;
|
|
||||||
tx_cur->tx_buf += actual_size;
|
|
||||||
if (tx_cur->tx_size == 0) {
|
|
||||||
tx_cur->result = true;
|
|
||||||
tx_cur->complete();
|
|
||||||
}
|
|
||||||
} while (actual_size > 0);
|
|
||||||
|
|
||||||
// Start transfer if it hasn't been
|
|
||||||
_send_isr_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void USBCDC::_send_abort_all()
|
|
||||||
{
|
|
||||||
assert_locked();
|
|
||||||
|
|
||||||
if (_tx_in_progress) {
|
|
||||||
endpoint_abort(_bulk_in);
|
|
||||||
_tx_in_progress = false;
|
|
||||||
}
|
|
||||||
_tx_buf = _tx_buffer;
|
|
||||||
_tx_size = 0;
|
|
||||||
|
|
||||||
AsyncWrite *tx_cur = _tx_list.head();
|
|
||||||
while (tx_cur != NULL) {
|
|
||||||
tx_cur->result = false;
|
|
||||||
tx_cur->complete();
|
|
||||||
tx_cur = _tx_list.head();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void USBCDC::send_nb(uint8_t *buffer, uint32_t size, uint32_t *actual, bool now)
|
void USBCDC::send_nb(uint8_t *buffer, uint32_t size, uint32_t *actual, bool now)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
@ -357,7 +395,6 @@ void USBCDC::send_nb(uint8_t *buffer, uint32_t size, uint32_t *actual, bool now)
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void USBCDC::_send_isr_start()
|
void USBCDC::_send_isr_start()
|
||||||
{
|
{
|
||||||
assert_locked();
|
assert_locked();
|
||||||
|
@ -382,7 +419,7 @@ void USBCDC::_send_isr(usb_ep_t endpoint)
|
||||||
_tx_size = 0;
|
_tx_size = 0;
|
||||||
_tx_in_progress = false;
|
_tx_in_progress = false;
|
||||||
|
|
||||||
_send_next();
|
_tx_list.process();
|
||||||
if (!_tx_in_progress) {
|
if (!_tx_in_progress) {
|
||||||
data_tx();
|
data_tx();
|
||||||
}
|
}
|
||||||
|
@ -392,72 +429,19 @@ bool USBCDC::receive(uint8_t *buffer, uint32_t size, uint32_t *size_read)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
if (!_terminal_connected) {
|
|
||||||
unlock();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool read_all = size_read == NULL;
|
bool read_all = size_read == NULL;
|
||||||
uint32_t size_read_dummy;
|
uint32_t size_read_dummy;
|
||||||
uint32_t *size_read_ptr = read_all ? &size_read_dummy : size_read;
|
uint32_t *size_read_ptr = read_all ? &size_read_dummy : size_read;
|
||||||
*size_read_ptr = 0;
|
*size_read_ptr = 0;
|
||||||
AsyncRead read_op(buffer, size, size_read_ptr, read_all);
|
AsyncRead read_op(this, buffer, size, size_read_ptr, read_all);
|
||||||
read_op.start(&_rx_list);
|
_rx_list.add(&read_op);
|
||||||
_receive_next();
|
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
read_op.wait();
|
read_op.wait(NULL);
|
||||||
return read_op.result;
|
return read_op.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void USBCDC::_receive_next()
|
|
||||||
{
|
|
||||||
assert_locked();
|
|
||||||
|
|
||||||
uint32_t actual_size;
|
|
||||||
do {
|
|
||||||
// Set current RX operation or return if there are none left
|
|
||||||
AsyncRead *rx_cur = _rx_list.head();
|
|
||||||
if (rx_cur == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
actual_size = 0;
|
|
||||||
receive_nb(rx_cur->rx_buf, rx_cur->rx_size, &actual_size);
|
|
||||||
rx_cur->rx_buf += actual_size;
|
|
||||||
*rx_cur->rx_actual += actual_size;
|
|
||||||
rx_cur->rx_size -= actual_size;
|
|
||||||
if ((!rx_cur->all && *rx_cur->rx_actual > 0) || (rx_cur->rx_size == 0)) {
|
|
||||||
// Wake thread if request is done
|
|
||||||
rx_cur->result = true;
|
|
||||||
rx_cur->complete();
|
|
||||||
rx_cur = NULL;
|
|
||||||
}
|
|
||||||
} while (actual_size > 0);
|
|
||||||
|
|
||||||
_receive_isr_start();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void USBCDC::_receive_abort_all()
|
|
||||||
{
|
|
||||||
assert_locked();
|
|
||||||
|
|
||||||
if (_rx_in_progress) {
|
|
||||||
endpoint_abort(_bulk_in);
|
|
||||||
_rx_in_progress = false;
|
|
||||||
}
|
|
||||||
_rx_buf = _rx_buffer;
|
|
||||||
_rx_size = 0;
|
|
||||||
|
|
||||||
AsyncRead *rx_cur = _rx_list.head();
|
|
||||||
while (rx_cur != NULL) {
|
|
||||||
rx_cur->result = false;
|
|
||||||
rx_cur->complete();
|
|
||||||
rx_cur = _rx_list.head();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void USBCDC::receive_nb(uint8_t *buffer, uint32_t size, uint32_t *size_read)
|
void USBCDC::receive_nb(uint8_t *buffer, uint32_t size, uint32_t *size_read)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -496,7 +480,7 @@ void USBCDC::_receive_isr(usb_ep_t endpoint)
|
||||||
_rx_buf = _rx_buffer;
|
_rx_buf = _rx_buffer;
|
||||||
_rx_size = read_finish(_bulk_out);
|
_rx_size = read_finish(_bulk_out);
|
||||||
_rx_in_progress = false;
|
_rx_in_progress = false;
|
||||||
_receive_next();
|
_rx_list.process();
|
||||||
if (!_rx_in_progress) {
|
if (!_rx_in_progress) {
|
||||||
data_rx();
|
data_rx();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "USBDevice_Types.h"
|
#include "USBDevice_Types.h"
|
||||||
|
|
||||||
#include "USBDevice.h"
|
#include "USBDevice.h"
|
||||||
#include "LinkedList.h"
|
#include "OperationList.h"
|
||||||
|
|
||||||
class AsyncOp;
|
class AsyncOp;
|
||||||
|
|
||||||
|
@ -180,6 +180,7 @@ protected:
|
||||||
|
|
||||||
class AsyncWrite;
|
class AsyncWrite;
|
||||||
class AsyncRead;
|
class AsyncRead;
|
||||||
|
class AsyncWait;
|
||||||
|
|
||||||
virtual void callback_reset();
|
virtual void callback_reset();
|
||||||
virtual void callback_state_change(DeviceState new_state);
|
virtual void callback_state_change(DeviceState new_state);
|
||||||
|
@ -191,15 +192,10 @@ protected:
|
||||||
void _init();
|
void _init();
|
||||||
|
|
||||||
void _change_terminal_connected(bool connected);
|
void _change_terminal_connected(bool connected);
|
||||||
void _connect_wake_all();
|
|
||||||
|
|
||||||
void _send_next();
|
|
||||||
void _send_abort_all();
|
|
||||||
void _send_isr_start();
|
void _send_isr_start();
|
||||||
void _send_isr(usb_ep_t endpoint);
|
void _send_isr(usb_ep_t endpoint);
|
||||||
|
|
||||||
void _receive_next();
|
|
||||||
void _receive_abort_all();
|
|
||||||
void _receive_isr_start();
|
void _receive_isr_start();
|
||||||
void _receive_isr(usb_ep_t endpoint);
|
void _receive_isr(usb_ep_t endpoint);
|
||||||
|
|
||||||
|
@ -211,16 +207,16 @@ protected:
|
||||||
uint8_t _cdc_new_line_coding[7];
|
uint8_t _cdc_new_line_coding[7];
|
||||||
uint8_t _config_descriptor[75];
|
uint8_t _config_descriptor[75];
|
||||||
|
|
||||||
LinkedList<AsyncOp> _connected_list;
|
OperationList<AsyncWait> _connected_list;
|
||||||
bool _terminal_connected;
|
bool _terminal_connected;
|
||||||
|
|
||||||
LinkedList<AsyncWrite> _tx_list;
|
OperationList<AsyncWrite> _tx_list;
|
||||||
bool _tx_in_progress;
|
bool _tx_in_progress;
|
||||||
uint8_t _tx_buffer[64];
|
uint8_t _tx_buffer[64];
|
||||||
uint8_t *_tx_buf;
|
uint8_t *_tx_buf;
|
||||||
uint32_t _tx_size;
|
uint32_t _tx_size;
|
||||||
|
|
||||||
LinkedList<AsyncRead> _rx_list;
|
OperationList<AsyncRead> _rx_list;
|
||||||
bool _rx_in_progress;
|
bool _rx_in_progress;
|
||||||
uint8_t _rx_buffer[64];
|
uint8_t _rx_buffer[64];
|
||||||
uint8_t *_rx_buf;
|
uint8_t *_rx_buf;
|
||||||
|
|
Loading…
Reference in New Issue