MTP Responder Contribution

Hi, just inquiring if it is possible to use the second USB port on the Teensy 3.6 with MTP? If so, can you advise how to make it work?

Thanks in advance.
 
So with the MTP_Blinky.ino code running on a Teensy 3.6 is it supposed to show up on a Windows PC as a USB Drive or is there more to be done to make this happen?
 
Using MTP on Audio Adapter card slot

Hi,

Just discovered the MTP library and seems to be exactly what I need. But where can I change the settings in order to work with the SD slot of the Audio Adapter?

I saw a lot of flags in 'SdFatConfig.h' to change set custom SPI configuration (only for STM32 and AVR boards).

Since I use a Teensy 3.6, the same file enables SDIO and SDIOEX classes... where I have no clue, how to make it work on the audio adapter slot.

Can someone help me? Thanks, Sebastien

P.S. And if you ask why I don't simply use the built-in slot, it's for historical reasons: I started using the "upper" one, that was easier to handle. And now I mounted the Teensy+Adapter on a PCB and can't access the built-in slot anymore :(
 
@sschiesser

I think something key was written in the MTP library, but the library is relative simple to edit
guess you can probably modify somewhere in "https://github.com/yoonghm/MTP/blob/master/MTP.h"
like changing line 37 :
SdFatSdioEX SD;
to
SdFat SD;

Also I didn't find call of SD.begin(); in the library,
you probably will need to do SD.begin(yourCSpin); before calling MTP.loop();
not sure would it work
 
Yes it did! I thought I first need to set new #define to enable changes, but finally I just needed
Code:
SPI.setMOSI(myMOSIpin);
SPI.setSCK(mySCKpin);
in setup() and
Code:
SD.begin(myCSpin);
in loop().

Thanks, s
 
Good evening (@CET)

After successful test with the MTP_blinky, I tried to implement the library into my code and get an error I can't explain: when just adding
Code:
#include <MTP.h>
anywhere in my code (in main.ino, main.h or any other file), I always get the error " 'SdFat' does not name a type".

This error also happens when I remove <MTP.h> and write
Code:
#include <SdFat.h>
SdFat SD;

The libraries are correctly installed and the examples codes work... some idea?

Best,
Sébastien
 
For anyone having troubles getting the MTP code from yoonghm's repository to work, I've figured out what's going wrong with it.

The "MTP Disk (Experimental)" USB type choice creates three interfaces: CDC control, CDC data, and MTP. However, the configuration descriptor that is generated claims only two interfaces to exist, and the interface descriptors themselves have numbers 0, 1, and 0 respectively. Either the incorrect count, or the duplicate interface number, is enough to get Windows (7, at least) to completely reject the device - of course without giving any indication anywhere of exactly why the device is being rejected.

To fix, you need to edit the usb_desc.h file - the one you copied from the MTP library into your Teensyduino installation. Find the section that starts with:
Code:
  #elif defined(USB_MTPDISK)
Just under that, find:
Code:
  #define NUM_INTERFACE         2
and change the number to 3, then a few lines further down find:
Code:
  #define MTP_INTERFACE         0 // MTP Disk
and change the number to 2.
 
Ok, I spoke a bit too soon about that making the code work - it at least gets the device to appear, but pretty much nothing other than creating empty folders would actually work. There was a warning during compilation that I should have paid closer attention to:
Code:
C:\Program Files\Arduino\libraries\MTP/MTP.h: In member function 'virtual uint32_t MTPStorage_SD::Create(uint32_t, bool, const char*)':
C:\Program Files\Arduino\libraries\MTP/MTP.h:375:38: warning: large integer implicitly truncated to unsigned type [-Woverflow]
       OpenFileByIndex(ret, FILE_WRITE);
                                      ^
FILE_WRITE had a value of 0x4202, but that parameter (and everything else within the SDFat library that deals with file flags) is only a byte. Somehow the compiler was picking up a traditional Unix definition of the file opening flags (O_CREAT and all that) that has the bits scattered throughout an int, instead of the Arduino definition that squeezes them all into a byte. I traced this down to the file Arduino\libraries\SdFat\src\SdFatConfig.h:
Code:
/** If the symbol USE_FCNTL_H is nonzero, open flags for access modes O_RDONLY,
 * O_WRONLY, O_RDWR and the open modifiers O_APPEND, O_CREAT, O_EXCL, O_SYNC
 * will be defined by including the system file fcntl.h.
 */
#if defined(__AVR__)
// AVR fcntl.h does not define open flags.
#define USE_FCNTL_H 0
#elif defined(PLATFORM_ID)
// Particle boards - use fcntl.h.
#define USE_FCNTL_H 1
#elif defined(__arm__)
// ARM gcc defines open flags.
#define USE_FCNTL_H 1
#else  // defined(__AVR__)
#define USE_FCNTL_H 0
#endif  // defined(__AVR__)
I have absolutely no idea what the right solution is here, so I just added a couple of lines right after that to force the Arduino definitions:
Code:
#undef USE_FCNTL_H
#define USE_FCNTL_H 0
I haven't tested this very thoroughly yet, but at least I can copy a text file to the Teensy and read it back now.
 
This seems to be fixed differently in the most current Teensyduino usb_desc.h and works without this change (which actually will fail).

For anyone having troubles getting the MTP code from yoonghm's repository to work, I've figured out what's going wrong with it.

The "MTP Disk (Experimental)" USB type choice creates three interfaces: CDC control, CDC data, and MTP. However, the configuration descriptor that is generated claims only two interfaces to exist, and the interface descriptors themselves have numbers 0, 1, and 0 respectively. Either the incorrect count, or the duplicate interface number, is enough to get Windows (7, at least) to completely reject the device - of course without giving any indication anywhere of exactly why the device is being rejected.

To fix, you need to edit the usb_desc.h file - the one you copied from the MTP library into your Teensyduino installation. Find the section that starts with:
Code:
  #elif defined(USB_MTPDISK)
Just under that, find:
Code:
  #define NUM_INTERFACE         2
and change the number to 3, then a few lines further down find:
Code:
  #define MTP_INTERFACE         0 // MTP Disk
and change the number to 2.
 
Has anyone gotten this to work with Linux (either mtpfs or go-mtpfs). I can get it to work with Windows 7, but there is something mtpfs on Linux does not like about it, and it fails to mount the device with no useful error messages other than "Transport endpoint is not connected". go-mtpfs fails with "selectStorages failed: header specified 0x0 bytes, but have 0x4".

When mtpfs starts up it says..

Listing raw device(s)
Device 0 (VID=16c0 and PID=04d1) is UNKNOWN in libmtp v1.1.10.
Please report this VID/PID and the device model to the libmtp development team
Found 1 device(s):
16c0:04d1 @ bus 3, dev 90
Attempting to connect device
Listing File Information on Device with name: Teensy
 
I have been able to make some progress. mtp tools on Linux seem to mostly work, mtp-files lists the files ok, and mtp-sendfile writes files ok, however mtp-getfile fails with an I/O error. Also jmtpfs does seem to be able to mount the device, and list files, but again gets an I/O error when trying to read a file.

NODEID: 7
unique: 39, success, outsize: 144
unique: 40, opcode: OPEN (14), nodeid: 7, insize: 48, pid: 27177
open flags: 0x8000 /SD Card/test-fixed-point.rb
unique: 40, error: -5 (Input/output error), outsize: 16
 
Seems there is a bug in the TRANSMIT(GetObject(CONTAINER->params[0])); routines.
It seems that at the end of a file that is not on a buffer size boundary it sends too much data back,
causing the Linux driver to throw an error. I suspect that the Windows driver ignores this error and truncates.
Having looked at the code it is quite complex but does appear to have a bug when sending a partial buffer at the end of a file.
Normally I would debug with JLink and GDB :) unfortunately that seems it would require some very fine hacking/soldering.
So I am just going to have to stare at the code as you can't do prints within an interrupt I suspect.

0.388959 gp_port_read (3): Reading 18 = 0x12 bytes from port...
0.389175 gp_libusb1_read [libusb1.c:577](0): 'libusb_bulk_transfer (port->pl->dh, port->settings.usb.inep, (unsigned char*)bytes, size, &curread, port->timeout)' failed: Overflow (-8)
0.389207 gp_port_read [gphoto2-port.c:437](0): Reading 18 = 0x12 bytes from port failed: Error reading from the port (-34)
 
Ahh found the bug line 62 in MTP.h

uint32_t to_copy = min(pos - size, avail);
should be
uint32_t to_copy = min(size - pos, avail);

Now it works with Linux. Makes you wonder why the Windows MTP drivers worked at all ;)

I'll submit a push request
 
I have submitted a PR to the MTP github to fix this properly.
The issue is actually in MTP.h OpenFileByIndex which should use oflag_t rather than a byte.

Ok, I spoke a bit too soon about that making the code work - it at least gets the device to appear, but pretty much nothing other than creating empty folders would actually work. There was a warning during compilation that I should have paid closer attention to:
Code:
C:\Program Files\Arduino\libraries\MTP/MTP.h: In member function 'virtual uint32_t MTPStorage_SD::Create(uint32_t, bool, const char*)':
C:\Program Files\Arduino\libraries\MTP/MTP.h:375:38: warning: large integer implicitly truncated to unsigned type [-Woverflow]
       OpenFileByIndex(ret, FILE_WRITE);
                                      ^
FILE_WRITE had a value of 0x4202, but that parameter (and everything else within the SDFat library that deals with file flags) is only a byte. Somehow the compiler was picking up a traditional Unix definition of the file opening flags (O_CREAT and all that) that has the bits scattered throughout an int, instead of the Arduino definition that squeezes them all into a byte. I traced this down to the file Arduino\libraries\SdFat\src\SdFatConfig.h:
Code:
/** If the symbol USE_FCNTL_H is nonzero, open flags for access modes O_RDONLY,
 * O_WRONLY, O_RDWR and the open modifiers O_APPEND, O_CREAT, O_EXCL, O_SYNC
 * will be defined by including the system file fcntl.h.
 */
#if defined(__AVR__)
// AVR fcntl.h does not define open flags.
#define USE_FCNTL_H 0
#elif defined(PLATFORM_ID)
// Particle boards - use fcntl.h.
#define USE_FCNTL_H 1
#elif defined(__arm__)
// ARM gcc defines open flags.
#define USE_FCNTL_H 1
#else  // defined(__AVR__)
#define USE_FCNTL_H 0
#endif  // defined(__AVR__)
I have absolutely no idea what the right solution is here, so I just added a couple of lines right after that to force the Arduino definitions:
Code:
#undef USE_FCNTL_H
#define USE_FCNTL_H 0
I haven't tested this very thoroughly yet, but at least I can copy a text file to the Teensy and read it back now.
 
Hi guys, first of all thank you so much for all the work you've done!
I'm trying the MTP on my Teensy 3.6 and it seems to works fine! woooowowoowo!!! :)
Should it works also on my MAC?

On my Teensy I use the Serial to show and interact with an applciation menu.... I'm using Putty connection over serial communication but after adding the MTP on my code I can see the storage on Windows file explorer but no COM is associated to the Teensy. Is it possible to both use MTP and COM communication with Putty or using MTP I'll not able to use my menu?
it would be also fine if I can enable MTP via menu or jumper only when I need to access the SD...
 
Hi all,
I'm trying to write a file in the SD using MTP with no luck... :(
I can access the SD on Windows Explorer and I can read and remove files but if I copy a new file in the SD it results in 0 bytes file.
I also tried with MTP_blinky.ino example and it seems doesn't work too.


Can you please help me?
 
No I haven’t apply any modifications... I just download the last version of the lib and installed from zip file.
I was supposed that it contains all the fixes.

You think that could be the root cause of my issue?
What exactly have I to do to apply the fix?


Thanks!
 
Back
Top