diff options
Diffstat (limited to 'fastboot/usb_linux.cpp')
-rw-r--r-- | fastboot/usb_linux.cpp | 91 |
1 files changed, 48 insertions, 43 deletions
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp index 7b879073d..02ffcd978 100644 --- a/fastboot/usb_linux.cpp +++ b/fastboot/usb_linux.cpp @@ -43,6 +43,8 @@ #include <linux/version.h> #include <linux/usb/ch9.h> +#include <memory> + #include "fastboot.h" #include "usb.h" @@ -85,6 +87,22 @@ struct usb_handle unsigned char ep_out; }; +class LinuxUsbTransport : public Transport { + public: + LinuxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {} + ~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 WaitForDisconnect() override; + + private: + std::unique_ptr<usb_handle> handle_; + + DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport); +}; + /* True if name isn't a valid name for a USB device in /sys/bus/usb/devices. * Device names are made up of numbers, dots, and dashes, e.g., '7-1.5'. * We reject interfaces (e.g., '7-1.5:1.0') and host controllers (e.g. 'usb1'). @@ -308,9 +326,9 @@ static int convert_to_devfs_name(const char* sysfs_name, return 0; } -static usb_handle *find_usb_device(const char *base, ifc_match_func callback) +static std::unique_ptr<usb_handle> find_usb_device(const char* base, ifc_match_func callback) { - usb_handle *usb = 0; + std::unique_ptr<usb_handle> usb; char devname[64]; char desc[1024]; int n, in, out, ifc; @@ -321,39 +339,37 @@ static usb_handle *find_usb_device(const char *base, ifc_match_func callback) int writable; busdir = opendir(base); - if(busdir == 0) return 0; + if (busdir == 0) return 0; - while((de = readdir(busdir)) && (usb == 0)) { - if(badname(de->d_name)) continue; + while ((de = readdir(busdir)) && (usb == nullptr)) { + if (badname(de->d_name)) continue; - if(!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) { + if (!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) { // DBG("[ scanning %s ]\n", devname); writable = 1; - if((fd = open(devname, O_RDWR)) < 0) { + if ((fd = open(devname, O_RDWR)) < 0) { // Check if we have read-only access, so we can give a helpful // diagnostic like "adb devices" does. writable = 0; - if((fd = open(devname, O_RDONLY)) < 0) { + if ((fd = open(devname, O_RDONLY)) < 0) { continue; } } n = read(fd, desc, sizeof(desc)); - if(filter_usb_device(de->d_name, desc, n, writable, callback, - &in, &out, &ifc) == 0) { - usb = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle))); + if (filter_usb_device(de->d_name, desc, n, writable, callback, &in, &out, &ifc) == 0) { + usb.reset(new usb_handle()); strcpy(usb->fname, devname); usb->ep_in = in; usb->ep_out = out; usb->desc = fd; n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc); - if(n != 0) { + if (n != 0) { close(fd); - free(usb); - usb = 0; + usb.reset(); continue; } } else { @@ -366,14 +382,14 @@ static usb_handle *find_usb_device(const char *base, ifc_match_func callback) return usb; } -int usb_write(usb_handle *h, const void *_data, int len) +ssize_t LinuxUsbTransport::Write(const void* _data, size_t len) { unsigned char *data = (unsigned char*) _data; unsigned count = 0; struct usbdevfs_bulktransfer bulk; int n; - if(h->ep_out == 0 || h->desc == -1) { + if (handle_->ep_out == 0 || handle_->desc == -1) { return -1; } @@ -381,12 +397,12 @@ int usb_write(usb_handle *h, const void *_data, int len) int xfer; xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; - bulk.ep = h->ep_out; + bulk.ep = handle_->ep_out; bulk.len = xfer; bulk.data = data; bulk.timeout = 0; - n = ioctl(h->desc, USBDEVFS_BULK, &bulk); + n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk); if(n != xfer) { DBG("ERROR: n = %d, errno = %d (%s)\n", n, errno, strerror(errno)); @@ -401,30 +417,30 @@ int usb_write(usb_handle *h, const void *_data, int len) return count; } -int usb_read(usb_handle *h, void *_data, int len) +ssize_t LinuxUsbTransport::Read(void* _data, size_t len) { unsigned char *data = (unsigned char*) _data; unsigned count = 0; struct usbdevfs_bulktransfer bulk; int n, retry; - if(h->ep_in == 0 || h->desc == -1) { + if (handle_->ep_in == 0 || handle_->desc == -1) { return -1; } while(len > 0) { int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; - bulk.ep = h->ep_in; + bulk.ep = handle_->ep_in; bulk.len = xfer; bulk.data = data; bulk.timeout = 0; retry = 0; do{ - DBG("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname); - n = ioctl(h->desc, USBDEVFS_BULK, &bulk); - DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, h->fname, retry); + DBG("[ usb read %d fd = %d], fname=%s\n", xfer, handle_->desc, handle_->fname); + n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk); + DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, handle_->fname, retry); if( n < 0 ) { DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno)); @@ -446,24 +462,12 @@ int usb_read(usb_handle *h, void *_data, int len) return count; } -void usb_kick(usb_handle *h) -{ - int fd; - - fd = h->desc; - h->desc = -1; - if(fd >= 0) { - close(fd); - DBG("[ usb closed %d ]\n", fd); - } -} - -int usb_close(usb_handle *h) +int LinuxUsbTransport::Close() { int fd; - fd = h->desc; - h->desc = -1; + fd = handle_->desc; + handle_->desc = -1; if(fd >= 0) { close(fd); DBG("[ usb closed %d ]\n", fd); @@ -472,20 +476,21 @@ int usb_close(usb_handle *h) return 0; } -usb_handle *usb_open(ifc_match_func callback) +Transport* usb_open(ifc_match_func callback) { - return find_usb_device("/sys/bus/usb/devices", callback); + std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback); + return handle ? new LinuxUsbTransport(std::move(handle)) : nullptr; } /* Wait for the system to notice the device is gone, so that a subsequent * fastboot command won't try to access the device before it's rebooted. * Returns 0 for success, -1 for timeout. */ -int usb_wait_for_disconnect(usb_handle *usb) +int LinuxUsbTransport::WaitForDisconnect() { double deadline = now() + WAIT_FOR_DISCONNECT_TIMEOUT; while (now() < deadline) { - if (access(usb->fname, F_OK)) + if (access(handle_->fname, F_OK)) return 0; usleep(50000); } |