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.tar.gz
rockbox-f679cf91cf94363d10f99db5cbae872401ed5612.zip
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 ee42a8c09e..276c270499 100644
--- a/rbutil/rbutilqt/base/autodetection.cpp
+++ b/rbutil/rbutilqt/base/autodetection.cpp
@@ -238,6 +238,11 @@ QStringList Autodetection::mountpoints()
238 return tempList; 238 return tempList;
239} 239}
240 240
241
242/** resolve device name to mount point / drive letter
243 * @param device device name / disk number
244 * @return mount point / drive letter
245 */
241QString Autodetection::resolveMountPoint(QString device) 246QString Autodetection::resolveMountPoint(QString device)
242{ 247{
243 qDebug() << "Autodetection::resolveMountPoint(QString)" << device; 248 qDebug() << "Autodetection::resolveMountPoint(QString)" << device;
@@ -289,39 +294,97 @@ QString Autodetection::resolveMountPoint(QString device)
289 QString result; 294 QString result;
290 unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt(); 295 unsigned int driveno = device.replace(QRegExp("^.*([0-9]+)"), "\\1").toInt();
291 296
292 for(int letter = 'A'; letter <= 'Z'; letter++) { 297 int letter;
293 DWORD written; 298 for(letter = 'A'; letter <= 'Z'; letter++) {
294 HANDLE h; 299 if(resolveDevicename(QString(letter)).toUInt() == driveno) {
295 TCHAR uncpath[MAX_PATH]; 300 result = letter;
296 UCHAR buffer[0x400]; 301 break;
297 PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer;
298
299 _stprintf(uncpath, _TEXT("\\\\.\\%c:"), letter);
300 h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
301 NULL, OPEN_EXISTING, 0, NULL);
302 if(h == INVALID_HANDLE_VALUE) {
303 //qDebug() << "error getting extents for" << uncpath;
304 continue;
305 } 302 }
306 // get the extents 303 }
307 if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 304 qDebug() << "Autodetection::resolveMountPoint(QString)" << "->" << result;
308 NULL, 0, extents, sizeof(buffer), &written, NULL)) { 305 if(!result.isEmpty())
309 for(unsigned int a = 0; a < extents->NumberOfDiskExtents; a++) { 306 return result + ":/";
310 qDebug() << "Disk:" << extents->Extents[a].DiskNumber; 307#endif
311 if(extents->Extents[a].DiskNumber == driveno) { 308 return QString("");
312 result = letter; 309}
313 qDebug("drive found for volume %i: %c", driveno, letter);
314 break;
315 }
316 }
317 310
311
312/** Resolve mountpoint to devicename / disk number
313 * @param path mountpoint path / drive letter
314 * @return devicename / disk number
315 */
316QString Autodetection::resolveDevicename(QString path)
317{
318 qDebug() << __func__;
319#if defined(Q_OS_LINUX)
320 FILE *mn = setmntent("/etc/mtab", "r");
321 if(!mn)
322 return QString("");
323
324 struct mntent *ent;
325 while((ent = getmntent(mn))) {
326 if(QString(ent->mnt_dir).startsWith(path)
327 && QString(ent->mnt_type).contains("vfat", Qt::CaseInsensitive)) {
328 endmntent(mn);
329 return QString(ent->mnt_fsname);
318 } 330 }
331 }
332 endmntent(mn);
333
334#endif
319 335
336#if defined(Q_OS_MACX)
337 int num;
338 struct statfs *mntinf;
339
340 num = getmntinfo(&mntinf, MNT_WAIT);
341 while(num--) {
342 if(QString(mntinf->f_mntonname).startsWith(path)
343 && QString(mntinf->f_fstypename).contains("vfat", Qt::CaseInsensitive))
344 return QString(mntinf->f_mntfromname);
345 mntinf++;
346 }
347#endif
348
349#if defined(Q_OS_OPENBSD)
350 int num;
351 struct statfs *mntinf;
352
353 num = getmntinfo(&mntinf, MNT_WAIT);
354 while(num--) {
355 if(QString(mntinf->f_mntonname).startsWith(device)
356 && QString(mntinf->f_fstypename).contains("msdos", Qt::CaseInsensitive))
357 return QString(mntinf->f_mntfromname);
358 mntinf++;
359 }
360#endif
361#if defined(Q_OS_WIN32)
362 DWORD written;
363 HANDLE h;
364 TCHAR uncpath[MAX_PATH];
365 UCHAR buffer[0x400];
366 PVOLUME_DISK_EXTENTS extents = (PVOLUME_DISK_EXTENTS)buffer;
367
368 _stprintf(uncpath, _TEXT("\\\\.\\%c:"), path.toAscii().at(0));
369 h = CreateFile(uncpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
370 NULL, OPEN_EXISTING, 0, NULL);
371 if(h == INVALID_HANDLE_VALUE) {
372 //qDebug() << "error getting extents for" << uncpath;
373 return "";
374 }
375 // get the extents
376 if(DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
377 NULL, 0, extents, sizeof(buffer), &written, NULL)) {
378 if(extents->NumberOfDiskExtents > 1) {
379 qDebug() << "volume spans multiple disks!";
380 return "";
381 }
382 //qDebug() << "Disk:" << extents->Extents[0].DiskNumber;
383 return QString("%1").arg(extents->Extents[0].DiskNumber);
320 } 384 }
321 if(!result.isEmpty())
322 return result + ":/";
323#endif 385#endif
324 return QString(""); 386 return QString("");
387
325} 388}
326 389
327 390
diff --git a/rbutil/rbutilqt/base/autodetection.h b/rbutil/rbutilqt/base/autodetection.h
index 7e6386cd5f..cffab5bd4f 100644
--- a/rbutil/rbutilqt/base/autodetection.h
+++ b/rbutil/rbutilqt/base/autodetection.h
@@ -42,6 +42,7 @@ public:
42 QString errdev(void) { return m_errdev; } 42 QString errdev(void) { return m_errdev; }
43 QString incompatdev(void) { return m_incompat; } 43 QString incompatdev(void) { return m_incompat; }
44 static QStringList mountpoints(void); 44 static QStringList mountpoints(void);
45 static QString resolveDevicename(QString path);
45 46
46private: 47private:
47 QString resolveMountPoint(QString); 48 QString resolveMountPoint(QString);
diff --git a/rbutil/rbutilqt/base/bootloaderinstallipod.cpp b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp
index 82c64954a6..e4a70e0cd6 100644
--- a/rbutil/rbutilqt/base/bootloaderinstallipod.cpp
+++ b/rbutil/rbutilqt/base/bootloaderinstallipod.cpp
@@ -22,6 +22,7 @@
22#include "bootloaderinstallipod.h" 22#include "bootloaderinstallipod.h"
23 23
24#include "../ipodpatcher/ipodpatcher.h" 24#include "../ipodpatcher/ipodpatcher.h"
25#include "autodetection.h"
25 26
26 27
27BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent) 28BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent)
@@ -36,7 +37,8 @@ BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent)
36 37
37BootloaderInstallIpod::~BootloaderInstallIpod() 38BootloaderInstallIpod::~BootloaderInstallIpod()
38{ 39{
39 free(ipod_sectorbuf); 40 if(ipod_sectorbuf)
41 free(ipod_sectorbuf);
40} 42}
41 43
42 44
@@ -198,12 +200,15 @@ BootloaderInstallBase::BootloaderType BootloaderInstallIpod::installed(void)
198 qDebug() << "BootloaderInstallIpod::installed(): BootloaderUnknown"; 200 qDebug() << "BootloaderInstallIpod::installed(): BootloaderUnknown";
199 result = BootloaderUnknown; 201 result = BootloaderUnknown;
200 } 202 }
201 else if (ipod.ipod_directory[0].entryOffset == 0) {
202 qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther";
203 result = BootloaderOther;
204 }
205 else { 203 else {
206 qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox"; 204 read_directory(&ipod);
205 if(ipod.ipod_directory[0].entryOffset == 0) {
206 qDebug() << "BootloaderInstallIpod::installed(): BootloaderOther";
207 result = BootloaderOther;
208 }
209 else {
210 qDebug() << "BootloaderInstallIpod::installed(): BootloaderRockbox";
211 }
207 } 212 }
208 ipod_close(&ipod); 213 ipod_close(&ipod);
209 214
@@ -219,20 +224,38 @@ BootloaderInstallBase::Capabilities BootloaderInstallIpod::capabilities(void)
219 224
220bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod) 225bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod)
221{ 226{
222 ipod_scan(ipod); 227 if(!m_blfile.isEmpty()) {
228#if defined(Q_OS_WIN32)
229 sprintf(ipod->diskname, "\\\\.\\PhysicalDrive%i",
230 Autodetection::resolveDevicename(m_blfile).toInt());
231#elif defined(Q_OS_MACX)
232 sprintf(ipod->diskname,
233 qPrintable(Autodetection::resolveDevicename(m_blfile)
234 .remove(QRegExp("s[0-9]+$"))));
235#else
236 sprintf(ipod->diskname,
237 qPrintable(Autodetection::resolveDevicename(m_blfile)
238 .remove(QRegExp("[0-9]+$"))));
239#endif
240 qDebug() << "ipodpatcher: overriding scan, using" << ipod->diskname;
241 }
242 else {
243 ipod_scan(ipod);
244 }
223 if(ipod_open(ipod, 0) < 0) { 245 if(ipod_open(ipod, 0) < 0) {
224 emit logItem(tr("Could not open Ipod"), LOGERROR); 246 emit logItem(tr("Could not open Ipod"), LOGERROR);
225 return false; 247 return false;
226 } 248 }
227 249
228 if(read_partinfo(ipod, 0) < 0) { 250 if(read_partinfo(ipod, 0) < 0) {
229 emit logItem(tr("Could not read partition table"), LOGERROR); 251 emit logItem(tr("Error reading partition table - possibly not an Ipod"), LOGERROR);
252 ipod_close(ipod);
230 return false; 253 return false;
231 } 254 }
232 255
233 if(ipod->pinfo[0].start == 0) { 256 if(ipod->pinfo[0].start == 0) {
234 emit logItem(tr("No firmware partition on disk"), LOGERROR); 257 emit logItem(tr("No firmware partition on disk"), LOGERROR);
235 258 ipod_close(ipod);
236 return false; 259 return false;
237 } 260 }
238 return true; 261 return true;
diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp
index 4679c2e9a8..aab298ce95 100644
--- a/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp
+++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.cpp
@@ -22,6 +22,7 @@
22#include "bootloaderinstallsansa.h" 22#include "bootloaderinstallsansa.h"
23 23
24#include "../sansapatcher/sansapatcher.h" 24#include "../sansapatcher/sansapatcher.h"
25#include "autodetection.h"
25 26
26BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) 27BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
27 : BootloaderInstallBase(parent) 28 : BootloaderInstallBase(parent)
@@ -36,7 +37,8 @@ BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
36 37
37BootloaderInstallSansa::~BootloaderInstallSansa() 38BootloaderInstallSansa::~BootloaderInstallSansa()
38{ 39{
39 free(sansa_sectorbuf); 40 if(sansa_sectorbuf)
41 free(sansa_sectorbuf);
40} 42}
41 43
42 44
@@ -80,30 +82,12 @@ bool BootloaderInstallSansa::install(void)
80void BootloaderInstallSansa::installStage2(void) 82void BootloaderInstallSansa::installStage2(void)
81{ 83{
82 struct sansa_t sansa; 84 struct sansa_t sansa;
83 sansa_scan(&sansa);
84 85
85 emit logItem(tr("Installing Rockbox bootloader"), LOGINFO); 86 emit logItem(tr("Installing Rockbox bootloader"), LOGINFO);
86 QCoreApplication::processEvents(); 87 QCoreApplication::processEvents();
87 88 if(!sansaInitialize(&sansa)) {
88 if(sansa_open(&sansa, 0) < 0) { 89 emit done(true);
89 emit logItem(tr("could not open Sansa"), LOGERROR); 90 return;
90 emit done(true);
91 return;
92 }
93
94 if(sansa_read_partinfo(&sansa, 0) < 0)
95 {
96 emit logItem(tr("could not read partitiontable"), LOGERROR);
97 emit done(true);
98 return;
99 }
100
101 int i = is_sansa(&sansa);
102 if(i < 0) {
103
104 emit logItem(tr("Disk is not a Sansa (Error: %1), aborting.").arg(i), LOGERROR);
105 emit done(true);
106 return;
107 } 91 }
108 92
109 if(sansa.hasoldbootloader) { 93 if(sansa.hasoldbootloader) {
@@ -169,27 +153,7 @@ bool BootloaderInstallSansa::uninstall(void)
169 emit logItem(tr("Uninstalling bootloader"), LOGINFO); 153 emit logItem(tr("Uninstalling bootloader"), LOGINFO);
170 QCoreApplication::processEvents(); 154 QCoreApplication::processEvents();
171 155
172 if(sansa_scan(&sansa) != 1) { 156 if(!sansaInitialize(&sansa)) {
173 emit logItem(tr("Can't find Sansa"), LOGERROR);
174 emit done(true);
175 return false;
176 }
177
178 if (sansa_open(&sansa, 0) < 0) {
179 emit logItem(tr("Could not open Sansa"), LOGERROR);
180 emit done(true);
181 return false;
182 }
183
184 if (sansa_read_partinfo(&sansa,0) < 0) {
185 emit logItem(tr("Could not read partition table"), LOGERROR);
186 emit done(true);
187 return false;
188 }
189
190 int i = is_sansa(&sansa);
191 if(i < 0) {
192 emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
193 emit done(true); 157 emit done(true);
194 return false; 158 return false;
195 } 159 }
@@ -235,18 +199,7 @@ BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
235 struct sansa_t sansa; 199 struct sansa_t sansa;
236 int num; 200 int num;
237 201
238 if(sansa_scan(&sansa) != 1) { 202 if(!sansaInitialize(&sansa)) {
239 return BootloaderUnknown;
240 }
241 if (sansa_open(&sansa, 0) < 0) {
242 return BootloaderUnknown;
243 }
244 if (sansa_read_partinfo(&sansa,0) < 0) {
245 sansa_close(&sansa);
246 return BootloaderUnknown;
247 }
248 if(is_sansa(&sansa) < 0) {
249 sansa_close(&sansa);
250 return BootloaderUnknown; 203 return BootloaderUnknown;
251 } 204 }
252 if((num = sansa_list_images(&sansa)) == 2) { 205 if((num = sansa_list_images(&sansa)) == 2) {
@@ -261,6 +214,43 @@ BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
261 214
262} 215}
263 216
217bool BootloaderInstallSansa::sansaInitialize(struct sansa_t *sansa)
218{
219 if(!m_blfile.isEmpty()) {
220#if defined(Q_OS_WIN32)
221 sprintf(sansa->diskname, "\\\\.\\PhysicalDrive%i",
222 Autodetection::resolveDevicename(m_blfile).toInt());
223#else
224 sprintf(sansa->diskname,
225 qPrintable(Autodetection::resolveDevicename(m_blfile).remove(QRegExp("[0-9]+$"))));
226#endif
227 qDebug() << "sansapatcher: overriding scan, using" << sansa->diskname;
228 }
229 else if(sansa_scan(sansa) != 1) {
230 emit logItem(tr("Can't find Sansa"), LOGERROR);
231 return false;
232 }
233
234 if (sansa_open(sansa, 0) < 0) {
235 emit logItem(tr("Could not open Sansa"), LOGERROR);
236 return false;
237 }
238
239 if (sansa_read_partinfo(sansa,0) < 0) {
240 emit logItem(tr("Could not read partition table"), LOGERROR);
241 sansa_close(sansa);
242 return false;
243 }
244
245 int i = is_sansa(sansa);
246 if(i < 0) {
247 emit logItem(tr("Disk is not a Sansa (Error %1), aborting.").arg(i), LOGERROR);
248 sansa_close(sansa);
249 return false;
250 }
251 return true;
252}
253
264 254
265/** Get capabilities of subclass installer. 255/** Get capabilities of subclass installer.
266 */ 256 */
diff --git a/rbutil/rbutilqt/base/bootloaderinstallsansa.h b/rbutil/rbutilqt/base/bootloaderinstallsansa.h
index a3911057a0..29eaa6d603 100644
--- a/rbutil/rbutilqt/base/bootloaderinstallsansa.h
+++ b/rbutil/rbutilqt/base/bootloaderinstallsansa.h
@@ -38,6 +38,7 @@ class BootloaderInstallSansa : public BootloaderInstallBase
38 Capabilities capabilities(void); 38 Capabilities capabilities(void);
39 39
40 private: 40 private:
41 bool sansaInitialize(struct sansa_t *);
41 42
42 private slots: 43 private slots:
43 void installStage2(void); 44 void installStage2(void);