Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56795ac4 authored by Chris Fries's avatar Chris Fries Committed by Gerrit Code Review
Browse files

Merge "Add derived UsbTransport class with USB reset method"

parents 48e3cdef ceb7cbf5
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -52,6 +52,13 @@ struct usb_ifc_info {
    char device_path[256];
};

class UsbTransport : public Transport {
    // Resets the underlying transport.  Returns 0 on success.
    // This effectively simulates unplugging and replugging
    virtual int Reset() = 0;
};

typedef int (*ifc_match_func)(usb_ifc_info *ifc);

Transport* usb_open(ifc_match_func callback);
// 0 is non blocking
UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms = 0);
+21 −9
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@

using namespace std::chrono_literals;

#define MAX_RETRIES 5
#define MAX_RETRIES 2

/* Timeout in seconds for usb_wait_for_disconnect.
 * It doesn't usually take long for a device to disconnect (almost always
@@ -91,18 +91,21 @@ struct usb_handle
    unsigned char ep_out;
};

class LinuxUsbTransport : public Transport {
class LinuxUsbTransport : public UsbTransport {
  public:
    explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
    explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout = 0)
        : handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
    ~LinuxUsbTransport() override = default;

    ssize_t Read(void* data, size_t len) override;
    ssize_t Write(const void* data, size_t len) override;
    int Close() override;
    int Reset() override;
    int WaitForDisconnect() override;

  private:
    std::unique_ptr<usb_handle> handle_;
    const uint32_t ms_timeout_;

    DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport);
};
@@ -402,7 +405,7 @@ ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)
        bulk.ep = handle_->ep_out;
        bulk.len = xfer;
        bulk.data = data;
        bulk.timeout = 0;
        bulk.timeout = ms_timeout_;

        n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk);
        if(n != xfer) {
@@ -436,7 +439,7 @@ ssize_t LinuxUsbTransport::Read(void* _data, size_t len)
        bulk.ep = handle_->ep_in;
        bulk.len = xfer;
        bulk.data = data;
        bulk.timeout = 0;
        bulk.timeout = ms_timeout_;
        retry = 0;

        do {
@@ -447,7 +450,7 @@ ssize_t LinuxUsbTransport::Read(void* _data, size_t len)
            if (n < 0) {
                DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno));
                if (++retry > MAX_RETRIES) return -1;
                std::this_thread::sleep_for(1s);
                std::this_thread::sleep_for(100ms);
            }
        } while (n < 0);

@@ -477,10 +480,19 @@ int LinuxUsbTransport::Close()
    return 0;
}

Transport* usb_open(ifc_match_func callback)
{
int LinuxUsbTransport::Reset() {
    int ret = 0;
    // We reset the USB connection
    if ((ret = ioctl(handle_->desc, USBDEVFS_RESET, 0))) {
        return ret;
    }

    return 0;
}

UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
    std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback);
    return handle ? new LinuxUsbTransport(std::move(handle)) : nullptr;
    return handle ? new LinuxUsbTransport(std::move(handle), timeout_ms) : nullptr;
}

/* Wait for the system to notice the device is gone, so that a subsequent
+21 −5
Original line number Diff line number Diff line
@@ -65,17 +65,20 @@ struct usb_handle
    unsigned int zero_mask;
};

class OsxUsbTransport : public Transport {
class OsxUsbTransport : public UsbTransport {
  public:
    OsxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
    OsxUsbTransport(std::unique_ptr<usb_handle> handle, uint32_t ms_timeout)
        : handle_(std::move(handle)), ms_timeout_(ms_timeout) {}
    ~OsxUsbTransport() override = default;

    ssize_t Read(void* data, size_t len) override;
    ssize_t Write(const void* data, size_t len) override;
    int Close() override;
    int Reset() override;

  private:
    std::unique_ptr<usb_handle> handle_;
    const uint32_t ms_timeout_;

    DISALLOW_COPY_AND_ASSIGN(OsxUsbTransport);
};
@@ -456,7 +459,7 @@ static int init_usb(ifc_match_func callback, std::unique_ptr<usb_handle>* handle
 * Definitions of this file's public functions.
 */

Transport* usb_open(ifc_match_func callback) {
UsbTransport* usb_open(ifc_match_func callback, uint32_t timeout_ms) {
    std::unique_ptr<usb_handle> handle;

    if (init_usb(callback, &handle) < 0) {
@@ -464,7 +467,7 @@ Transport* usb_open(ifc_match_func callback) {
        return nullptr;
    }

    return new OsxUsbTransport(std::move(handle));
    return new OsxUsbTransport(std::move(handle), timeout_ms);
}

int OsxUsbTransport::Close() {
@@ -472,6 +475,17 @@ int OsxUsbTransport::Close() {
    return 0;
}

int OsxUsbTransport::Reset() {
    IOReturn result = (*handle_->interface)->ResetDevice(handle_->interface);

    if (result == 0) {
        return 0;
    } else {
        ERR("usb_reset failed with status %x\n", result);
        return -1;
    }
}

ssize_t OsxUsbTransport::Read(void* data, size_t len) {
    IOReturn result;
    UInt32 numBytes = len;
@@ -494,7 +508,9 @@ ssize_t OsxUsbTransport::Read(void* data, size_t len) {
        return -1;
    }

    result = (*handle_->interface)->ReadPipe(handle_->interface, handle_->bulkIn, data, &numBytes);
    result = (*handle_->interface)
                     ->ReadPipeTO(handle_->interface, handle_->bulkIn, data, &numBytes,
                                  USB_TRANSACTION_TIMEOUT, USB_TRANSACTION_TIMEOUT);

    if (result == 0) {
        return (int) numBytes;
+9 −3
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ struct usb_handle {
    std::string interface_name;
};

class WindowsUsbTransport : public Transport {
class WindowsUsbTransport : public UsbTransport {
  public:
    WindowsUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {}
    ~WindowsUsbTransport() override = default;
@@ -74,6 +74,7 @@ class WindowsUsbTransport : public Transport {
    ssize_t Read(void* data, size_t len) override;
    ssize_t Write(const void* data, size_t len) override;
    int Close() override;
    int Reset() override;

  private:
    std::unique_ptr<usb_handle> handle_;
@@ -261,6 +262,12 @@ int WindowsUsbTransport::Close() {
    return 0;
}

int WindowsUsbTransport::Reset() {
    DBG("usb_reset currently unsupported\n\n");
    // TODO, this is a bit complicated since it is using ADB
    return -1;
}

int recognized_device(usb_handle* handle, ifc_match_func callback) {
    struct usb_ifc_info info;
    USB_DEVICE_DESCRIPTOR device_desc;
@@ -366,8 +373,7 @@ static std::unique_ptr<usb_handle> find_usb_device(ifc_match_func callback) {
    return handle;
}

Transport* usb_open(ifc_match_func callback)
{
UsbTransport* usb_open(ifc_match_func callback, uint32_t) {
    std::unique_ptr<usb_handle> handle = find_usb_device(callback);
    return handle ? new WindowsUsbTransport(std::move(handle)) : nullptr;
}