libusbhost: Add support for creating a usb_device struct from an existing fd

We will use this for sharing USB file descriptors across address spaces via Binder

Change-Id: Iadbd3e0a4178f79d1d778fdfd5175f6fe0e2aaf5
Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood 2010-12-12 14:17:02 -08:00
parent 127fd070f0
commit cd185f23cc
2 changed files with 67 additions and 29 deletions

View file

@ -81,6 +81,16 @@ struct usb_device *usb_device_open(const char *dev_name);
/* Releases all resources associated with the USB device */
void usb_device_close(struct usb_device *device);
/* Creates a usb_device object for already open USB device.
* This is intended to facilitate sharing USB devices across address spaces.
*/
struct usb_device *usb_device_new(const char *dev_name, int fd);
/* Returns the file descriptor for the usb_device. Used in conjunction with
* usb_device_new() for sharing USB devices across address spaces.
*/
int usb_device_get_fd(struct usb_device *device);
/* Returns the name for the USB device, which is the same as
* the dev_name passed to usb_device_open()
*/

View file

@ -214,11 +214,7 @@ void usb_host_run(struct usb_host_context *context,
struct usb_device *usb_device_open(const char *dev_name)
{
struct usb_device *device = calloc(1, sizeof(struct usb_device));
int fd, length, did_retry = 0;
strcpy(device->dev_name, dev_name);
device->writeable = 1;
int fd, did_retry = 0, writeable = 1;
retry:
fd = open(dev_name, O_RDWR);
@ -233,23 +229,16 @@ retry:
goto retry;
}
if (fd < 0) goto fail;
device->writeable = 0;
if (fd < 0)
return NULL;
writeable = 0;
D("[ usb open read-only %s fd = %d]\n", dev_name, fd);
}
length = read(fd, device->desc, sizeof(device->desc));
D("usb_device_open read returned %d errno %d\n", fd, errno);
if (length < 0)
goto fail;
device->fd = fd;
device->desc_length = length;
return device;
fail:
close(fd);
free(device);
return NULL;
struct usb_device* result = usb_device_new(dev_name, fd);
if (result)
result->writeable = writeable;
return result;
}
void usb_device_close(struct usb_device *device)
@ -258,6 +247,53 @@ void usb_device_close(struct usb_device *device)
free(device);
}
struct usb_device *usb_device_new(const char *dev_name, int fd)
{
struct usb_device *device = calloc(1, sizeof(struct usb_device));
int length;
if (lseek(fd, 0, SEEK_SET) != 0)
goto failed;
length = read(fd, device->desc, sizeof(device->desc));
D("usb_device_new read returned %d errno %d\n", fd, errno);
if (length < 0)
goto failed;
device->fd = fd;
device->desc_length = length;
// assume we are writeable, since usb_device_get_fd will only return writeable fds
device->writeable = 1;
return device;
failed:
close(fd);
free(device);
return NULL;
}
static int usb_device_reopen_writeable(struct usb_device *device)
{
if (device->writeable)
return 1;
int fd = open(device->dev_name, O_RDWR);
if (fd >= 0) {
close(device->fd);
device->fd = fd;
device->writeable = 1;
return 1;
}
D("usb_device_reopen_writeable failed errno %d\n", errno);
return 0;
}
int usb_device_get_fd(struct usb_device *device)
{
if (!usb_device_reopen_writeable(device))
return -1;
return device->fd;
}
const char* usb_device_get_name(struct usb_device *device)
{
return device->dev_name;
@ -300,16 +336,8 @@ int usb_device_send_control(struct usb_device *device,
struct usbdevfs_ctrltransfer ctrl;
// this usually requires read/write permission
if (!device->writeable) {
int fd = open(device->dev_name, O_RDWR);
if (fd > 0) {
close(device->fd);
device->fd = fd;
device->writeable = 1;
} else {
return -1;
}
}
if (!usb_device_reopen_writeable(device))
return -1;
memset(&ctrl, 0, sizeof(ctrl));
ctrl.bRequestType = requestType;