summaryrefslogtreecommitdiff
path: root/fastboot/usb_linux.cpp
diff options
context:
space:
mode:
authorDavid Pursell <dpursell@google.com>2015-10-30 11:22:01 -0700
committerDavid Pursell <dpursell@google.com>2015-11-16 09:31:07 -0800
commit0b156638307db890e5539b52521fd24beb3440cb (patch)
tree42feda4e66833b368f6c6b7c6a63562baa0db084 /fastboot/usb_linux.cpp
parent942f8ea84f3f96c2e2556fe90ebba0ec76730553 (diff)
fastboot: create Transport object (take 2).
(Second upload of this CL; original upload had the wrong version of usb_windows.cpp that caused a compilation error. Fixed error and re-tested.) This CL creates a Transport object to provide a generic interface for various transports. Specifically this is designed to be able to add UDP support to fastboot in an upcoming CL without changing the main program logic. Also includes some minor code style fixes and replaces malloc/free in the USB implementation files with smart pointers and std::string. Bug: http://b/22029765 Change-Id: I1175bbce08690fbd15f51e68166be9b3e9973ea0
Diffstat (limited to 'fastboot/usb_linux.cpp')
-rw-r--r--fastboot/usb_linux.cpp91
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);
}