mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
Bootloader installation for ipod and sansa: override the scanning with the device pointed to by the mountpoint. This allows selecting the correct player if two of the same brand are connected (FS#10096).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20832 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
549fc95b8d
commit
f679cf91cf
5 changed files with 169 additions and 91 deletions
|
@ -238,6 +238,11 @@ QStringList Autodetection::mountpoints()
|
||||||
return tempList;
|
return tempList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** resolve device name to mount point / drive letter
|
||||||
|
* @param device device name / disk number
|
||||||
|
* @return mount point / drive letter
|
||||||
|
*/
|
||||||
QString Autodetection::resolveMountPoint(QString device)
|
QString Autodetection::resolveMountPoint(QString device)
|
||||||
{
|
{
|
||||||
qDebug() << "Autodetection::resolveMountPoint(QString)" << device;
|
qDebug() << "Autodetection::resolveMountPoint(QString)" << device;
|
||||||
|
@ -289,39 +294,97 @@ QString Autodetection::resolveMountPoint(QString device)
|
||||||
QString result;
|
QString result;
|
||||||
unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt();
|
unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt();
|
||||||
|
|
||||||
for(int letter = 'A'; letter <= 'Z'; letter++) {
|
int letter;
|
||||||
|
for(letter = 'A'; letter <= 'Z'; letter++) {
|
||||||
|
if(resolveDevicename(QString(letter)).toUInt() == driveno) {
|
||||||
|
result = letter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qDebug() << "Autodetection::resolveMountPoint(QString)" << "->" << result;
|
||||||
|
if(!result.isEmpty())
|
||||||
|
return result + ":/";
|
||||||
|
#endif
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Resolve mountpoint to devicename / disk number
|
||||||
|
* @param path mountpoint path / drive letter
|
||||||
|
* @return devicename / disk number
|
||||||
|
*/
|
||||||
|
QString Autodetection::resolveDevicename(QString path)
|
||||||
|
{
|
||||||
|
qDebug() << __func__;
|
||||||
|
#if defined(Q_OS_LINUX)
|
||||||
|
FILE *mn = setmntent("/etc/mtab", "r");
|
||||||
|
if(!mn)
|
||||||
|
return QString("");
|
||||||
|
|
||||||
|
struct mntent *ent;
|
||||||
|
while((ent = getmntent(mn))) {
|
||||||
|
if(QString(ent->mnt_dir).startsWith(path)
|
||||||
|
&& QString(ent->mnt_type).contains("vfat", Qt::CaseInsensitive)) {
|
||||||
|
endmntent(mn);
|
||||||
|
return QString(ent->mnt_fsname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endmntent(mn);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_MACX)
|
||||||
|
int num;
|
||||||
|
struct statfs *mntinf;
|
||||||
|
|
||||||
|
num = getmntinfo(&mntinf, MNT_WAIT);
|
||||||
|
while(num--) {
|
||||||
|
if(QString(mntinf->f_mntonname).startsWith(path)
|
||||||
|
&& QString(mntinf->f_fstypename).contains("vfat", Qt::CaseInsensitive))
|
||||||
|
return QString(mntinf->f_mntfromname);
|
||||||
|
mntinf++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(Q_OS_OPENBSD)
|
||||||
|
int num;
|
||||||
|
struct statfs *mntinf;
|
||||||
|
|
||||||
|
num = getmntinfo(&mntinf, MNT_WAIT);
|
||||||
|
while(num--) {
|
||||||
|
if(QString(mntinf->f_mntonname).startsWith(device)
|
||||||
|
&& QString(mntinf->f_fstypename).contains("msdos", Qt::CaseInsensitive))
|
||||||
|
return QString(mntinf->f_mntfromname);
|
||||||
|
mntinf++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(Q_OS_WIN32)
|
||||||
DWORD written;
|
DWORD written;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
TCHAR uncpath[MAX_PATH];
|
TCHAR uncpath[MAX_PATH];
|
||||||
UCHAR buffer[0x400];
|
UCHAR buffer[0x400];
|
||||||
PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer;
|
PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer;
|
||||||
|
|
||||||
_stprintf(uncpath, _TEXT("\\\\.\\%c:"), letter);
|
_stprintf(uncpath, _TEXT("\\\\.\\%c:"), path.toAscii().at(0));
|
||||||
h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
NULL, OPEN_EXISTING, 0, NULL);
|
NULL, OPEN_EXISTING, 0, NULL);
|
||||||
if(h == INVALID_HANDLE_VALUE) {
|
if(h == INVALID_HANDLE_VALUE) {
|
||||||
//qDebug() << "error getting extents for" << uncpath;
|
//qDebug() << "error getting extents for" << uncpath;
|
||||||
continue;
|
return "";
|
||||||
}
|
}
|
||||||
// get the extents
|
// get the extents
|
||||||
if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
|
if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
|
||||||
NULL, 0, extents, sizeof(buffer), &written, NULL)) {
|
NULL, 0, extents, sizeof(buffer), &written, NULL)) {
|
||||||
for(unsigned int a = 0; a < extents->NumberOfDiskExtents; a++) {
|
if(extents->NumberOfDiskExtents > 1) {
|
||||||
qDebug() << "Disk:" << extents->Extents[a].DiskNumber;
|
qDebug() << "volume spans multiple disks!";
|
||||||
if(extents->Extents[a].DiskNumber == driveno) {
|
return "";
|
||||||
result = letter;
|
|
||||||
qDebug("drive found for volume %i: %c", driveno, letter);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
//qDebug() << "Disk:" << extents->Extents[0].DiskNumber;
|
||||||
|
return QString("%1").arg(extents->Extents[0].DiskNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if(!result.isEmpty())
|
|
||||||
return result + ":/";
|
|
||||||
#endif
|
#endif
|
||||||
return QString("");
|
return QString("");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
QString errdev(void) { return m_errdev; }
|
QString errdev(void) { return m_errdev; }
|
||||||
QString incompatdev(void) { return m_incompat; }
|
QString incompatdev(void) { return m_incompat; }
|
||||||
static QStringList mountpoints(void);
|
static QStringList mountpoints(void);
|
||||||
|
static QString resolveDevicename(QString path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString resolveMountPoint(QString);
|
QString resolveMountPoint(QString);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "bootloaderinstallipod.h"
|
#include "bootloaderinstallipod.h"
|
||||||
|
|
||||||
#include "../ipodpatcher/ipodpatcher.h"
|
#include "../ipodpatcher/ipodpatcher.h"
|
||||||
|
#include "autodetection.h"
|
||||||
|
|
||||||
|
|
||||||
BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent)
|
BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent)
|
||||||
|
@ -36,6 +37,7 @@ BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent)
|
||||||
|
|
||||||
BootloaderInstallIpod::~BootloaderInstallIpod()
|
BootloaderInstallIpod::~BootloaderInstallIpod()
|
||||||
{
|
{
|
||||||
|
if(ipod_sectorbuf)
|
||||||
free(ipod_sectorbuf);
|
free(ipod_sectorbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,13 +200,16 @@ BootloaderInstallBase::BootloaderType BootloaderInstallIpod::installed(void)
|
||||||
qDebug() << "BootloaderInstallIpod::installed(): BootloaderUnknown";
|
qDebug() << "BootloaderInstallIpod::installed(): BootloaderUnknown";
|
||||||
result = BootloaderUnknown;
|
result = BootloaderUnknown;
|
||||||
}
|
}
|
||||||
else if (ipod.ipod_directory[0].entryOffset == 0) {
|
else {
|
||||||
|
read_directory(&ipod);
|
||||||
|
if(ipod.ipod_directory[0].entryOffset == 0) {
|
||||||
qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther";
|
qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther";
|
||||||
result = BootloaderOther;
|
result = BootloaderOther;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox";
|
qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ipod_close(&ipod);
|
ipod_close(&ipod);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -219,20 +224,38 @@ BootloaderInstallBase::Capabilities BootloaderInstallIpod::capabilities(void)
|
||||||
|
|
||||||
bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod)
|
bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod)
|
||||||
{
|
{
|
||||||
|
if(!m_blfile.isEmpty()) {
|
||||||
|
#if defined(Q_OS_WIN32)
|
||||||
|
sprintf(ipod->diskname, "\\\\.\\PhysicalDrive%i",
|
||||||
|
Autodetection::resolveDevicename(m_blfile).toInt());
|
||||||
|
#elif defined(Q_OS_MACX)
|
||||||
|
sprintf(ipod->diskname,
|
||||||
|
qPrintable(Autodetection::resolveDevicename(m_blfile)
|
||||||
|
.remove(QRegExp("s[0-9]+$"))));
|
||||||
|
#else
|
||||||
|
sprintf(ipod->diskname,
|
||||||
|
qPrintable(Autodetection::resolveDevicename(m_blfile)
|
||||||
|
.remove(QRegExp("[0-9]+$"))));
|
||||||
|
#endif
|
||||||
|
qDebug() << "ipodpatcher: overriding scan, using" << ipod->diskname;
|
||||||
|
}
|
||||||
|
else {
|
||||||
ipod_scan(ipod);
|
ipod_scan(ipod);
|
||||||
|
}
|
||||||
if(ipod_open(ipod, 0) < 0) {
|
if(ipod_open(ipod, 0) < 0) {
|
||||||
emit logItem(tr("Could not open Ipod"), LOGERROR);
|
emit logItem(tr("Could not open Ipod"), LOGERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(read_partinfo(ipod, 0) < 0) {
|
if(read_partinfo(ipod, 0) < 0) {
|
||||||
emit logItem(tr("Could not read partition table"), LOGERROR);
|
emit logItem(tr("Error reading partition table - possibly not an Ipod"), LOGERROR);
|
||||||
|
ipod_close(ipod);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ipod->pinfo[0].start == 0) {
|
if(ipod->pinfo[0].start == 0) {
|
||||||
emit logItem(tr("No firmware partition on disk"), LOGERROR);
|
emit logItem(tr("No firmware partition on disk"), LOGERROR);
|
||||||
|
ipod_close(ipod);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "bootloaderinstallsansa.h"
|
#include "bootloaderinstallsansa.h"
|
||||||
|
|
||||||
#include "../sansapatcher/sansapatcher.h"
|
#include "../sansapatcher/sansapatcher.h"
|
||||||
|
#include "autodetection.h"
|
||||||
|
|
||||||
BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
|
BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
|
||||||
: BootloaderInstallBase(parent)
|
: BootloaderInstallBase(parent)
|
||||||
|
@ -36,6 +37,7 @@ BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
|
||||||
|
|
||||||
BootloaderInstallSansa::~BootloaderInstallSansa()
|
BootloaderInstallSansa::~BootloaderInstallSansa()
|
||||||
{
|
{
|
||||||
|
if(sansa_sectorbuf)
|
||||||
free(sansa_sectorbuf);
|
free(sansa_sectorbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,28 +82,10 @@ bool BootloaderInstallSansa::install(void)
|
||||||
void BootloaderInstallSansa::installStage2(void)
|
void BootloaderInstallSansa::installStage2(void)
|
||||||
{
|
{
|
||||||
struct sansa_t sansa;
|
struct sansa_t sansa;
|
||||||
sansa_scan(&sansa);
|
|
||||||
|
|
||||||
emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
|
emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
|
if(!sansaInitialize(&sansa)) {
|
||||||
if(sansa_open(&sansa, 0) < 0) {
|
|
||||||
emit logItem(tr("could not open Sansa"), LOGERROR);
|
|
||||||
emit done(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sansa_read_partinfo(&sansa, 0) < 0)
|
|
||||||
{
|
|
||||||
emit logItem(tr("could not read partitiontable"), LOGERROR);
|
|
||||||
emit done(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = is_sansa(&sansa);
|
|
||||||
if(i < 0) {
|
|
||||||
|
|
||||||
emit logItem(tr("Disk is not a Sansa (Error: %1), aborting.").arg(i), LOGERROR);
|
|
||||||
emit done(true);
|
emit done(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -169,27 +153,7 @@ bool BootloaderInstallSansa::uninstall(void)
|
||||||
emit logItem(tr("Uninstalling bootloader"), LOGINFO);
|
emit logItem(tr("Uninstalling bootloader"), LOGINFO);
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
if(sansa_scan(&sansa) != 1) {
|
if(!sansaInitialize(&sansa)) {
|
||||||
emit logItem(tr("Can't find Sansa"), LOGERROR);
|
|
||||||
emit done(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sansa_open(&sansa, 0) < 0) {
|
|
||||||
emit logItem(tr("Could not open Sansa"), LOGERROR);
|
|
||||||
emit done(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sansa_read_partinfo(&sansa,0) < 0) {
|
|
||||||
emit logItem(tr("Could not read partition table"), LOGERROR);
|
|
||||||
emit done(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = is_sansa(&sansa);
|
|
||||||
if(i < 0) {
|
|
||||||
emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
|
|
||||||
emit done(true);
|
emit done(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -235,18 +199,7 @@ BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
|
||||||
struct sansa_t sansa;
|
struct sansa_t sansa;
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
if(sansa_scan(&sansa) != 1) {
|
if(!sansaInitialize(&sansa)) {
|
||||||
return BootloaderUnknown;
|
|
||||||
}
|
|
||||||
if (sansa_open(&sansa, 0) < 0) {
|
|
||||||
return BootloaderUnknown;
|
|
||||||
}
|
|
||||||
if (sansa_read_partinfo(&sansa,0) < 0) {
|
|
||||||
sansa_close(&sansa);
|
|
||||||
return BootloaderUnknown;
|
|
||||||
}
|
|
||||||
if(is_sansa(&sansa) < 0) {
|
|
||||||
sansa_close(&sansa);
|
|
||||||
return BootloaderUnknown;
|
return BootloaderUnknown;
|
||||||
}
|
}
|
||||||
if((num = sansa_list_images(&sansa)) == 2) {
|
if((num = sansa_list_images(&sansa)) == 2) {
|
||||||
|
@ -261,6 +214,43 @@ BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa)
|
||||||
|
{
|
||||||
|
if(!m_blfile.isEmpty()) {
|
||||||
|
#if defined(Q_OS_WIN32)
|
||||||
|
sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i",
|
||||||
|
Autodetection::resolveDevicename(m_blfile).toInt());
|
||||||
|
#else
|
||||||
|
sprintf(sansa->diskname,
|
||||||
|
qPrintable(Autodetection::resolveDevicename(m_blfile).remove(QRegExp("[0-9]+$"))));
|
||||||
|
#endif
|
||||||
|
qDebug() << "sansapatcher: overriding scan, using" << sansa->diskname;
|
||||||
|
}
|
||||||
|
else if(sansa_scan(sansa) != 1) {
|
||||||
|
emit logItem(tr("Can't find Sansa"), LOGERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sansa_open(sansa, 0) < 0) {
|
||||||
|
emit logItem(tr("Could not open Sansa"), LOGERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sansa_read_partinfo(sansa,0) < 0) {
|
||||||
|
emit logItem(tr("Could not read partition table"), LOGERROR);
|
||||||
|
sansa_close(sansa);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = is_sansa(sansa);
|
||||||
|
if(i < 0) {
|
||||||
|
emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
|
||||||
|
sansa_close(sansa);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Get capabilities of subclass installer.
|
/** Get capabilities of subclass installer.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -38,6 +38,7 @@ class BootloaderInstallSansa : public BootloaderInstallBase
|
||||||
Capabilities capabilities(void);
|
Capabilities capabilities(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool sansaInitialize(struct sansa_t *);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void installStage2(void);
|
void installStage2(void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue