Files
XBMC4Xbox/xbmc/utils/MemoryUnitManager.cpp
Rocky5 921f9fe9f8 Clean Copy
If ever adding the XBMC4Xbox source to GitHub use "git add -f -A" or it wont add all the files.
2024-01-08 19:01:29 +00:00

286 lines
7.9 KiB
C++

/*
* Copyright (C) 2005-2013 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#include "xbox/Undocumented.h"
#include "MemoryUnitManager.h"
#include "FileSystem/MemoryUnits/FatXDevice.h"
#include "FileSystem/MemoryUnits/FatXFileSystem.h"
#include "FileSystem/MemoryUnits/Fat32Device.h"
#include "FileSystem/MemoryUnits/Fat32FileSystem.h"
#include "Application.h"
#include "URL.h"
#include "LocalizeStrings.h"
#include "utils/log.h"
using namespace std;
using namespace XFILE;
// Undocumented stuff
typedef STRING OBJECT_STRING;
typedef PSTRING POBJECT_STRING;
extern "C"
{
XBOXAPI NTSTATUS WINAPI
MU_CreateDeviceObject(
IN ULONG Port,
IN ULONG Slot,
IN POBJECT_STRING DeviceName
);
XBOXAPI VOID WINAPI
MU_CloseDeviceObject(
IN ULONG Port,
IN ULONG Slot
);
XBOXAPI PDEVICE_OBJECT WINAPI
MU_GetExistingDeviceObject(
IN ULONG Port,
IN ULONG Slot
);
};
CMemoryUnitManager g_memoryUnitManager;
CMemoryUnitManager::CMemoryUnitManager()
{
m_initialized = false;
}
bool CMemoryUnitManager::Update()
{
DWORD newdev = 0;
DWORD deaddev = 0;
bool notify = true;
if (!m_initialized)
{
newdev = XGetDevices(XDEVICE_TYPE_MEMORY_UNIT);
m_initialized = true;
notify = false;
}
else if (!XGetDeviceChanges(XDEVICE_TYPE_MEMORY_UNIT, &newdev, &deaddev))
return false;
if (!newdev && !deaddev)
return false;
CLog::Log(LOGDEBUG, __FUNCTION__" Reports added device %08x and removed device %08x", newdev, deaddev);
if (deaddev && deaddev != newdev)
UnMountUnits(deaddev);
if (newdev && newdev != deaddev)
MountUnits(newdev, notify);
return (newdev || deaddev);
}
void CMemoryUnitManager::UnMountUnits(unsigned long device)
{
CLog::Log(LOGNOTICE, "Attempting to unmount memory unit device %08x", device);
for (DWORD i = 0; i < 4; ++i)
{
if (device & (1 << i))
{
if (HasDevice(XDEVICE_PORT0 + i, XDEVICE_TOP_SLOT))
{
UnMountDevice(XDEVICE_PORT0 + i, XDEVICE_TOP_SLOT);
}
}
if (device & (1 << (i + 16)))
{
if (HasDevice(XDEVICE_PORT0 + i, XDEVICE_BOTTOM_SLOT))
{
UnMountDevice(XDEVICE_PORT0 + i, XDEVICE_BOTTOM_SLOT);
}
}
}
}
void CMemoryUnitManager::MountUnits(unsigned long device, bool notify)
{
CLog::Log(LOGNOTICE, "Attempting to mount memory unit device %08x", device);
for (DWORD i = 0; i < 4; ++i)
{
if (device & (1 << i))
{
bool success = MountDevice(XDEVICE_PORT0 + i, XDEVICE_TOP_SLOT);
if (notify || !success) Notify(XDEVICE_PORT0 + i, XDEVICE_TOP_SLOT, success);
}
if (device & (1 << (i + 16)))
{
bool success = MountDevice(XDEVICE_PORT0 + i, XDEVICE_BOTTOM_SLOT);
if (notify || !success) Notify(XDEVICE_PORT0 + i, XDEVICE_BOTTOM_SLOT, success);
}
}
}
bool CMemoryUnitManager::IsDriveValid(char Drive)
{
for (unsigned int i = 0; i < m_memUnits.size(); i++)
{
IDevice *device = m_memUnits[i];
if (strcmpi(device->GetFileSystem(), "fatx") == 0)
{
if (((CFatXDevice *)device)->GetDrive() == Drive)
return true;
}
}
return false;
}
bool CMemoryUnitManager::HasDevice(unsigned long port, unsigned long slot)
{
for (unsigned int i = 0; i < m_memUnits.size(); i++)
if (m_memUnits[i]->IsInPort(port, slot))
return true;
return false;
}
bool CMemoryUnitManager::MountDevice(unsigned long port, unsigned long slot)
{
// check whether we already have one mounted here...
if (HasDevice(port, slot))
{
CLog::Log(LOGERROR, __FUNCTION__" Attempt to mount already mounted usb device");
return false;
}
NTSTATUS Status;
CHAR szDeviceName[64];
OBJECT_STRING DeviceName;
PDEVICE_OBJECT DeviceObject;
// setup the string buffer - leave room for NULL and '\\'
DeviceName.Length = 0;
DeviceName.MaximumLength = sizeof(szDeviceName)/sizeof(CHAR)-2;
DeviceName.Buffer = szDeviceName;
// create the device object
CLog::Log(LOGDEBUG, __FUNCTION__" Creating MU device (port %i, slot %i)", port, slot);
Status = MU_CreateDeviceObject(port, slot, &DeviceName);
if(NT_SUCCESS(Status))
{
CLog::Log(LOGDEBUG, __FUNCTION__" Getting MU device (port %i, slot %i)", port, slot);
DeviceObject = MU_GetExistingDeviceObject(port, slot);
CFatXDevice *device = new CFatXDevice(port, slot, DeviceObject);
if (device->Mount(DeviceName.Buffer))
{
m_memUnits.push_back(device);
return true;
}
delete device;
// Try FAT12/16/32
CFat32Device *fatDevice = new CFat32Device(port, slot, DeviceObject);
if (fatDevice->Mount(DeviceName.Buffer))
{
m_memUnits.push_back(fatDevice);
return true;
}
delete fatDevice;
MU_CloseDeviceObject(port, slot);
}
return false;
}
bool CMemoryUnitManager::UnMountDevice(unsigned long port, unsigned long slot)
{
CLog::Log(LOGDEBUG, __FUNCTION__" Unmounting MU device (port %i, slot %i)", port, slot);
for (vector<IDevice *>::iterator it = m_memUnits.begin(); it != m_memUnits.end(); ++it)
{
IDevice *device = *it;
if (device->IsInPort(port, slot))
{
CLog::Log(LOGDEBUG, __FUNCTION__" Found MU device to unmount (port %i, slot %i)", port, slot);
device->UnMount();
CLog::Log(LOGDEBUG, __FUNCTION__" Closing device object (port %i, slot %i)", port, slot);
MU_CloseDeviceObject(port, slot);
CLog::Log(LOGDEBUG, __FUNCTION__" Device object is closed");
delete device;
CLog::Log(LOGDEBUG, __FUNCTION__" Device is deleted");
m_memUnits.erase(it);
return true;
}
}
return false;
}
IDevice *CMemoryUnitManager::GetDevice(unsigned char unit) const
{
if (unit >= m_memUnits.size())
{
CLog::Log(LOGERROR, __FUNCTION__" Attempt to access memory device %i when it doesn't exist", unit);
return NULL;
}
return m_memUnits[unit];
}
bool CMemoryUnitManager::IsDriveWriteable(const CStdString &path) const
{
CURL url(path);
IDevice *device = GetDevice(url.GetProtocol()[3] - '0');
if (device && strcmpi(device->GetFileSystem(), "fatx") == 0)
return true;
return false;
}
void CMemoryUnitManager::GetMemoryUnitSources(VECSOURCES &shares)
{
for (unsigned int i = 0; i < m_memUnits.size(); i++)
{
CMediaSource share;
CStdString volumeName = m_memUnits[i]->GetVolumeName();
volumeName.TrimRight(' ');
// Memory Unit # (volumeName) (fs)
if (volumeName.IsEmpty())
share.strName.Format("%s %i (%s)", g_localizeStrings.Get(20136).c_str(), i + 1, m_memUnits[i]->GetFileSystem());
else
share.strName.Format("%s %i (%s) (%s)", g_localizeStrings.Get(20136).c_str(), i + 1, volumeName.c_str(), m_memUnits[i]->GetFileSystem());
share.strPath.Format("mem%i://", i);
shares.push_back(share);
}
}
IFileSystem *CMemoryUnitManager::GetFileSystem(unsigned char unit)
{
IDevice *device = GetDevice(unit);
if (!device)
return NULL;
if (strcmpi(device->GetFileSystem(), "fatx") == 0)
return new CFatXFileSystem(unit);
return new CFat32FileSystem(unit);
}
void CMemoryUnitManager::Notify(unsigned long port, unsigned long slot, bool success)
{
CStdString portSlot;
portSlot.Format(g_localizeStrings.Get(20139).c_str(), port, slot);
if (success)
g_application.m_guiDialogKaiToast.QueueNotification(g_localizeStrings.Get(20137), portSlot);
else
g_application.m_guiDialogKaiToast.QueueNotification(g_localizeStrings.Get(20138), portSlot);
}