introduce device capabilities in --list-devices

This is preparation for direct object modification.
This commit is contained in:
Peter Hatina 2014-11-12 09:29:34 +01:00
parent 7a5f10fe54
commit a00250fda6
5 changed files with 151 additions and 50 deletions

View File

@ -14,6 +14,9 @@ AC_PROG_INSTALL
m4_include([m4/cxx11.m4])
AX_CXX_COMPILE_STDCXX_11([noext])
AC_CHECK_LIB([mtp], [LIBMTP_Init], [], [AC_MSG_ERROR([libmtp not found])])
AC_CHECK_LIB([mtp], [LIBMTP_Check_Capability],
[AC_DEFINE([HAVE_LIBMTP_CHECK_CAPABILITY], [1], [Check device capabilities])],
[])
AC_CHECK_HEADERS([libmtp.h])
dnl Enable fdatasync, but not on OSX

View File

@ -364,6 +364,11 @@ void SMTPFileSystem::printVersion() const
fuse_opt_free_args(&args);
}
bool SMTPFileSystem::listDevices() const
{
return MTPDevice::listDevices(m_options.m_verbose);
}
bool SMTPFileSystem::exec()
{
if (!m_options.m_good)

View File

@ -34,12 +34,6 @@ class SMTPFileSystem
private:
struct SMTPFileSystemOptions {
public:
enum { KEY_VERSION,
KEY_HELP,
KEY_LIST_DEVICES,
KEY_DEVICE,
KEY_ENABLE_MOVE};
int m_good;
int m_help;
int m_version;
@ -78,7 +72,7 @@ public:
bool parseOptions(int argc, char **argv);
void printHelp() const;
void printVersion() const;
bool listDevices() { return m_device.listDevices(); }
bool listDevices() const;
bool exec();
bool isGood() const { return m_options.m_good; }

View File

@ -37,6 +37,7 @@ uint32_t MTPDevice::s_root_node = ~0;
MTPDevice::MTPDevice():
m_device(nullptr),
m_capabilities(),
m_device_mutex(),
m_root_dir(),
m_move_enabled(false)
@ -51,6 +52,33 @@ MTPDevice::~MTPDevice()
disconnect();
}
bool MTPDevice::connect(LIBMTP_raw_device_t *dev)
{
if (m_device) {
logerr("Already connected.\n");
return true;
}
// Do not output LIBMTP debug stuff
StreamHelper::off();
m_device = LIBMTP_Open_Raw_Device_Uncached(dev);
StreamHelper::on();
if (!m_device) {
LIBMTP_Dump_Errorstack(m_device);
return false;
}
if (!enumStorages())
return false;
// Retrieve capabilities.
m_capabilities = MTPDevice::getCapabilities(*this);
logmsg("Connected.\n");
return true;
}
bool MTPDevice::connect(int dev_no)
{
if (m_device) {
@ -119,6 +147,9 @@ bool MTPDevice::connect(int dev_no)
if (!enumStorages())
return false;
// Retrieve capabilities.
m_capabilities = MTPDevice::getCapabilities(*this);
logmsg("Connected.\n");
return true;
}
@ -144,22 +175,12 @@ bool MTPDevice::connect(const std::string &dev_file)
smtpfs_reset_device(raw_device);
#endif // HAVE_LIBUSB1
// Do not output LIBMTP debug stuff
StreamHelper::off();
m_device = LIBMTP_Open_Raw_Device_Uncached(raw_device);
StreamHelper::on();
bool rval = connect(raw_device);
// TODO: Smart pointer with alloc, free hooks.
smtpfs_raw_device_free(raw_device);
if (!m_device) {
LIBMTP_Dump_Errorstack(m_device);
return false;
}
if (!enumStorages())
return false;
logmsg("Connected.\n");
return true;
return rval;
}
#endif
@ -173,34 +194,6 @@ void MTPDevice::disconnect()
logmsg("Disconnected.\n");
}
bool MTPDevice::listDevices()
{
int raw_devices_cnt;
LIBMTP_raw_device_t *raw_devices;
// Do not output LIBMTP debug stuff
StreamHelper::off();
LIBMTP_error_number_t err = LIBMTP_Detect_Raw_Devices(
&raw_devices, &raw_devices_cnt);
StreamHelper::on();
if (err != 0) {
if (err == LIBMTP_ERROR_NO_DEVICE_ATTACHED)
std::cerr << "No raw devices found.\n";
return false;
}
for (int i = 0; i < raw_devices_cnt; ++i) {
std::cout << i + 1 << ": "
<< (raw_devices[i].device_entry.vendor ? raw_devices[i].device_entry.vendor : "Unknown vendor ")
<< (raw_devices[i].device_entry.product ? raw_devices[i].device_entry.product : "Unknown product")
<< "\n";
}
free(static_cast<void*>(raw_devices));
return true;
}
uint64_t MTPDevice::storageTotalSize() const
{
uint64_t total = 0;
@ -591,3 +584,76 @@ int MTPDevice::fileRename(const std::string &oldpath, const std::string &newpath
logmsg("File '", oldpath, "' renamed to '", tmp_new_basename, "'.\n");
return 0;
}
MTPDevice::Capabilities MTPDevice::getCapabilities() const
{
return m_capabilities;
}
MTPDevice::Capabilities MTPDevice::getCapabilities(const MTPDevice &device)
{
MTPDevice::Capabilities capabilities;
#ifdef HAVE_LIBMTP_CHECK_CAPABILITY
if (device.m_device) {
capabilities.setCanGetPartialObject(
static_cast<bool>(
LIBMTP_Check_Capability(
device.m_device,
LIBMTP_DEVICECAP_GetPartialObject)));
capabilities.setCanSendPartialobject(
static_cast<bool>(
LIBMTP_Check_Capability(
device.m_device,
LIBMTP_DEVICECAP_SendPartialObject)));
capabilities.setCanEditObjects(
static_cast<bool>(
LIBMTP_Check_Capability(
device.m_device,
LIBMTP_DEVICECAP_EditObjects)));
}
#endif
return capabilities;
}
bool MTPDevice::listDevices(bool verbose)
{
int raw_devices_cnt;
LIBMTP_raw_device_t *raw_devices;
// Do not output LIBMTP debug stuff
StreamHelper::off();
LIBMTP_error_number_t err = LIBMTP_Detect_Raw_Devices(
&raw_devices, &raw_devices_cnt);
StreamHelper::on();
if (err != 0) {
if (err == LIBMTP_ERROR_NO_DEVICE_ATTACHED)
std::cerr << "No raw devices found.\n";
return false;
}
for (int i = 0; i < raw_devices_cnt; ++i) {
std::cout << i + 1 << ": "
<< (raw_devices[i].device_entry.vendor ? raw_devices[i].device_entry.vendor : "Unknown vendor ")
<< (raw_devices[i].device_entry.product ? raw_devices[i].device_entry.product : "Unknown product")
<< std::endl;
#ifdef HAVE_LIBMTP_CHECK_CAPABILITY
MTPDevice dev;
if (verbose) {
if (!dev.connect(&raw_devices[i]))
return false;
const MTPDevice::Capabilities &cap = dev.getCapabilities();
std::cout << " - can get partial object: " << (cap.canGetPartialObject() ? "yes" : "no") << std::endl;
std::cout << " - can send partial object: " << (cap.canSendPartialObject() ? "yes" : "no") << std::endl;
std::cout << " - can edit objects : " << (cap.canEditObjects() ? "yes" : "no") << std::endl;
dev.disconnect();
}
#endif
}
free(static_cast<void*>(raw_devices));
return true;
}

View File

@ -32,14 +32,40 @@ extern "C" {
class MTPDevice
{
public:
class Capabilities
{
public:
Capabilities()
: m_get_partial_object(false)
, m_send_partial_object(false)
, m_edit_objects(false)
{
}
void setCanGetPartialObject(bool b) { m_get_partial_object = b; }
void setCanSendPartialobject(bool b) { m_send_partial_object = b; }
void setCanEditObjects(bool b) { m_edit_objects = b; }
bool canGetPartialObject() const { return m_get_partial_object; }
bool canSendPartialObject() const { return m_send_partial_object; }
bool canEditObjects() const { return m_edit_objects; }
private:
bool m_get_partial_object;
bool m_send_partial_object;
bool m_edit_objects;
};
// -------------------------------------------------------------------------
MTPDevice();
~MTPDevice();
bool connect(LIBMTP_raw_device_t *dev);
bool connect(int dev_no = 0);
bool connect(const std::string &dev_file);
void disconnect();
bool listDevices();
void enableMove(bool e = true) { m_move_enabled = e; }
uint64_t storageTotalSize() const;
@ -57,14 +83,21 @@ public:
int fileRemove(const std::string &path);
int fileRename(const std::string &oldpath, const std::string &newpath);
Capabilities getCapabilities() const;
static bool listDevices(bool verbose = false);
private:
void criticalEnter() { m_device_mutex.lock(); }
void criticalLeave() { m_device_mutex.unlock(); }
bool enumStorages();
static Capabilities getCapabilities(const MTPDevice &device);
private:
LIBMTP_mtpdevice_t *m_device;
Capabilities m_capabilities;
std::mutex m_device_mutex;
TypeDir m_root_dir;
bool m_move_enabled;