View Issue Details

IDProjectCategoryView StatusLast Update
0003033MMW v4Synchronizationpublic2007-09-18 18:16
Reporterjiri Assigned To 
PriorityhighSeverityminorReproducibilityalways
Status confirmedResolutionopen 
Product Version3.0 
Summary0003033: Retrieve information from iPod about requested image dimensions, etc.
DescriptionCurrently we hardcode some information about iPods in our synchronization plug-in, for example dimensions of the album art images to be stored on iPod. Another problem is that we can't reliably get serial number of iPod.

Fortunatelly, starting from 4th generation of iPods, there's an XML document that contains all this information. The document isn't stored in a file, but can be retrieved over USB interface. I stored all our current knowledge about how to get this XML document from iPod to our Wiki: http://www.jirihajek.net/MMwiki/index.php/IPod_USB_interface
TagsNo tags attached.
Fixed in build

Activities

jiri

2007-05-04 15:38

administrator   ~0009107

Last edited: 2007-05-04 15:40

Assigning to Ludek to write a testing application that would (based on the above specified documentation) read the XML data reliably from iPod. It should:
 1. Return the XML document from iPod.
 2. Be written in Delphi so that we can use it in our plug-in (based on C source code of SG3_Utils).
 3. Don't require administration rights (to be tested on XP and Vista).
 4. Work somehow on Win9x and ME. It probably won't work really well, since these systems don't support SPTI interface that we need to use, but it should at least properly return empty results.

All interesting information should be documented in the Wiki article.

Ludek

2007-05-15 16:59

developer   ~0009151

1) and 2) has been done.
See function Get_iPod_XML( DriveLetter : Char) : String;
in the new unit SG3_Utils.pas

3) There are multiple times mentioned on the internet that
In order to send IOCTL_SCSI_PASS_THROUGH_DIRECT you must be an administrator.

The problem is that we use IOCTL_SCSI_PASS_THROUGH_DIRECT method that is defined as CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) and due to FILE_WRITE_ACCESS attribute you must be an administrator :-(

4) I do not have any such system installed (Win98, WinME) so I could not test it.

jiri

2007-09-18 15:03

administrator   ~0010813

It seems that 3 is a problem we can't solve, except by using e.g. a service (as Apple does?).

Anyway, for a possible future reference, here's a sample code I found at (http://stashbox.org/37478/SysInfoXML.cpp) (not that we already have implemented a similar code in Delphi):

#include <windows.h>
#include <stddef.h> // for offsetof
#include <winioctl.h>
#include <strsafe.h>

    typedef struct {
  USHORT Length;
  UCHAR ScsiStatus;
  UCHAR PathId;
  UCHAR TargetId;
  UCHAR Lun;
  UCHAR CdbLength;
  UCHAR SenseInfoLength;
  UCHAR DataIn;
  ULONG DataTransferLength;
  ULONG TimeOutValue;
  PVOID DataBuffer;
  ULONG SenseInfoOffset;
  UCHAR Cdb[16];
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;


    typedef struct {
  SCSI_PASS_THROUGH_DIRECT spt;
  ULONG Filler;
  UCHAR ucSenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;



    #define IOCTL_SCSI_BASE 0x00000004

/*
 * constants for DataIn member of SCSI_PASS_THROUGH* structures
 */
#define SCSI_IOCTL_DATA_OUT 0
#define SCSI_IOCTL_DATA_IN 1
#define SCSI_IOCTL_DATA_UNSPECIFIED 2

/*
 * Standard IOCTL define
 */
#define CTL_CODE( DevType, Function, Method, Access ) ( \
    ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS

static void scsi_inquiry(HANDLE deviceHandle, UCHAR page, UCHAR *inqbuf, size_t &buf_len)
{
    char buf[2048];
    BOOL status;
    PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER pswb;
    
    DWORD length=0, returned=0;

  /*
   * Get the drive inquiry data
   */
  ZeroMemory( &buf, 2048 );
  ZeroMemory( inqbuf, buf_len );
  pswb = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)buf;
  pswb->spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
  pswb->spt.CdbLength = 6;
  pswb->spt.SenseInfoLength = 32;
  pswb->spt.DataIn = SCSI_IOCTL_DATA_IN;
  pswb->spt.DataTransferLength = buf_len;
  pswb->spt.TimeOutValue = 2;
  pswb->spt.DataBuffer = inqbuf;
  pswb->spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
  pswb->spt.Cdb[0] = 0x12;
    pswb->spt.Cdb[1] = 0x1;
    pswb->spt.Cdb[2] = page;
  pswb->spt.Cdb[4] = buf_len;

  length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
  status = DeviceIoControl( deviceHandle,
                IOCTL_SCSI_PASS_THROUGH_DIRECT,
                pswb,
                length,
                pswb,
                length,
                &returned,
                NULL );

    
    if (status && returned >3)
        buf_len=returned;
    else
        buf_len=0;
}

static void AddPagetoXML(HANDLE dev, char *dest, size_t destlen, UCHAR page)
{
    UCHAR buf[256];
    buf[255]=0;
    ZeroMemory(buf, 256);
    size_t buflen=255;
    scsi_inquiry(dev, page, buf, buflen);
    StringCchCatA(dest, destlen, (char *)buf+4);
}

static void BuildXML(HANDLE dev, char *xml, size_t xmllen)
{
    *xml=0;
    UCHAR pages[255];
    ZeroMemory(pages, 255);
    size_t pageslen=255;
    scsi_inquiry(dev, 0xc0, pages, pageslen);
    if (pageslen>3)
    {
        unsigned char numPages=pages[3];
        if (numPages+4 <= 255)
        {
            for (int i=0;i<numPages;i++)
            {
                AddPagetoXML(dev, xml, xmllen, pages[i+4]);
            }
        }
    }
}

bool ParseSysInfoXML(wchar_t drive_letter)
{
    char xml[65536];
    wchar_t fn[MAX_PATH];
    StringCchPrintf(fn, MAX_PATH, L"\\\\.\\%c:", drive_letter);
    HANDLE hfile = CreateFileW(fn, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    if (hfile != INVALID_HANDLE_VALUE)
    {
        BuildXML(hfile, xml, 65536);
        // TODO: umm, do something with it :)
        CloseHandle(hfile);
        return true;
    }
    return false;
}

Ludek

2007-09-18 18:16

developer   ~0010818

Yes, the same code is already rewritten in delphi (by me) and is included in
../Plugins/Devices/d_iPod/Sg3_Utils.pas