Android support (#918)
* Support of alternative layout and basic cmake * Added ltdl link * Added open from FD * Changed behavoir of library... integration of autotools * Redesign of USB device access, crash fix * Removed non needed cmake files * Fixed missing merge
This commit is contained in:
@@ -198,6 +198,7 @@ int gp_init_localedir (const char *localedir);
|
||||
*/
|
||||
#ifdef _GPHOTO2_INTERNAL_CODE
|
||||
#define CAMLIBDIR_ENV "CAMLIBS"
|
||||
#define CAMLIBDIR_PREFIX_ENV "CAMLIBS_PREFIX"
|
||||
#endif /* _GPHOTO2_INTERNAL_CODE */
|
||||
|
||||
|
||||
|
||||
@@ -179,8 +179,13 @@ foreach_func (const char *filename, lt_ptr data)
|
||||
{
|
||||
foreach_data_t *fd = data;
|
||||
CameraList *list = fd->list;
|
||||
char *prefix = getenv(CAMLIBDIR_PREFIX_ENV);
|
||||
|
||||
GP_LOG_D ("Found '%s'.", filename);
|
||||
if(prefix && !strstr(filename,prefix)) {
|
||||
GP_LOG_D("Skipping camlib filename '%s' not matching %s.",filename,prefix);
|
||||
return (0);
|
||||
}
|
||||
fd->result = gp_list_append (list, filename, NULL);
|
||||
|
||||
return ((fd->result == GP_OK)?0:1);
|
||||
@@ -312,6 +317,7 @@ unlocked_gp_abilities_list_load_dir (CameraAbilitiesList *list, const char *dir,
|
||||
return GP_ERROR_CANCEL;
|
||||
}
|
||||
}
|
||||
|
||||
gp_context_progress_stop (context, p);
|
||||
lt_dlexit ();
|
||||
gp_list_free (flist);
|
||||
|
||||
@@ -384,6 +384,10 @@ GP_CHECK_LIBRARY([LIBUSB1],[libusb-1.0],[>= 1.0.0],
|
||||
AC_DEFINE([HAVE_LIBUSB_STRERROR], [1],
|
||||
[Define if libusb-1.0 has libusb_strerror])
|
||||
])
|
||||
AC_CHECK_FUNC([libusb_wrap_sys_device], [dnl
|
||||
AC_DEFINE([HAVE_LIBUSB_WRAP_SYS_DEVICE], [1],
|
||||
[Define if libusb-1.0 has libusb_wrap_sys_device])
|
||||
])
|
||||
LIBS="$save_LIBS"
|
||||
], [],
|
||||
[default-on],
|
||||
|
||||
@@ -106,6 +106,7 @@ int gp_port_init_localedir (const char *localedir);
|
||||
*/
|
||||
#ifdef _GPHOTO2_INTERNAL_CODE
|
||||
#define IOLIBDIR_ENV "IOLIBS"
|
||||
#define IOLIBDIR_PREFIX_ENV "IOLIBS_PREFIX"
|
||||
#endif /* _GPHOTO2_INTERNAL_CODE */
|
||||
|
||||
|
||||
|
||||
@@ -202,6 +202,21 @@ int gp_port_set_pin (GPPort *port, GPPin pin, GPLevel level);
|
||||
int gp_port_send_break (GPPort *port, int duration);
|
||||
int gp_port_flush (GPPort *port, int direction);
|
||||
|
||||
/**
|
||||
* \brief Allow using file descriptor of USB device without auto-discovery
|
||||
*
|
||||
* This is required for access of USB on android since applications don't have direct
|
||||
* access to USB device
|
||||
*
|
||||
* It must be called prior to library initialization
|
||||
*/
|
||||
int gp_port_usb_set_sys_device(int fd);
|
||||
|
||||
/**
|
||||
* \brief Get externally set file descriptor of USB device, return -1 if not set
|
||||
*/
|
||||
int gp_port_usb_get_sys_device(void);
|
||||
|
||||
int gp_port_usb_find_device (GPPort *port, int idvendor, int idproduct);
|
||||
int gp_port_usb_find_device_by_class (GPPort *port, int mainclass, int subclass, int protocol);
|
||||
int gp_port_usb_clear_halt (GPPort *port, int ep);
|
||||
|
||||
@@ -238,8 +238,13 @@ foreach_func (const char *filename, lt_ptr data)
|
||||
GPPortType type;
|
||||
unsigned int j, old_size = list->count;
|
||||
int result;
|
||||
char *prefix = getenv(IOLIBDIR_PREFIX_ENV);
|
||||
|
||||
GP_LOG_D ("Called for filename '%s'.", filename );
|
||||
if(prefix && !strstr(filename,prefix)) {
|
||||
GP_LOG_D("Skipping filename '%s' not matching %s.",filename,prefix);
|
||||
return (0);
|
||||
}
|
||||
|
||||
lh = lt_dlopenext (filename);
|
||||
if (!lh) {
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <gphoto2/gphoto2-port-library.h>
|
||||
#include <gphoto2/gphoto2-port-log.h>
|
||||
#include <gphoto2/gphoto2-port-locking.h>
|
||||
#include <gphoto2/gphoto2-port.h>
|
||||
|
||||
#include "libgphoto2_port/gphoto2-port-info.h"
|
||||
|
||||
@@ -1214,3 +1215,37 @@ gp_port_get_error (GPPort *port)
|
||||
|
||||
return _("No error description available");
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
|
||||
static int gp_port_usb_fd = -1;
|
||||
|
||||
int
|
||||
gp_port_usb_set_sys_device(int fd)
|
||||
{
|
||||
gp_port_usb_fd = fd;
|
||||
return (GP_OK);
|
||||
}
|
||||
|
||||
int
|
||||
gp_port_usb_get_sys_device(void)
|
||||
{
|
||||
return gp_port_usb_fd;
|
||||
}
|
||||
#else
|
||||
int gp_port_usb_set_sys_device(int fd)
|
||||
{
|
||||
return GP_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
int gp_port_usb_get_sys_device()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ LIBGPHOTO2_5_0 {
|
||||
gp_port_timeout_get;
|
||||
gp_port_timeout_set;
|
||||
gp_port_usb_clear_halt;
|
||||
gp_port_usb_set_sys_device;
|
||||
gp_port_usb_get_sys_device;
|
||||
gp_port_usb_find_device;
|
||||
gp_port_usb_find_device_by_class;
|
||||
gp_port_usb_msg_class_read;
|
||||
|
||||
@@ -116,6 +116,33 @@ struct _PrivateIrqCompleted {
|
||||
/* FIXME: safe size? */
|
||||
#define INTERRUPT_BUFFER_SIZE 256
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
static struct _GPPortExternalSysDevice {
|
||||
/* some more may be used in future */
|
||||
libusb_device_handle *h;
|
||||
libusb_device *d;
|
||||
libusb_context *ctx;
|
||||
libusb_device *dl[1];
|
||||
} external_sys_device = { NULL, NULL, NULL, { NULL } };
|
||||
|
||||
static int has_external_fd()
|
||||
{
|
||||
if(gp_port_usb_get_sys_device() == -1)
|
||||
return 0;
|
||||
if(external_sys_device.h)
|
||||
return 1;
|
||||
libusb_set_option(NULL,LIBUSB_OPTION_NO_DEVICE_DISCOVERY,NULL);
|
||||
C_LIBUSB (libusb_init (&external_sys_device.ctx), GP_ERROR_IO);
|
||||
LOG_ON_LIBUSB_E(libusb_wrap_sys_device(external_sys_device.ctx,gp_port_usb_get_sys_device(),&external_sys_device.h));
|
||||
external_sys_device.d = libusb_get_device(external_sys_device.h);
|
||||
external_sys_device.dl[0] = external_sys_device.d;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct _GPPortPrivateLibrary {
|
||||
libusb_context *ctx;
|
||||
libusb_device *d;
|
||||
@@ -155,6 +182,10 @@ load_devicelist (GPPortPrivateLibrary *pl) {
|
||||
time_t xtime;
|
||||
|
||||
time(&xtime);
|
||||
#if HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(!has_external_fd()) /* when external device present no need to research for Android */
|
||||
#endif
|
||||
{
|
||||
if (xtime != pl->devslastchecked) {
|
||||
if (pl->nrofdevs)
|
||||
libusb_free_device_list (pl->devs, 1);
|
||||
@@ -163,6 +194,16 @@ load_devicelist (GPPortPrivateLibrary *pl) {
|
||||
pl->devs = NULL;
|
||||
pl->descs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(has_external_fd()) {
|
||||
pl->nrofdevs = 1;
|
||||
pl->devs = external_sys_device.dl;
|
||||
C_MEM (pl->descs = calloc (1, sizeof(pl->descs[0])));
|
||||
LOG_ON_LIBUSB_E (libusb_get_device_descriptor(pl->devs[0], &pl->descs[0]));
|
||||
}
|
||||
#endif
|
||||
if (!pl->nrofdevs) {
|
||||
int i;
|
||||
|
||||
@@ -186,7 +227,16 @@ gp_port_library_list (GPPortInfoList *list)
|
||||
int nrofdevs = 0;
|
||||
struct libusb_device_descriptor *descs;
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(has_external_fd()) {
|
||||
ctx = external_sys_device.ctx;
|
||||
}
|
||||
else {
|
||||
C_LIBUSB (libusb_init (&ctx), GP_ERROR_IO);
|
||||
}
|
||||
#else
|
||||
C_LIBUSB (libusb_init (&ctx), GP_ERROR_IO);
|
||||
#endif
|
||||
|
||||
/* TODO: make sure libusb_exit gets called in all error paths inside this function */
|
||||
|
||||
@@ -197,11 +247,20 @@ gp_port_library_list (GPPortInfoList *list)
|
||||
gp_port_info_set_path (info, "^usb:");
|
||||
gp_port_info_list_append (list, info); /* do not check return value, it might be -1 */
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(has_external_fd()) {
|
||||
nrofdevs = 1;
|
||||
devs = external_sys_device.dl;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
nrofdevs = libusb_get_device_list (ctx, &devs);
|
||||
if (!nrofdevs) {
|
||||
libusb_exit (ctx); /* should free all stuff above */
|
||||
goto nodevices;
|
||||
}
|
||||
}
|
||||
|
||||
C_MEM (descs = calloc (nrofdevs, sizeof(descs[0])));
|
||||
for (i=0;i<nrofdevs;i++)
|
||||
@@ -309,8 +368,13 @@ gp_port_library_list (GPPortInfoList *list)
|
||||
C_GP (gp_port_info_list_append (list, info));
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(!has_external_fd())
|
||||
#endif
|
||||
{
|
||||
libusb_free_device_list (devs, 1);
|
||||
libusb_exit (ctx); /* should free all stuff above */
|
||||
}
|
||||
free (descs);
|
||||
|
||||
nodevices:
|
||||
@@ -333,11 +397,19 @@ static int gp_libusb1_init (GPPort *port)
|
||||
|
||||
port->pl->config = port->pl->interface = port->pl->altsetting = -1;
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(has_external_fd()) {
|
||||
port->pl->ctx = external_sys_device.ctx;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (LOG_ON_LIBUSB_E (libusb_init (&port->pl->ctx))) {
|
||||
free (port->pl);
|
||||
port->pl = NULL;
|
||||
return GP_ERROR_IO;
|
||||
}
|
||||
}
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
unlink("usblog.raw");
|
||||
port->pl->logfd = open("usblog.raw",O_CREAT|O_WRONLY,0644);
|
||||
@@ -356,9 +428,20 @@ gp_libusb1_exit (GPPort *port)
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
if (port->pl->logfd >=0 ) close (port->pl->logfd);
|
||||
#endif
|
||||
if (port->pl->nrofdevs)
|
||||
if (port->pl->nrofdevs) {
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(!has_external_fd())
|
||||
#endif
|
||||
{
|
||||
libusb_free_device_list (port->pl->devs, 1);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(!has_external_fd())
|
||||
#endif
|
||||
{
|
||||
libusb_exit (port->pl->ctx);
|
||||
}
|
||||
free (port->pl);
|
||||
port->pl = NULL;
|
||||
}
|
||||
@@ -380,13 +463,27 @@ gp_libusb1_open (GPPort *port)
|
||||
C_PARAMS (port->pl->d);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(gp_port_usb_get_sys_device() != -1) {
|
||||
if(!external_sys_device.h) {
|
||||
LOG_ON_LIBUSB_E(libusb_wrap_sys_device(port->pl->ctx,gp_port_usb_get_sys_device(),&external_sys_device.h));
|
||||
libusb_ref_device(libusb_get_device(external_sys_device.h));
|
||||
}
|
||||
port->pl->dh = external_sys_device.h;
|
||||
port->pl->d = libusb_get_device(external_sys_device.h);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
C_LIBUSB (libusb_open (port->pl->d, &port->pl->dh), GP_ERROR_IO);
|
||||
}
|
||||
if (!port->pl->dh) {
|
||||
int saved_errno = errno;
|
||||
gp_port_set_error (port, _("Could not open USB device (%s)."),
|
||||
strerror(saved_errno));
|
||||
return GP_ERROR_IO;
|
||||
}
|
||||
|
||||
ret = libusb_kernel_driver_active (port->pl->dh, port->settings.usb.interface);
|
||||
|
||||
#if 0
|
||||
@@ -493,6 +590,9 @@ gp_libusb1_close (GPPort *port)
|
||||
|
||||
_close_async_interrupts(port);
|
||||
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
if(gp_port_usb_get_sys_device() == -1) {
|
||||
#endif
|
||||
if (libusb_release_interface (port->pl->dh,
|
||||
port->settings.usb.interface) < 0) {
|
||||
int saved_errno = errno;
|
||||
@@ -523,6 +623,9 @@ gp_libusb1_close (GPPort *port)
|
||||
}
|
||||
|
||||
libusb_close (port->pl->dh);
|
||||
#ifdef HAVE_LIBUSB_WRAP_SYS_DEVICE
|
||||
}
|
||||
#endif
|
||||
|
||||
struct _PrivateIrqCompleted *irq_iter;
|
||||
struct _PrivateIrqCompleted *irq_next;
|
||||
|
||||
Reference in New Issue
Block a user