PB.Ex MTP (Windows)

Applications, Games, Tools, User libs and useful stuff coded in PureBasic
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

PB.Ex MTP (Windows)

Post by RSBasic »

Hello

With this library you can access smartpones, tablets, cameras and other mobile devices that support the MTP (Media Transfer Protocol) protocol and read device information (device ID, device name, firmware version, manufacturer, serial number, ...) and the directories and files on the device and copy them to the PC.
I tested it with my iPhone and with my Canon digital camera.

Functions:
  • ExamineMTP()
    • Syntax:

      Code: Select all

      Result = ExamineMTP(@ErrorOutput$)
    • Description: Starts the list of all devices. This could be smartphones, tablets, cameras, mass storage and other mobile devices.
    • Parameter:
      1. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    NextMTPEntry()
    • Syntax:

      Code: Select all

      Result = NextMTPEntry(@ErrorOutput$)
    • Description: The next device is determined. This function is only valid within the ExamineMTP loop.
    • Parameter:
      1. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    FinishMTP()
    • Syntax:

      Code: Select all

      Result = FinishMTP(@ErrorOutput$)
    • Description: Closes the list of devices. This function is only valid within the ExamineMTP loop.
    • Parameter:
      1. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    MTPEntryName()
    • Syntax:

      Code: Select all

      Result = MTPEntryName(@Output$, @ErrorOutput$)
    • Description: Determines the name of the current device. This function is only valid within the ExamineMTP loop.
    • Parameter:
      1. @Output$: The device name is stored in this variable. With this name it is possible to access this device with OpenMTP() to read device information and copy files.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    OpenMTP()
    • Syntax:

      Code: Select all

      Result = OpenMTP(ID, DeviceName$, @ErrorOutput$)
    • Description: Connects to the specified device to read device information and copy files.
    • Parameter:
      1. ID: A unique number. #PB_Any can be used to generate the number automatically.
      2. DeviceName$: The name of the device. The device name can be determined with ExamineMTP().
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful. If #PB_Any is used, the ID is returned.
    • Example:

      Code: Select all

      EnableExplicit
      
      Global PBEx_MTP
      
      #PBEx_MTP_Type_File = 1
      #PBEx_MTP_Type_Directory = 2
      #PBEx_MTP_DeviceType_Generic = 0
      #PBEx_MTP_DeviceType_Camera = 1
      #PBEx_MTP_DeviceType_MediaPlayer = 2
      #PBEx_MTP_DeviceType_Phone = 3
      #PBEx_MTP_DeviceType_Video = 4
      #PBEx_MTP_DeviceType_PersonalInformationManager = 5
      #PBEx_MTP_DeviceType_AudioRecorder = 6
      
      CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
        PBEx_MTP = OpenLibrary(#PB_Any, "PB.Ex_MTP_x86.dll")
      CompilerElseIf #PB_Compiler_Processor = #PB_Processor_x64
        PBEx_MTP = OpenLibrary(#PB_Any, "PB.Ex_MTP_x64.dll")
      CompilerEndIf
      
      If PBEx_MTP
        Prototype ExamineMTP(ErrorOutput)
        Global ExamineMTP.ExamineMTP = GetFunction(PBEx_MTP, "ExamineMTP")
        Prototype NextMTPEntry(ErrorOutput)
        Global NextMTPEntry.NextMTPEntry = GetFunction(PBEx_MTP, "NextMTPEntry")
        Prototype FinishMTP(ErrorOutput)
        Global FinishMTP.FinishMTP = GetFunction(PBEx_MTP, "FinishMTP")
        Prototype MTPEntryName(Output, ErrorOutput)
        Global MTPEntryName.MTPEntryName = GetFunction(PBEx_MTP, "MTPEntryName")
        Prototype OpenMTP(ID, DeviceName.p-Unicode, ErrorOutput)
        Global OpenMTP.OpenMTP = GetFunction(PBEx_MTP, "OpenMTP")
        Prototype CloseMTP(ID, ErrorOutput)
        Global CloseMTP.CloseMTP = GetFunction(PBEx_MTP, "CloseMTP")
        Prototype IsMTP(ID, ErrorOutput)
        Global IsMTP.IsMTP = GetFunction(PBEx_MTP, "IsMTP")
        Prototype ExamineMTPDirectory(ID, ErrorOutput)
        Global ExamineMTPDirectory.ExamineMTPDirectory = GetFunction(PBEx_MTP, "ExamineMTPDirectory")
        Prototype FinishMTPDirectory(ID, ErrorOutput)
        Global FinishMTPDirectory.FinishMTPDirectory = GetFunction(PBEx_MTP, "FinishMTPDirectory")
        Prototype NextMTPDirectoryEntry(ID, ErrorOutput)
        Global NextMTPDirectoryEntry.NextMTPDirectoryEntry = GetFunction(PBEx_MTP, "NextMTPDirectoryEntry")
        Prototype MTPDirectoryEntryName(ID, Output, ErrorOutput)
        Global MTPDirectoryEntryName.MTPDirectoryEntryName = GetFunction(PBEx_MTP, "MTPDirectoryEntryName")
        Prototype SetMTPDirectory(ID, DirectoryPath.p-Unicode, ErrorOutput)
        Global SetMTPDirectory.SetMTPDirectory = GetFunction(PBEx_MTP, "SetMTPDirectory")
        Prototype GetMTPDirectory(ID, Output, ErrorOutput)
        Global GetMTPDirectory.GetMTPDirectory = GetFunction(PBEx_MTP, "GetMTPDirectory")
        Prototype MTPDirectoryEntryType(ID, ErrorOutput)
        Global MTPDirectoryEntryType.MTPDirectoryEntryType = GetFunction(PBEx_MTP, "MTPDirectoryEntryType")
        Prototype ReceiveMTPFile(ID, RemoteFileName.p-Unicode, FileName.p-Unicode, ErrorOutput)
        Global ReceiveMTPFile.ReceiveMTPFile = GetFunction(PBEx_MTP, "ReceiveMTPFile")
        Prototype MTPDirectoryEntrySize(ID, ErrorOutput)
        Global MTPDirectoryEntrySize.MTPDirectoryEntrySize = GetFunction(PBEx_MTP, "MTPDirectoryEntrySize")
        Prototype MTPDirectoryEntryDate(ID, ErrorOutput)
        Global MTPDirectoryEntryDate.MTPDirectoryEntryDate = GetFunction(PBEx_MTP, "MTPDirectoryEntryDate")
        Prototype GetMTPDescription(ID, Output, ErrorOutput)
        Global GetMTPDescription.GetMTPDescription = GetFunction(PBEx_MTP, "GetMTPDescription")
        Prototype GetMTPDeviceID(ID, Output, ErrorOutput)
        Global GetMTPDeviceID.GetMTPDeviceID = GetFunction(PBEx_MTP, "GetMTPDeviceID")
        Prototype GetMTPDeviceType(ID, ErrorOutput)
        Global GetMTPDeviceType.GetMTPDeviceType = GetFunction(PBEx_MTP, "GetMTPDeviceType")
        Prototype GetMTPFirmwareVersion(ID, Output, ErrorOutput)
        Global GetMTPFirmwareVersion.GetMTPFirmwareVersion = GetFunction(PBEx_MTP, "GetMTPFirmwareVersion")
        Prototype GetMTPFriendlyName(ID, Output, ErrorOutput)
        Global GetMTPFriendlyName.GetMTPFriendlyName = GetFunction(PBEx_MTP, "GetMTPFriendlyName")
        Prototype GetMTPManufacturer(ID, Output, ErrorOutput)
        Global GetMTPManufacturer.GetMTPManufacturer = GetFunction(PBEx_MTP, "GetMTPManufacturer")
        Prototype GetMTPModel(ID, Output, ErrorOutput)
        Global GetMTPModel.GetMTPModel = GetFunction(PBEx_MTP, "GetMTPModel")
        Prototype GetMTPPnPDeviceID(ID, Output, ErrorOutput)
        Global GetMTPPnPDeviceID.GetMTPPnPDeviceID = GetFunction(PBEx_MTP, "GetMTPPnPDeviceID")
        Prototype GetMTPSerialNumber(ID, Output, ErrorOutput)
        Global GetMTPSerialNumber.GetMTPSerialNumber = GetFunction(PBEx_MTP, "GetMTPSerialNumber")
        
      EndIf
      
      Global Output$ = Space(1024)
      Global ErrorOutput$ = Space(128)
      
      ;List all devices to determine the device name.
      ; If ExamineMTP(@ErrorOutput$)
      ;   While NextMTPEntry(@ErrorOutput$)
      ;     MTPEntryName(@Output$, @ErrorOutput$)
      ;     Debug Output$
      ;   Wend
      ; EndIf
      
      ;List all directories and files.
      ;If OpenMTP(1, "Canon IXUS 125 HS", @ErrorOutput$)
      If OpenMTP(1, "Apple iPhone", @ErrorOutput$)
        
        ;Get device information
        GetMTPFriendlyName(1, @Output$, @ErrorOutput$)
        Debug "Friendly name: " + Output$
        GetMTPManufacturer(1, @Output$, @ErrorOutput$)
        Debug "Manufacturer: " + Output$
        GetMTPFirmwareVersion(1, @Output$, @ErrorOutput$)
        Debug "Firmware version: " + Output$
        GetMTPPnPDeviceID(1, @Output$, @ErrorOutput$)
        Debug "PnPDeviceID: " + Output$
        
        Debug "--------------------------------------------------"
        
        ;SetMTPDirectory(1, "\Internal Storage\DCIM\100APPLE", @ErrorOutput$)
        If ExamineMTPDirectory(1, @ErrorOutput$)
          While NextMTPDirectoryEntry(1, @ErrorOutput$)
            MTPDirectoryEntryName(1, @Output$, @ErrorOutput$)
            If MTPDirectoryEntryType(1, @ErrorOutput$) = #PBEx_MTP_Type_Directory
              Debug "Folder: " + Output$
            ElseIf  MTPDirectoryEntryType(1, @ErrorOutput$) = #PBEx_MTP_Type_File
              Debug "File: " + Output$
              Debug Str(MTPDirectoryEntrySize(1, @ErrorOutput$)) + " Bytes"
              Debug FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", MTPDirectoryEntryDate(1, @ErrorOutput$))
              
            EndIf
            
          Wend
        EndIf
        
        CloseMTP(1, @ErrorOutput$)
      Else
        Debug ErrorOutput$
      EndIf
      
      CloseLibrary(PBEx_MTP)
      
    CloseMTP()
    • Syntax:

      Code: Select all

      Result = CloseMTP(ID, @ErrorOutput$)
    • Description: Closes the connection to the device.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    IsMTP()
    • Syntax:

      Code: Select all

      Result = IsMTP(ID, @ErrorOutput$)
    • Description: Checks if the connection is still valid.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: ID is valid.
    ExamineMTPDirectory()
    • Syntax:

      Code: Select all

      Result = ExamineMTPDirectory(ID, @ErrorOutput$)
    • Description: Starts the listing of all directories and files.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    FinishMTPDirectory()
    • Syntax:

      Code: Select all

      Result = FinishMTPDirectory(ID, @ErrorOutput$)
    • Description: Closes the list of directories and files. This function is only valid within the ExamineMTPDirectory loop.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    NextMTPDirectoryEntry()
    • Syntax:

      Code: Select all

      Result = NextMTPDirectoryEntry(ID, @ErrorOutput$)
    • Description: The next directory or file is determined. This function is only valid within the ExamineMTPDirectory loop.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    MTPDirectoryEntryName()
    • Syntax:

      Code: Select all

      Result = MTPDirectoryEntryName(ID, @Output$, @ErrorOutput$)
    • Description: The name of the directory or file is determined. This function is only valid within the ExamineMTPDirectory loop.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The name of the directory or file is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    SetMTPDirectory()
    • Syntax:

      Code: Select all

      Result = SetMTPDirectory(ID, DirectoryPath$, @ErrorOutput$)
    • Description: Changes the current directory using the path. If empty, the root directory is selected.
    • Parameter:
      1. ID: The number connection.
      2. DirectoryPath$: Path to the directory.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPDirectory()
    • Syntax:

      Code: Select all

      Result = GetMTPDirectory(ID, @Output$, @ErrorOutput$)
    • Description: Determines the current directory.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The path of the current directory is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    MTPDirectoryEntryType()
    • Syntax:

      Code: Select all

      Result = MTPDirectoryEntryType(ID, @ErrorOutput$)
    • Description: Determines the type of the current entry. This function is only valid within the ExamineMTPDirectory loop.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value: The following constants can be queried:
      • #PBEx_MTP_Type_File: The entry is a file.
      • #PBEx_MTP_Type_Directory: The entry is a directory.
    ReceiveMTPFile()
    • Syntax:

      Code: Select all

      Result = ReceiveMTPFile(ID, RemoteFileName$, FileName$, @ErrorOutput$)
    • Description: Copies the specified file to the hard disk using the path.
    • Parameter:
      1. ID: The number connection.
      2. RemoteFileName$: Complete path including file name of the file to be copied.
      3. FileName$: Complete target path incl. file name where the file should be copied to.
      4. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    MTPDirectoryEntrySize()
    • Syntax:

      Code: Select all

      Result = MTPDirectoryEntrySize(ID, @ErrorOutput$)
    • Description: Determines the file size. This function is only valid within the ExamineMTPDirectory loop.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value: The size of the file in bytes.
    MTPDirectoryEntryDate()
    • Syntax:

      Code: Select all

      Result = MTPDirectoryEntryDate(ID, @ErrorOutput$)
    • Description: Determines the creation date of the file. This function is only valid within the ExamineMTPDirectory loop.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value: Value of the creation date. The value can be used with the date library.
    GetMTPDescription()
    • Syntax:

      Code: Select all

      Result = GetMTPDescription(ID, @Output$, @ErrorOutput$)
    • Description: Determines the device description.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The device description is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPDeviceID()
    • Syntax:

      Code: Select all

      Result = GetMTPDeviceID(ID, @Output$, @ErrorOutput$)
    • Description: Determines the device ID.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The device ID is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPDeviceType()
    • Syntax:

      Code: Select all

      Result = GetMTPDeviceType(ID, @ErrorOutput$)
    • Description: Determines the type of the device.
    • Parameter:
      1. ID: The number connection.
      2. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value: The following constants can be queried:
      • #PBEx_MTP_DeviceType_Generic
      • #PBEx_MTP_DeviceType_Camera
      • #PBEx_MTP_DeviceType_MediaPlayer
      • #PBEx_MTP_DeviceType_Phone
      • #PBEx_MTP_DeviceType_Video
      • #PBEx_MTP_DeviceType_PersonalInformationManager
      • #PBEx_MTP_DeviceType_AudioRecorder
    GetMTPFirmwareVersion()
    • Syntax:

      Code: Select all

      Result = GetMTPFirmwareVersion(ID, @Output$, @ErrorOutput$)
    • Description: Determines the firmware version.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The firmware version is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPFriendlyName()
    • Syntax:

      Code: Select all

      Result = GetMTPFriendlyName(ID, @Output$, @ErrorOutput$)
    • Description: Determines the device name.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The device name is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPManufacturer()
    • Syntax:

      Code: Select all

      Result = GetMTPManufacturer(ID, @Output$, @ErrorOutput$)
    • Description: Determines the manufacturer.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The manufacturer is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPModel()
    • Syntax:

      Code: Select all

      Result = GetMTPModel(ID, @Output$, @ErrorOutput$)
    • Description: Determines the model name.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The model name is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPPnPDeviceID()
    • Syntax:

      Code: Select all

      Result = GetMTPPnPDeviceID(ID, @Output$, @ErrorOutput$)
    • Description: Determines the PnP device ID. (Plug and Play)
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The PnP Device ID is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
    GetMTPSerialNumber()
    • Syntax:

      Code: Select all

      Result = GetMTPSerialNumber(ID, @Output$, @ErrorOutput$)
    • Description: Determines the serial number.
    • Parameter:
      1. ID: The number connection.
      2. @Output$: The serial number is stored in this variable.
      3. @ErrorOutput$: If an error occurred, the error message is stored in the variable. This variable must be reserved with 128 characters before passing. Maximum return length is 128 characters including the NULL character. If no error description is to be returned for an error, 0 can be passed instead.
    • Return value:
      • 1: The process was successful.
System requirements:
  • Windows Vista or higher
  • .NET Framework 4.5 or higher
  • Unicode activation (default from PB 5.50)
Lizenz: This DLL file is free of charge and may be used both privately and commercially.
This library is based on: https://github.com/Bassman2/MediaDevices

Download: https://www.rsbasic.de/downloads/downlo ... Ex_MTP.zip
Image

I would be very pleased about feedbacks, improvement suggestions, error messages or wishes. If you want to support me, you can also donate something. Thanks :)
Image
Image
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: PB.Ex MTP (Windows)

Post by RSBasic »

PB.Ex MTP 1.0.1.0 has been released.

Changelog:
  • Bugfix
Image
Image
MarkOtt
User
User
Posts: 28
Joined: Sat Feb 11, 2017 8:33 pm
Location: Switzerland

Re: PB.Ex MTP (Windows)

Post by MarkOtt »

Hello RSBasic

Thank you very much for your really useful solution.
Works great with Galaxy S3, S6 and iPhone.

Is there also a way to load a file from the PC to the mobile?

Best regards. Markus
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: PB.Ex MTP (Windows)

Post by RSBasic »

Thank you for testing and I am happy that it also works with Galaxy S3 and S6.
MarkOtt wrote:Is there also a way to load a file from the PC to the mobile?
Theoretically yes, but unfortunately I don't have a testable device. I can only transfer files from my smartphone and tablet to my PC, not to device.
In my DLL file I developed an undocumented function. Because I don't have a device to test, I didn't document this function.
You can test the following function:

Code: Select all

Prototype SendMTPFile(ID, FileName.p-Unicode, RemoteFileName.p-Unicode, ErrorOutput)
Global SendMTPFile.SendMTPFile = GetFunction(PBEx_MTP, "SendMTPFile")
No guarantee that this function will work because I could not test it.
Image
Image
MarkOtt
User
User
Posts: 28
Joined: Sat Feb 11, 2017 8:33 pm
Location: Switzerland

Re: PB.Ex MTP (Windows)

Post by MarkOtt »

SendMTPFile works very well on Samsung Galaxy S3, S6 and S7.

As there is no command to create a subdirectory, the directory must exist already (including a new subdir in the target path does not help). The file date on the target device is always 1970.01.01. An existing file cannot be overwritten.

On iPhone (Firmware version: 12.1.2) SendMTPFile does not work, the error message is:
"Die Anforderung wird nicht unterstützt. (Ausnahme von HRESULT: 0x80070032)"
(my translation: "The request is not supported. (Exception from HRESULT: 0x80070032)"

A command to create a subdirectory and one to set the file date would be very nice. But I know that this cannot be done easily. Well done anyway and veeery helpful!
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: PB.Ex MTP (Windows)

Post by RSBasic »

PB.Ex MTP 1.0.2.0 has been released.

Changelog:
  • Added: CreateMTPDirectory()
MarkOtt wrote:SendMTPFile works very well on Samsung Galaxy S3, S6 and S7.
Great
MarkOtt wrote:On iPhone (Firmware version: 12.1.2) SendMTPFile does not work, the error message is:
"Die Anforderung wird nicht unterstützt. (Ausnahme von HRESULT: 0x80070032)"
I have that message, too. For this reason I have not documented the SendMTPFile function because I cannot test it. Only certain devices allow copying (PC -> device).
MarkOtt wrote:A command to set the file date would be very nice.
That's not possible. I'm sorry
MarkOtt wrote:The file date on the target device is always 1970.01.01.
I don't know. It works on my test devices. It may be that it is another date format that I do not know.
MarkOtt wrote:A command to create a subdirectory would be very nice.
I added the function. I can't test it because my devices don't allow it.

Code: Select all

Prototype CreateMTPDirectory(ID, DirectoryPath.p-Unicode, ErrorOutput)
Global CreateMTPDirectory.CreateMTPDirectory = GetFunction(PBEx_MTP, "CreateMTPDirectory")
Image
Image
MarkOtt
User
User
Posts: 28
Joined: Sat Feb 11, 2017 8:33 pm
Location: Switzerland

Re: PB.Ex MTP (Windows)

Post by MarkOtt »

CreateMTPDirectory also works great on S3, S6 and S7. Thank you very much! :D
This will probably work fine on all Android with MTP enabled.
Multiple subdirectories can be created at once in one command, eg. \Card\Images\X\Y\Z\

Regarding SendMTPFile:
Shouldn't the file date be set automatically correct by the MTP protocol part on the mobile side?
Maybe a flaw in Android's MTP protocol implementation.

Do we have a chance to see a DeleteMTPFile ?

Sorry, I know, the appetite comes while eating. :)
I am always ready to test on Android.
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: PB.Ex MTP (Windows)

Post by RSBasic »

PB.Ex MTP 1.0.3.0 has been released.

Changelog:
  • Added: DeleteMTPDirectory()
  • Added: DeleteMTPFile()
@MarkOtt

Code: Select all

Prototype DeleteMTPDirectory(ID, Path.p-Unicode, ErrorOutput)
Global DeleteMTPDirectory.DeleteMTPDirectory = GetFunction(PBEx_MTP, "DeleteMTPDirectory")
Prototype DeleteMTPFile(ID, Path.p-Unicode, ErrorOutput)
Global DeleteMTPFile.DeleteMTPFile = GetFunction(PBEx_MTP, "DeleteMTPFile")
Image
Image
MarkOtt
User
User
Posts: 28
Joined: Sat Feb 11, 2017 8:33 pm
Location: Switzerland

Re: PB.Ex MTP (Windows)

Post by MarkOtt »

Just great!!

DeleteMTPFile() and DeleteMTPDirectory() are working perfect in Galaxy S3 to S7. 8)
Deleting a directory removes also the included subdirectories and files in one command. Very "powerful", but also very useful if handled carefully.


Regarding SendMTPFile() and the resulting file date 1.1.1970:

I searched a little bit in "libmtp" and found that it uses a date with ISO 8601 format.
"yyyy-mm-ddThh:mm:ss" or "yyyymmddThhmmss" (for local time zone)

The according c-code I found in "libmtp.c" is:
curtime = time(NULL);
loctime = localtime(&curtime);
strftime (tmp, sizeof(tmp), "%Y%m%dT%H%M%S.0%z", loctime);

Do you have a possibility to specify such a date/time in your code for SendMTPFile() ?
(maybe 1.1.1970 is the result of specifying 0 as a parameter somewhere)

Sorry to ask in this silly way, but I have no experience with .NET at all.

Thanks again for your wonderful work!
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: PB.Ex MTP (Windows)

Post by RSBasic »

I'm sorry, I have not found a way to change the date when sending or later.
I can only read the date of a file.
Image
Image
MarkOtt
User
User
Posts: 28
Joined: Sat Feb 11, 2017 8:33 pm
Location: Switzerland

Re: PB.Ex MTP (Windows)

Post by MarkOtt »

Interesting detail:
After removing the physical connection (USB cable) from the PC/Windows, and after physically connecting the Android device again, then the correct file date (time written) appears in a subsequent MTPDirectoryEntryDate(). Disconnecting with CloseMTP() and CloseLibrary() and reconnecting with OpenMTP() is not enough.

On the Android device itself the correct file date is available immediately after uploading a file. Thus Android is setting the file date automatically as one would expect.

There must be some sort of cache on the Windows system, strangely only for the file date, as file name and file size are always working immediately after uploading the file. Also in a concurrent Windows-Explorer showing the connected directory, the file name and file size are appearing immediately, only the file date is missing until the next physical reconnection of the device.

Interestingly enough, the file date is immediately displayed in Windows Explorer as expected if I copy a file directly to the device using Windows Explorer. It is able to bypass this "cache" effect.
Post Reply