diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2009-04-30 19:14:24 +0000 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2009-04-30 19:14:24 +0000 |
commit | f679cf91cf94363d10f99db5cbae872401ed5612 (patch) | |
tree | 8925a97c85a19c19a7979b464d0529dbd30dd430 /rbutil | |
parent | 549fc95b8d0f9ecfb6c18ad6c9a75503458e645d (diff) | |
download | rockbox-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
Diffstat (limited to 'rbutil')
-rw-r--r-- | rbutil/rbutilqt/base/autodetection.cpp | 115 | ||||
-rw-r--r-- | rbutil/rbutilqt/base/autodetection.h | 1 | ||||
-rw-r--r-- | rbutil/rbutilqt/base/bootloaderinstallipod.cpp | 41 | ||||
-rw-r--r-- | rbutil/rbutilqt/base/bootloaderinstallsansa.cpp | 100 | ||||
-rw-r--r-- | rbutil/rbutilqt/base/bootloaderinstallsansa.h | 1 |
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 | */ | ||
241 | QString Autodetection::resolveMountPoint(QString device) | 246 | QString 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 | */ | ||
316 | QString 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 | ||
46 | private: | 47 | private: |
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 | ||
27 | BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent) | 28 | BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent) |
@@ -36,7 +37,8 @@ BootloaderInstallIpod::BootloaderInstallIpod(QObject *parent) | |||
36 | 37 | ||
37 | BootloaderInstallIpod::~BootloaderInstallIpod() | 38 | BootloaderInstallIpod::~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 | ||
220 | bool BootloaderInstallIpod::ipodInitialize(struct ipod_t *ipod) | 225 | bool 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 | ||
26 | BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) | 27 | BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) |
27 | : BootloaderInstallBase(parent) | 28 | : BootloaderInstallBase(parent) |
@@ -36,7 +37,8 @@ BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent) | |||
36 | 37 | ||
37 | BootloaderInstallSansa::~BootloaderInstallSansa() | 38 | BootloaderInstallSansa::~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) | |||
80 | void BootloaderInstallSansa::installStage2(void) | 82 | void 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 | ||
217 | bool 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); |