Archive:USB Mass Storage support in XBMC for Xbox - Developers discussion: Difference between revisions

From Official Kodi Wiki
Jump to navigation Jump to search
>Gamester17
No edit summary
>Gamester17
No edit summary
Line 160: Line 160:
[[category:Inner Workings]]
[[category:Inner Workings]]
[[category:Development]]
[[category:Development]]
[[category:Inner Workings]]
[[category:Xbox]]
[[category:Mac OS X]]
[[category:To-Do]]

Revision as of 05:35, 22 April 2009

Note! Non-developers can also help with the USB Mass Storage support in XBMC article (link).

FAT12/FAT16/VFAT/FAT32 on USB Mass Storage devices

XBMC still rely on the Xbox BIOS kernel USB driver to handle the USB subsystem stuff, including drive detection, etc.. XBMC then uses a ported version of dosfs to enable FAT12/FAT16/VFAT/FAT32 reading from USB Mass Storage devices, is read the drive directly (ie not via the usual XDK stuff) which we then feed through a simple filesystem layer (based on dosfs).

  • IoSynchronousDeviceIoControlRequest does not return a success on USB HDD
  • Kernel will report a: "WRN[MU]: The logical block configuration of an MU is outside supported parameter ranges."


So what can we do to detect a USB HDD Drive?
I tried to use some code from undocumented source to made a test: I think we can ackt like the kernel and can controll the USB our self to support also USB HDD's
i really just played with the code nothing else..


bool CMemoryUnitManager::MountFatDevice(unsigned long port, unsigned long slot) { #define WRITE_SIZE (4096*256) //1MB write size

 #define TEST_BUFFER_SIZE (4096*32)    //128KB
 #define TRANSFER_SIZE    4096
 #define MU_MEDIA_OFFSET  4096*8
 #define EXTRA_SIZE 4096
 #define SECTOR_MASK 0xFFFFFF000
 PARTITION_INFORMATION pi;
 ULONG					tryCount = 0;
 //CHAR                   name[64];

// HRESULT hr;

 //HANDLE                  hFile;
 PUCHAR buffer,buffer2;
 UCHAR pattern[4] = {1,2,3,4};
 ULONG i;
 HANDLE hVolume;
 OBJECT_ATTRIBUTES oa;
 IO_STATUS_BLOCK statusBlock;
 //DISK_GEOMETRY diskGeometry;
 NTSTATUS Status;

PDEVICE_OBJECT DeviceObject;

 CHAR oszDeviceObjectBuffer[64];
 //OBJECT_STRING DeviceName;
 OBJECT_STRING objName;
 ULONG   totalErrorCount = 0;
 ULONG   localErrorCount = 0;
 ULONGLONG bytesPerSecond = 0;
 objName.Length = 1024;
 objName.MaximumLength = sizeof(oszDeviceObjectBuffer)-1;
 objName.Buffer = oszDeviceObjectBuffer;

//DeviceName.Length = 0; //DeviceName.MaximumLength = sizeof(szDeviceName)/sizeof(CHAR)-2; //DeviceName.Buffer = szDeviceName;

 CLog::Log(LOGDEBUG, __FUNCTION__" Creating MU device (port %i, slot %i)", port, slot);
 Status = MU_CreateDeviceObject(port, slot, &objName);
 if(!NT_SUCCESS(Status))
 {
   CLog::Log(LOGDEBUG, __FUNCTION__"Could not create device object for MU, status = 0x%0.8x");
   //return false;
 }
 buffer =  (PUCHAR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, TEST_BUFFER_SIZE+EXTRA_SIZE);
 buffer2 =  (PUCHAR) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, TEST_BUFFER_SIZE+EXTRA_SIZE);
 buffer = (PUCHAR)((ULONG) buffer & SECTOR_MASK);
 buffer += EXTRA_SIZE;
 buffer2 = (PUCHAR)((ULONG) buffer2 & SECTOR_MASK);
 buffer2 += EXTRA_SIZE;
 for (i=0;i<TEST_BUFFER_SIZE/sizeof(ULONG);i++) 
 {
   *((PULONG)buffer+i) = i;
 }
 CLog::Log(LOGDEBUG, __FUNCTION__"MUTEST: LowLevelTest: Test buffer 1 at %x, 2 at %x",buffer,buffer2);
 InitializeObjectAttributes(&oa, (POBJECT_STRING) &objName, OBJ_CASE_INSENSITIVE, NULL, NULL);
 CLog::Log(LOGDEBUG, __FUNCTION__"MUTEST: LowLevelTest: Opening volume");
     
 Status = NtOpenFile(&hVolume,
                       SYNCHRONIZE | GENERIC_ALL,
                       &oa,
                       &statusBlock,
                       FILE_SHARE_READ | FILE_SHARE_WRITE,
                       FILE_NO_INTERMEDIATE_BUFFERING | FILE_SYNCHRONOUS_IO_ALERT);
     
 Status = NtDeviceIoControlFile(hVolume,0,NULL,NULL,&statusBlock,IOCTL_DISK_GET_PARTITION_INFO,NULL,0,&pi,
                                          sizeof(pi));

//if (!NT_SUCCESS(Status)) //{

   CLog::Log(LOGDEBUG, __FUNCTION__" Getting MU device (port %i, slot %i)", port, slot);

DeviceObject = MU_GetExistingDeviceObject(port, slot);

   CLog::Log(LOGDEBUG, __FUNCTION__" Reading MU partition info (port %i, slot %i)", port, slot);
 	
   Status = IoSynchronousDeviceIoControlRequest(IOCTL_DISK_GET_PARTITION_INFO,
           DeviceObject, NULL, 0, &pi,
           sizeof(pi), NULL, FALSE);
   if (!NT_SUCCESS(Status))
   {
     CLog::Log(LOGDEBUG, __FUNCTION__" !! FAILED !! Reading MU partition info (port %i, slot %i)", port, slot);
     //return false;
     // IOCTL_DISK_GET_DRIVE_GEOMETRY
     // IOCTL_DISK_GET_PARTITION_INFO
     // IOCTL_DISK_VERIFY
   }
   uint8_t sector[SECTOR_SIZE];
   uint8_t unit = m_fatUnits.size();
   CFatDevice *fatDevice = new CFatDevice(port, slot, DeviceObject);
   m_fatUnits.push_back(fatDevice);
   // TEST: Dump first 32k of image to make sure we're reading valid data (yuck!)
   DumpImage("Z:\\image.bin", unit, 64);
   CLog::Log(LOGDEBUG, __FUNCTION__" Reading first sector to determine type");
   uint32_t lbrSector = 0;
   int ret = CheckFirstSectorForLBR(unit);
   if (ret)
   {
     CLog::Log(LOGDEBUG, __FUNCTION__" First sector failed LBR test (%i)", ret);
     // read the MBR

uint32_t psize; uint8_t pactive, ptype;

     // 0 is the partition number
     lbrSector = DFS_GetPtnStart(unit, sector, 0, &pactive, &ptype, &psize);
     if (lbrSector == 0xFFFFFFFF)
     { // fail
       CLog::Log(LOGDEBUG, __FUNCTION__" No MBR found - assuming none exists");
       lbrSector = 0;
     }
     else
     {
       CLog::Log(LOGDEBUG, __FUNCTION__" Partition 0 start sector 0x%-08.8lX active %-02.2hX type %-02.2hX size %-08.8lX\n", lbrSector, pactive, ptype, psize);
     }
   }
   if (DFS_GetVolInfo(unit, sector, lbrSector, fatDevice->GetVolume()))
   {
     CLog::Log(LOGDEBUG, __FUNCTION__" Error getting volume information\n");
     UnMountFatDevice(port, slot);
     return false;
   }
   fatDevice->ReadVolumeName();
   fatDevice->LogInfo();
   return true;

//}

 //return false;

}



The 4GB limit

XBMC rely on the Xbox BIOS kernel USB driver to handle the USB subsystem stuff, including drive detection etc. One limitation with this is this it can't support memory-cars/harddrives larger than 4GB. This is Xbox BIOS kernel limitation. Only way around it that we see would be to completely rewriting the USB driver (practically writting a USB stack for the Xbox from scratch), which no one of Team-XBMC developers have the experience, skill or time to do, (plus it'd be a hell of a lot of work).