Skip to content

Commit

Permalink
Merge pull request #18 from fpoussin/feature-endpoints
Browse files Browse the repository at this point in the history
Adding multiple endpoints support (#10)
  • Loading branch information
fpoussin authored Mar 22, 2019
2 parents 310b2eb + 07afe56 commit 780ebfc
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 79 deletions.
10 changes: 6 additions & 4 deletions examples/usb/SimpleBulkTransfer/usbexample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ void UsbExample::setupDevice() {
m_config.alternate = 0;
m_config.config = 0;
m_config.interface = 1;
m_config.readEp = 0x81;
m_config.writeEp = 0x02;

//
m_read_ep = 0x81;
m_write_ep = 0x02;

//
m_usb_dev->setFilter(m_filter);
Expand All @@ -66,9 +68,9 @@ bool UsbExample::closeDevice() {
}

void UsbExample::read(QByteArray *buf) {
m_usb_dev->read(buf, 1);
m_usb_dev->read(buf, 1, m_read_ep);
}

void UsbExample::write(QByteArray *buf) {
m_usb_dev->write(buf, static_cast<quint32>(buf->size()));
m_usb_dev->write(buf, static_cast<quint32>(buf->size()), m_write_ep);
}
3 changes: 3 additions & 0 deletions examples/usb/SimpleBulkTransfer/usbexample.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public slots:

QtUsb::DeviceFilter m_filter;
QtUsb::DeviceConfig m_config;

QtUsb::endpoint m_read_ep;
QtUsb::endpoint m_write_ep;
};

#endif // USBEXAMPLE_H
1 change: 1 addition & 0 deletions examples/usb/UsbNotifications/usbexample.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public slots:

private:
QUsbManager m_usb_manager;

};

#endif // USBEXAMPLE_H
95 changes: 51 additions & 44 deletions src/usb/qusbdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,14 @@ void QUsbDevicePrivate::setDefaults() {
q->m_connected = false;
q->m_debug = false;
q->m_timeout = QtUsb::DefaultTimeout;
q->m_config.readEp = 0x81;
q->m_config.writeEp = 0x01;
q->m_config.config = 0x01;
q->m_config.interface = 0x00;
q->m_config.alternate = 0x00;
}

void QUsbDevicePrivate::printUsbError(int error_code) const
{
qWarning("libusb Error: %s", libusb_strerror((enum libusb_error)error_code));
qWarning("libusb Error: %s", libusb_strerror(static_cast<enum libusb_error>(error_code)));
}

QUsbDevice::QUsbDevice(QObject* parent) : QObject(*(new QUsbDevicePrivate), parent), d_dummy(Q_NULLPTR) {
Expand All @@ -37,7 +35,7 @@ QUsbDevice::QUsbDevice(QObject* parent) : QObject(*(new QUsbDevicePrivate), pare
if (r < 0) {
qCritical("LibUsb Init Error %d", r); // there was an error
}
mReadBufferSize = 1024 * 64;
m_read_buffer_size = 1024 * 64;
}

QUsbDevice::~QUsbDevice() {
Expand All @@ -64,21 +62,21 @@ QByteArray QUsbDevice::speedString() const {
return "Error";
}

qint32 QUsbDevice::write(const QByteArray &buf) {
return this->write(&buf, buf.size());
qint32 QUsbDevice::write(const QByteArray &buf, QtUsb::endpoint endpoint) {
return this->write(&buf, buf.size(), endpoint);
}

qint32 QUsbDevice::read(QByteArray *buf) { return this->read(buf, 4096); }
qint32 QUsbDevice::read(QByteArray *buf, QtUsb::endpoint endpoint) { return this->read(buf, 4096, endpoint); }

bool QUsbDevice::write(char c) {
bool QUsbDevice::write(char c, QtUsb::endpoint endpoint) {
QByteArray buf(1, c);
return this->write(buf) > 0;
return this->write(buf, endpoint) > 0;
}

bool QUsbDevice::read(char *c) {
bool QUsbDevice::read(char *c, QtUsb::endpoint endpoint) {
QByteArray buf;
Q_CHECK_PTR(c);
if (this->read(&buf, 1) > 0) {
if (this->read(&buf, 1, endpoint) > 0) {
*c = buf.at(0);
return true;
}
Expand All @@ -90,8 +88,6 @@ void QUsbDevice::showSettings() {
<< "Debug" << m_debug << "\n"
<< "Config" << m_config.config << "\n"
<< "Timeout" << m_timeout << "\n"
<< "ReadEp" << QString::number(m_config.readEp, 16) << "\n"
<< "WriteEp" << QString::number(m_config.writeEp, 16) << "\n"
<< "Interface" << m_config.interface << "\n"
<< "Device.pid" << QString::number(m_filter.pid, 16) << "\n"
<< "Device.vid" << QString::number(m_filter.vid, 16) << "\n";
Expand Down Expand Up @@ -158,7 +154,7 @@ qint32 QUsbDevice::open() {
rc = libusb_open(dev, &d->m_devHandle);
if (rc == 0) break;
else {
qWarning("Failed to open device: %s", libusb_strerror((enum libusb_error)rc));
qWarning("Failed to open device: %s", libusb_strerror(static_cast<enum libusb_error>(rc)));
}
}
}
Expand Down Expand Up @@ -247,17 +243,20 @@ void QUsbDevice::setDebug(bool enable) {
libusb_set_debug(d->m_ctx, LIBUSB_LOG_LEVEL_ERROR);
}

void QUsbDevice::flush() {
void QUsbDevice::flush(quint8 endpoint) {
Q_D(QUsbDevice);
QByteArray buf;
qint32 read_bytes;

buf.resize(4096);
libusb_bulk_transfer(d->m_devHandle, m_config.readEp, (uchar*)(buf.data()), 4096,
libusb_bulk_transfer(d->m_devHandle,
endpoint,
reinterpret_cast<uchar*>(buf.data()),
4096,
&read_bytes, 25);
}

qint32 QUsbDevice::read(QByteArray* buf, quint32 len) {
qint32 QUsbDevice::read(QByteArray* buf, int len, QtUsb::endpoint endpoint) {
UsbPrintFuncName();
Q_D(QUsbDevice);
Q_CHECK_PTR(buf);
Expand All @@ -273,33 +272,36 @@ qint32 QUsbDevice::read(QByteArray* buf, quint32 len) {
read_total = 0;
read_bytes = 0;

if (mReadBuffer.isEmpty())
if (m_read_buffer.isEmpty())
if (m_debug) qDebug("Read cache empty");

/* Fetch from buffer first */
if (len <= (quint32)mReadBuffer.size() && !mReadBuffer.isEmpty()) {
if (m_debug) qDebug("Reading %d bytes from cache", mReadBuffer.size());
*buf = mReadBuffer.mid(0, len);
mReadBuffer.remove(0, len);
return len;
if (len <= m_read_buffer.size() && !m_read_buffer.isEmpty()) {
if (m_debug) qDebug("Reading %d bytes from cache", m_read_buffer.size());
*buf = m_read_buffer.mid(0, (len));
m_read_buffer.remove(0, len);
return static_cast<int>(len);
}

/* Copy what's in the read buffer */
len -= mReadBuffer.size();
*buf = mReadBuffer;
mReadBuffer.clear();
mReadBuffer.resize(mReadBufferSize);
len -= static_cast<quint32>(m_read_buffer.size());
*buf = m_read_buffer;
m_read_buffer.clear();
m_read_buffer.resize(m_read_buffer_size);

/* Wait till we have at least the required data */
timer.start();
rc = LIBUSB_SUCCESS;
while (timer.elapsed() < m_timeout && (qint32)len - read_total > 0) {
rc = libusb_bulk_transfer(d->m_devHandle, m_config.readEp,
(uchar*)(mReadBuffer.data() + read_total),
mReadBufferSize, &read_bytes, 10);
while (timer.elapsed() < m_timeout && len - read_total > 0) {
rc = libusb_bulk_transfer(d->m_devHandle,
endpoint,
reinterpret_cast<uchar*>((m_read_buffer.data() + read_total)),
m_read_buffer_size,
&read_bytes,
10);
read_total += read_bytes;
if (rc == LIBUSB_ERROR_PIPE) {
libusb_clear_halt(d->m_devHandle, m_config.readEp);
libusb_clear_halt(d->m_devHandle, endpoint);
continue;
}
if (rc == LIBUSB_ERROR_TIMEOUT) {
Expand All @@ -310,15 +312,15 @@ qint32 QUsbDevice::read(QByteArray* buf, quint32 len) {
if (m_debug && timer.elapsed() >= m_timeout) qDebug("USB Timeout!");

// we resize the buffer.
mReadBuffer.resize(read_total);
buf->append(mReadBuffer.mid(0, len));
mReadBuffer.remove(0, len);
m_read_buffer.resize(read_total);
buf->append(m_read_buffer.mid(0, len));
m_read_buffer.remove(0, len);

QString datastr, s;

if (m_debug) {
for (qint32 i = 0; i < read_total; i++) {
datastr.append(s.sprintf("%02X:", (uchar)buf->at(i)));
for (int i = 0; i < read_total; i++) {
datastr.append(s.sprintf("%02X:", buf->at(i)));
}
datastr.remove(datastr.size() - 1, 1); // remove last colon
qDebug("%d bytes Received: %s", read_total, datastr.toStdString().c_str());
Expand All @@ -332,7 +334,7 @@ qint32 QUsbDevice::read(QByteArray* buf, quint32 len) {
return read_total;
}

qint32 QUsbDevice::write(const QByteArray* buf, quint32 len) {
qint32 QUsbDevice::write(const QByteArray* buf, int len, QtUsb::endpoint endpoint) {
UsbPrintFuncName();
Q_D(QUsbDevice);
Q_CHECK_PTR(buf);
Expand All @@ -345,8 +347,8 @@ qint32 QUsbDevice::write(const QByteArray* buf, quint32 len) {

if (m_debug) {
QString cmd, s;
for (quint32 i = 0; i < len; i++) {
cmd.append(s.sprintf("%02X:", (uchar)buf->at(i)));
for (int i = 0; i < len; i++) {
cmd.append(s.sprintf("%02X:", buf->at(i)));
}
cmd.remove(cmd.size() - 1, 1); // remove last colon;
qDebug() << "Sending" << len << "bytes:" << cmd;
Expand All @@ -359,16 +361,21 @@ qint32 QUsbDevice::write(const QByteArray* buf, quint32 len) {

timer.start();
while (timer.elapsed() < m_timeout && len - sent > 0) {
rc = libusb_bulk_transfer(d->m_devHandle, (m_config.writeEp),
(uchar*)buf->data(), len, &sent_tmp, m_timeout);
QByteArray b(buf->mid(0, len)); // Need a local copy since we got const data
rc = libusb_bulk_transfer(d->m_devHandle,
endpoint,
reinterpret_cast<unsigned char*>(b.data()),
len,
&sent_tmp,
m_timeout);
if (rc == LIBUSB_ERROR_PIPE) {
libusb_clear_halt(d->m_devHandle, m_config.readEp);
libusb_clear_halt(d->m_devHandle, endpoint);
}
sent += sent_tmp;
if (rc != LIBUSB_SUCCESS) break;
}

if ((qint32)len != sent) {
if (len != sent) {
qWarning("Only sent %d out of %d", sent, len);
return -1;
}
Expand Down
50 changes: 21 additions & 29 deletions src/usb/qusbdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ class Q_USB_EXPORT QUsbDevice : public QObject {
Q_PROPERTY(QtUsb::DeviceConfig config READ config WRITE setConfig)
Q_PROPERTY(quint16 pid READ pid)
Q_PROPERTY(quint16 vid READ vid)
Q_PROPERTY(quint8 readEp READ readEp)
Q_PROPERTY(quint8 writeEp READ writeEp)
Q_PROPERTY(quint16 timeout READ timeout WRITE setTimeout)
Q_PROPERTY(QtUsb::DeviceSpeed speed READ speed)

Expand Down Expand Up @@ -100,18 +98,6 @@ class Q_USB_EXPORT QUsbDevice : public QObject {
*
* @return quint8
*/
quint8 readEp(void) const { return m_config.readEp; }
/**
* @brief Get current write (OUT) endpoint
*
* @return quint8
*/
quint8 writeEp(void) const { return m_config.writeEp; }
/**
* @brief Get current timeout
*
* @return quint16 Timeout
*/
quint16 timeout(void) const { return m_timeout; }
/**
* @brief Get debug mode
Expand Down Expand Up @@ -146,6 +132,7 @@ public slots:
* @return qint32
*/
qint32 open();

/**
* @brief See base class
*
Expand All @@ -156,52 +143,57 @@ public slots:
* @brief See base class
*
*/
void flush();
void flush(quint8 endpoint);

/**
* @brief See base class
*
* @param buf
* @param maxSize
* @return qint32
*/
qint32 read(QByteArray *buf, quint32 len);
qint32 read(QByteArray *buf, int len, QtUsb::endpoint endpoint);

/**
* @brief See base class
*
* @param buf
* @param maxSize
* @return qint32
*/
qint32 write(const QByteArray *buf, quint32 len);
qint32 write(const QByteArray *buf, int len, QtUsb::endpoint endpoint);

/**
* @brief Write full array to device
*
* @param buf data to write
* @return qint32 actual number of bytes written on success, negative on error
*/
qint32 write(const QByteArray &buf);
/**
* @brief Read maximum amount of bytes to buffer, up to 4096 bytes
*
* @param buf data to write into
* @return qint32 actual number of bytes read on success, negative on error
*/
qint32 read(QByteArray *buf);
qint32 read(QByteArray *buf, QtUsb::endpoint endpoint);

/**
* @brief Write full array to device
*
* @param buf data to write
* @return qint32 actual number of bytes written on success, negative on error
*/
qint32 write(const QByteArray &buf, QtUsb::endpoint endpoint);

/**
* @brief Write a single char
*
* @param c char
* @return bool true on sucess
*/
bool write(char c);
bool write(char c, QtUsb::endpoint endpoint);

/**
* @brief Read a single char
*
* @param c char
* @return bool true on sucess
*/
bool read(char *c);
bool read(char *c, QtUsb::endpoint endpoint);

/**
* @brief Print settings to qDebug
Expand All @@ -223,8 +215,8 @@ private slots:
QtUsb::DeviceConfig m_config; /**< Device config */
QtUsb::DeviceSpeed m_spd; /**< Device speed */

QByteArray mReadBuffer;
quint32 mReadBufferSize;
QByteArray m_read_buffer;
int m_read_buffer_size;
};

QT_END_NAMESPACE
Expand Down
4 changes: 2 additions & 2 deletions src/usb/qusbtypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace QtUsb {

const quint16 DefaultTimeout = 250; /**< Default timeout in milliseconds */

typedef quint8 endpoint;

/**
* @brief USB speeds
*
Expand Down Expand Up @@ -37,8 +39,6 @@ enum DeviceStatus {
*
*/
typedef struct {
quint8 readEp; /**< Read Endpoint (IN) */
quint8 writeEp; /**< Write Endpoint (OUT) */
quint8 config; /**< Configuration index */
quint8 interface; /**< Interface index */
quint8 alternate; /**< Alternate configuration index */
Expand Down

0 comments on commit 780ebfc

Please sign in to comment.