Skip to content

Commit

Permalink
Merge pull request #58 from amtep/master
Browse files Browse the repository at this point in the history
Fix MTP compatibility with some android kernels
  • Loading branch information
amtep committed May 7, 2015
2 parents ce813b5 + cb6fa70 commit 0452b9f
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 23 deletions.
8 changes: 8 additions & 0 deletions mts/transport/usb/descriptor.c
Expand Up @@ -94,3 +94,11 @@ const struct mtp1strings_s mtp1strings = {
MTP_STRING_DESCRIPTOR,
},
};

const struct usb_functionfs_descs_head_incompatible mtp1descriptors_header_incompatible = {
.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
.length = cpu_to_le32(sizeof(struct mtp1_descriptors_s_incompatible)),
.fs_count = 4,
.hs_count = 4,
.ss_count = 0
};
34 changes: 28 additions & 6 deletions mts/transport/usb/mtp1descriptors.h
Expand Up @@ -17,14 +17,17 @@ static const char* in_file = "/dev/mtp/ep1";
static const char* out_file = "/dev/mtp/ep2";
static const char* interrupt_file = "/dev/mtp/ep3";

struct mtp1_descs_s {
struct usb_interface_descriptor intf;
struct usb_endpoint_descriptor_no_audio mtp_ep_in;
struct usb_endpoint_descriptor_no_audio mtp_ep_out;
struct usb_endpoint_descriptor_no_audio mtp_ep_int;
} __attribute__((packed));

struct mtp1_descriptors_s {
struct usb_functionfs_descs_head header;
struct {
struct usb_interface_descriptor intf;
struct usb_endpoint_descriptor_no_audio mtp_ep_in;
struct usb_endpoint_descriptor_no_audio mtp_ep_out;
struct usb_endpoint_descriptor_no_audio mtp_ep_int;
} __attribute__((packed)) fs_descs, hs_descs;
struct mtp1_descs_s fs_descs;
struct mtp1_descs_s hs_descs;
} __attribute__((packed));

extern const struct mtp1_descriptors_s mtp1descriptors;
Expand All @@ -39,4 +42,23 @@ struct mtp1strings_s {

extern const struct mtp1strings_s mtp1strings;


struct usb_functionfs_descs_head_incompatible {
__le32 magic;
__le32 length;
__le32 fs_count;
__le32 hs_count;
// The following field is added to the header in some
// android kernels, which breaks compatibility.
__le32 ss_count;
} __attribute__((packed));

struct mtp1_descriptors_s_incompatible {
struct usb_functionfs_descs_head_incompatible header;
struct mtp1_descs_s fs_descs;
struct mtp1_descs_s hs_descs;
} __attribute__((packed));

extern const struct usb_functionfs_descs_head_incompatible mtp1descriptors_header_incompatible;

#endif
54 changes: 37 additions & 17 deletions mts/transport/usb/mtptransporterusb.cpp
Expand Up @@ -32,6 +32,7 @@
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
Expand Down Expand Up @@ -72,6 +73,39 @@ MTPTransporterUSB::MTPTransporterUSB() : m_ioState(SUSPENDED), m_containerReadLe
this, SLOT(handleDataReady()), Qt::QueuedConnection);
}

bool MTPTransporterUSB::writeMtpDescriptors()
{
if (write(m_ctrlFd, &mtp1descriptors, sizeof mtp1descriptors) >= 0)
return true;

if (errno == EINVAL) {
MTP_LOG_WARNING("Kernel did not accept endpoint descriptors;"
" trying 'ss_count' workaround");
// Some android kernels changed the usb_functionfs_descs_head size
// by adding an ss_count member. Try it that way.
mtp1_descriptors_s_incompatible descs;
descs.header = mtp1descriptors_header_incompatible;
descs.fs_descs = mtp1descriptors.fs_descs;
descs.hs_descs = mtp1descriptors.hs_descs;
if (write(m_ctrlFd, &descs, sizeof descs) >= 0)
return true;
}

MTP_LOG_CRITICAL("Couldn't write descriptors to control endpoint file"
<< control_file);
return false;
}

bool MTPTransporterUSB::writeMtpStrings()
{
if (write(m_ctrlFd, &mtp1strings, sizeof(mtp1strings)) >= 0)
return true;

MTP_LOG_CRITICAL("Couldn't write strings to control endpoint file"
<< control_file);
return false;
}

bool MTPTransporterUSB::activate()
{
MTP_LOG_CRITICAL("MTPTransporterUSB::activate");
Expand All @@ -84,23 +118,9 @@ bool MTPTransporterUSB::activate()
}
else
{
if(-1 == write(m_ctrlFd, &mtp1descriptors, sizeof mtp1descriptors))
{
MTP_LOG_CRITICAL("Couldn't write descriptors to control endpoint file "
<< control_file);
}
else
{
if(-1 == write(m_ctrlFd, &mtp1strings, sizeof(mtp1strings)))
{
MTP_LOG_CRITICAL("Couldn't write strings to control endpoint file "
<< control_file);
}
else
{
success = true;
MTP_LOG_INFO("mtp function set up");
}
if (writeMtpDescriptors() && writeMtpStrings()) {
success = true;
MTP_LOG_INFO("mtp function set up");
}
}

Expand Down
2 changes: 2 additions & 0 deletions mts/transport/usb/mtptransporterusb.h
Expand Up @@ -93,6 +93,8 @@ class MTPTransporterUSB : public MTPTransporter

private:
void processReceivedData(); // Helper function for handleDataReady()
bool writeMtpDescriptors(); // configure the USB endpoints for functionfs
bool writeMtpStrings(); // step 2 of functionfs configuration

enum IOState{
ACTIVE,
Expand Down

0 comments on commit 0452b9f

Please sign in to comment.