summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Riebeling <Dominik.Riebeling@gmail.com>2009-04-30 19:14:24 +0000
committerDominik Riebeling <Dominik.Riebeling@gmail.com>2009-04-30 19:14:24 +0000
commitf679cf91cf94363d10f99db5cbae872401ed5612 (patch)
tree8925a97c85a19c19a7979b464d0529dbd30dd430
parent549fc95b8d0f9ecfb6c18ad6c9a75503458e645d (diff)
downloadrockbox-f679cf91cf94363d10f99db5cbae872401ed5612.zip
rockbox-f679cf91cf94363d10f99db5cbae872401ed5612.tar.gz
rockbox-f679cf91cf94363d10f99db5cbae872401ed5612.tar.bz2
rockbox-f679cf91cf94363d10f99db5cbae872401ed5612.tar.xz
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
-rw-r--r--rbutil/rbutilqt/base/autodetection.cpp115
-rw-r--r--rbutil/rbutilqt/base/autodetection.h1
-rw-r--r--rbutil/rbutilqt/base/bootloaderinstallipod.cpp41
-rw-r--r--rbutil/rbutilqt/base/bootloaderinstallsansa.cpp100
-rw-r--r--rbutil/rbutilqt/base/bootloaderinstallsansa.h1
5 files changed, 168 insertions, 90 deletions
diff --git a/rbutil/rbutilqt/base/autodetection.cpp b/rbutil/rbutilqt/base/autodetection.cpp
index ee42a8c..276c270 100644
--- a/rbutil/rbutilqt/base/autodetection.cpp
+++ b/rbutil/rbutilqt/base/autodetection.cpp
@@ -238,6 +238,11 @@ QStringList Autodetection::mountpoints()
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)
{
qDebug() << "Autodetection::resolveMountPoint(QString)" << device;
@@ -289,39 +294,97 @@ QString Autodetection::resolveMountPoint(QString device)
QString result;
unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt();
- for(int letter = 'A'; letter <= 'Z'; letter++) {
- DWORD written;
- HANDLE h;
- TCHAR uncpath[MAX_PATH];
- UCHAR buffer[0x400];
- PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer;
-
- _stprintf(uncpath, _TEXT("\\\\.\\%c:"), letter);
- h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, 0, NULL);
- if(h == INVALID_HANDLE_VALUE) {
- //qDebug() << "error getting extents for" << uncpath;
- continue;
+ int letter;
+ for(letter = 'A'; letter <= 'Z'; letter++) {
+ if(resolveDevicename(QString(letter)).toUInt() == driveno) {
+ result = letter;
+ break;
}
- // get the extents
- if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
- NULL, 0, extents, sizeof(buffer), &written, NULL)) {
- for(unsigned int a = 0; a < extents->NumberOfDiskExtents; a++) {
- qDebug() << "Disk:" << extents->Extents[a].DiskNumber;
- if(extents->Extents[a].DiskNumber == driveno) {
- result = letter;
- qDebug("drive found for volume %i: %c", driveno, 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;
+ HANDLE h;
+ TCHAR uncpath[MAX_PATH];
+ UCHAR buffer[0x400];
+ PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer;
+
+ _stprintf(uncpath, _TEXT("\\\\.\\%c:"), path.toAscii().at(0));
+ h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+ if(h == INVALID_HANDLE_VALUE) {
+ //qDebug() << "error getting extents for" << uncpath;
+ return "";
+ }
+ // get the extents
+ if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
+ NULL, 0, extents, sizeof(buffer), &written, NULL)) {
+ if(extents->NumberOfDiskExtents > 1) {
+ qDebug() << "volume spans multiple disks!";
+ return "";
+ }
+ //qDebug() << "Disk:" << extents->Extents[0].DiskNumber;
+ return QString("%1").arg(extents->Extents[0].DiskNumber);
}
- if(!result.isEmpty())
- return result + ":/";
#endif
return QString("");
+
}
diff --git a/rbutil/rbutilqt/base/autodetection.h b/rbutil/rbutilqt/base/autodetection.h
index 7e6386c..cffab5b 100644
--- a/rbutil/rbutilqt/base/autodetection.h
+++ b/rbutil/rbutilqt/base/autodetection.h
@@ -42,6 +42,7 @@ public:
QString errdev(void) { return m_errdev; }
QString incompatdev(void) { return m_incompat; }
static QStringList mountpoints(void);
+ static QString resolveDevicename(QString path);
private:
QString resolveMountPoint(QString);
diff --git a/rbutil/rbutilqt/base/bootloaderinstallipod.cpp b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp
index 82c6495..e4a70e0 100644
--- a/rbutil/rbutilqt/base/bootloaderinstallipod.cpp
+++ b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp
@@ -22,6 +22,7 @@
#include "bootloaderinstallipod.h"
#include "../ipodpatcher/ipodpatcher.h"
+#include "autodetection.h"
BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent)
@@ -36,7 +37,8 @@ BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent)
BootloaderInstallIpod::~BootloaderInstallIpod()
{
- free(ipod_sectorbuf);
+ if(ipod_sectorbuf)
+ free(ipod_sectorbuf);
}
@@ -198,12 +200,15 @@ BootloaderInstallBase::BootloaderType BootloaderInstallIpod::installed(void)
qDebug() << "BootloaderInstallIpod::installed(): BootloaderUnknown";
result = BootloaderUnknown;
}
- else if (ipod.ipod_directory[0].entryOffset == 0) {
- qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther";
- result = BootloaderOther;
- }
else {
- qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox";
+ read_directory(&ipod);
+ if(ipod.ipod_directory[0].entryOffset == 0) {
+ qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther";
+ result = BootloaderOther;
+ }
+ else {
+ qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox";
+ }
}
ipod_close(&ipod);
@@ -219,20 +224,38 @@ BootloaderInstallBase::Capabilities BootloaderInstallIpod::capabilities(void)
bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod)
{
- ipod_scan(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);
+ }
if(ipod_open(ipod, 0) < 0) {
emit logItem(tr("Could not open Ipod"), LOGERROR);
return false;
}
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;
}
if(ipod->pinfo[0].start == 0) {
emit logItem(tr("No firmware partition on disk"), LOGERROR);
-
+ ipod_close(ipod);
return false;
}
return true;
diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp
index 4679c2e..aab298c 100644
--- a/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp
+++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp
@@ -22,6 +22,7 @@
#include "bootloaderinstallsansa.h"
#include "../sansapatcher/sansapatcher.h"
+#include "autodetection.h"
BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
: BootloaderInstallBase(parent)
@@ -36,7 +37,8 @@ BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
BootloaderInstallSansa::~BootloaderInstallSansa()
{
- free(sansa_sectorbuf);
+ if(sansa_sectorbuf)
+ free(sansa_sectorbuf);
}
@@ -80,30 +82,12 @@ bool BootloaderInstallSansa::install(void)
void BootloaderInstallSansa::installStage2(void)
{
struct sansa_t sansa;
- sansa_scan(&sansa);
emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
QCoreApplication::processEvents();
-
- 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);
- return;
+ if(!sansaInitialize(&sansa)) {
+ emit done(true);
+ return;
}
if(sansa.hasoldbootloader) {
@@ -169,27 +153,7 @@ bool BootloaderInstallSansa::uninstall(void)
emit logItem(tr("Uninstalling bootloader"), LOGINFO);
QCoreApplication::processEvents();
- if(sansa_scan(&sansa) != 1) {
- 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);
+ if(!sansaInitialize(&sansa)) {
emit done(true);
return false;
}
@@ -235,18 +199,7 @@ BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
struct sansa_t sansa;
int num;
- if(sansa_scan(&sansa) != 1) {
- 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);
+ if(!sansaInitialize(&sansa)) {
return BootloaderUnknown;
}
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.
*/
diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.h b/rbutil/rbutilqt/base/bootloaderinstallsansa.h
index a391105..29eaa6d 100644
--- a/rbutil/rbutilqt/base/bootloaderinstallsansa.h
+++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.h
@@ -38,6 +38,7 @@ class BootloaderInstallSansa : public BootloaderInstallBase
Capabilities capabilities(void);
private:
+ bool sansaInitialize(struct sansa_t *);
private slots:
void installStage2(void);