summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rbutil/rbutilqt/base/autodetection.cpp391
-rw-r--r--rbutil/rbutilqt/base/autodetection.h17
2 files changed, 260 insertions, 148 deletions
diff --git a/rbutil/rbutilqt/base/autodetection.cpp b/rbutil/rbutilqt/base/autodetection.cpp
index de3765ffb1..2d7476502a 100644
--- a/rbutil/rbutilqt/base/autodetection.cpp
+++ b/rbutil/rbutilqt/base/autodetection.cpp
@@ -33,20 +33,101 @@ Autodetection::Autodetection(QObject* parent): QObject(parent)
33{ 33{
34} 34}
35 35
36bool Autodetection::detect() 36
37bool Autodetection::detect(void)
37{ 38{
38 m_device = ""; 39 QMap<PlayerStatus, QString> states;
39 m_mountpoint = ""; 40 states[PlayerOk] = "Ok";
40 m_errdev = ""; 41 states[PlayerAmbiguous] = "Ambiguous";
41 m_usberr = ""; 42 states[PlayerError] = "Error";
43 states[PlayerIncompatible] = "Incompatible";
44 states[PlayerMtpMode] = "MtpMode";
45
46 // clear detection state
47 m_detected.clear();
42 48
43 detectUsb(); 49 detectUsb();
50 mergeMounted();
51 mergePatcher();
52 // if any entry with usbdevices containing a value is left that entry
53 // hasn't been merged later. This indicates a problem during detection
54 // (ambiguous player but refining it failed). In this case create an entry
55 // for eacho of those so the user can select.
56 for(int i = 0; i < m_detected.size(); ++i) {
57 int j = m_detected.at(i).usbdevices.size();
58 if(j > 0) {
59 struct Detected entry = m_detected.takeAt(i);
60 while(j--) {
61 struct Detected d;
62 d.device = entry.usbdevices.at(j);
63 d.mountpoint = entry.mountpoint;
64 d.status = PlayerAmbiguous;
65 m_detected.append(d);
66 }
67 }
68 }
69 for(int i = 0; i < m_detected.size(); ++i) {
70 qDebug() << "[Autodetect] Detected player:" << m_detected.at(i).device
71 << "at" << m_detected.at(i).mountpoint << states[m_detected.at(i).status];
72 }
73
74 return m_detected.size() > 0;
75}
76
77
78/** @brief detect devices based on usb pid / vid.
79 */
80void Autodetection::detectUsb()
81{
82 // usbids holds the mapping in the form
83 // ((VID<<16)|(PID)), targetname
84 // the ini file needs to hold the IDs as hex values.
85 QMap<int, QStringList> usbids = SystemInfo::usbIdMap(SystemInfo::MapDevice);
86 QMap<int, QStringList> usberror = SystemInfo::usbIdMap(SystemInfo::MapError);
87 QMap<int, QStringList> usbincompat = SystemInfo::usbIdMap(SystemInfo::MapIncompatible);
88
89 // usb pid detection
90 QList<uint32_t> attached;
91 attached = System::listUsbIds();
44 92
45 // Try detection via rockbox.info / rbutil.log 93 int i = attached.size();
94 while(i--) {
95 if(usbids.contains(attached.at(i))) {
96 // we found a USB device that might be ambiguous.
97 struct Detected d;
98 d.status = PlayerOk;
99 d.usbdevices = usbids.value(attached.at(i));
100 m_detected.append(d);
101 qDebug() << "[USB] detected supported player" << d.usbdevices;
102 }
103 if(usberror.contains(attached.at(i))) {
104 struct Detected d;
105 d.status = PlayerMtpMode;
106 d.device = usbids.value(attached.at(i)).at(0);
107 m_detected.append(d);
108 qDebug() << "[USB] detected problem with player" << d.device;
109 }
110 QString idstring = QString("%1").arg(attached.at(i), 8, 16, QChar('0'));
111 if(!SystemInfo::platformValue(idstring, SystemInfo::CurName).toString().isEmpty()) {
112 struct Detected d;
113 d.status = PlayerIncompatible;
114 d.device = idstring;
115 m_detected.append(d);
116 qDebug() << "[USB] detected incompatible player" << d.device;
117 }
118 }
119}
120
121
122// Merge players detected by checking mounted filesystems for known files:
123// - rockbox-info.txt / rbutil.log
124// - player specific files
125void Autodetection::mergeMounted(void)
126{
46 QStringList mounts = Utils::mountpoints(Utils::MountpointsSupported); 127 QStringList mounts = Utils::mountpoints(Utils::MountpointsSupported);
47 qDebug() << "[Autodetect] paths to check:" << mounts; 128 qDebug() << "[Autodetect] paths to check:" << mounts;
48 129
49 for(int i=0; i< mounts.size();i++) 130 for(int i = 0; i < mounts.size(); i++)
50 { 131 {
51 // do the file checking 132 // do the file checking
52 QDir dir(mounts.at(i)); 133 QDir dir(mounts.at(i));
@@ -57,11 +138,20 @@ bool Autodetection::detect()
57 QSettings log(mounts.at(i) + "/.rockbox/rbutil.log", 138 QSettings log(mounts.at(i) + "/.rockbox/rbutil.log",
58 QSettings::IniFormat, this); 139 QSettings::IniFormat, this);
59 if(!log.value("platform").toString().isEmpty()) { 140 if(!log.value("platform").toString().isEmpty()) {
60 if(m_device.isEmpty()) 141 int index = findDetectedDevice(log.value("platform").toString());
61 m_device = log.value("platform").toString(); 142 struct Detected d;
62 m_mountpoint = mounts.at(i); 143 d.device = log.value("platform").toString();
63 qDebug() << "[Autodetect] rbutil.log detected:" << m_device << m_mountpoint; 144 d.mountpoint = mounts.at(i);
64 return true; 145 d.status = PlayerOk;
146 if(index < 0) {
147 m_detected.append(d);
148 }
149 else {
150 m_detected.takeAt(index);
151 m_detected.append(d);
152 }
153 qDebug() << "[Autodetect] rbutil.log detected:"
154 << log.value("platform").toString() << mounts.at(i);
65 } 155 }
66 } 156 }
67 157
@@ -69,14 +159,20 @@ bool Autodetection::detect()
69 RockboxInfo info(mounts.at(i)); 159 RockboxInfo info(mounts.at(i));
70 if(info.success()) 160 if(info.success())
71 { 161 {
72 if(m_device.isEmpty()) 162 int index = findDetectedDevice(info.target());
73 { 163 struct Detected d;
74 m_device = info.target(); 164 d.device = info.target();
165 d.mountpoint = mounts.at(i);
166 d.status = PlayerOk;
167 if(index < 0) {
168 m_detected.append(d);
169 }
170 else {
171 m_detected.takeAt(index);
172 m_detected.append(d);
75 } 173 }
76 m_mountpoint = mounts.at(i);
77 qDebug() << "[Autodetect] rockbox-info.txt detected:" 174 qDebug() << "[Autodetect] rockbox-info.txt detected:"
78 << m_device << m_mountpoint; 175 << info.target() << mounts.at(i);
79 return true;
80 } 176 }
81 177
82 // check for some specific files in root folder 178 // check for some specific files in root folder
@@ -85,31 +181,61 @@ bool Autodetection::detect()
85 if(rootentries.contains("archos.mod", Qt::CaseInsensitive)) 181 if(rootentries.contains("archos.mod", Qt::CaseInsensitive))
86 { 182 {
87 // archos.mod in root folder -> Archos Player 183 // archos.mod in root folder -> Archos Player
88 m_device = "player"; 184 struct Detected d;
89 m_mountpoint = mounts.at(i); 185 d.device = "player";
90 return true; 186 d.mountpoint = mounts.at(i);
187 d.status = PlayerOk;
188 m_detected.append(d);
91 } 189 }
92 if(rootentries.contains("ONDIOST.BIN", Qt::CaseInsensitive)) 190 if(rootentries.contains("ONDIOST.BIN", Qt::CaseInsensitive))
93 { 191 {
94 // ONDIOST.BIN in root -> Ondio FM 192 // ONDIOST.BIN in root -> Ondio FM
95 m_device = "ondiofm"; 193 struct Detected d;
96 m_mountpoint = mounts.at(i); 194 d.device = "ondiofm";
97 return true; 195 d.mountpoint = mounts.at(i);
196 d.status = PlayerOk;
197 int index = findDetectedDevice("ondiofm");
198 if(index < 0) {
199 m_detected.append(d);
200 }
201 else {
202 m_detected.takeAt(index);
203 m_detected.append(d);
204 }
98 } 205 }
99 if(rootentries.contains("ONDIOSP.BIN", Qt::CaseInsensitive)) 206 if(rootentries.contains("ONDIOSP.BIN", Qt::CaseInsensitive))
100 { 207 {
101 // ONDIOSP.BIN in root -> Ondio SP 208 // ONDIOSP.BIN in root -> Ondio SP
102 m_device = "ondiosp"; 209 struct Detected d;
103 m_mountpoint = mounts.at(i); 210 d.device = "ondiosp";
104 return true; 211 d.mountpoint = mounts.at(i);
212 d.status = PlayerOk;
213 int index = findDetectedDevice("ondiosp");
214 if(index < 0) {
215 m_detected.append(d);
216 }
217 else {
218 m_detected.takeAt(index);
219 m_detected.append(d);
220 }
105 } 221 }
106 if(rootentries.contains("ajbrec.ajz", Qt::CaseInsensitive)) 222 if(rootentries.contains("ajbrec.ajz", Qt::CaseInsensitive))
107 { 223 {
108 qDebug() << "[Autodetect] ajbrec.ajz found. Trying detectAjbrec()"; 224 qDebug() << "[Autodetect] ajbrec.ajz found. Trying detectAjbrec()";
109 if(detectAjbrec(mounts.at(i))) { 225 struct Detected d;
110 m_mountpoint = mounts.at(i); 226 d.device = detectAjbrec(mounts.at(i));
111 qDebug() << "[Autodetect]" << m_device; 227 d.mountpoint = mounts.at(i);
112 return true; 228 d.status = PlayerOk;
229 if(!d.device.isEmpty()) {
230 qDebug() << "[Autodetect]" << d.device;
231 int index = findDetectedDevice("ondiosp");
232 if(index < 0) {
233 m_detected.append(d);
234 }
235 else {
236 m_detected.takeAt(index);
237 m_detected.append(d);
238 }
113 } 239 }
114 } 240 }
115 // detection based on player specific folders 241 // detection based on player specific folders
@@ -118,23 +244,50 @@ bool Autodetection::detect()
118 if(rootfolders.contains("GBSYSTEM", Qt::CaseInsensitive)) 244 if(rootfolders.contains("GBSYSTEM", Qt::CaseInsensitive))
119 { 245 {
120 // GBSYSTEM folder -> Gigabeat 246 // GBSYSTEM folder -> Gigabeat
121 m_device = "gigabeatf"; 247 struct Detected d;
122 m_mountpoint = mounts.at(i); 248 d.device = "gigabeatf";
123 return true; 249 d.mountpoint = mounts.at(i);
250 int index = findDetectedDevice("ondiosp");
251 if(index < 0) {
252 m_detected.append(d);
253 }
254 else {
255 m_detected.takeAt(index);
256 m_detected.append(d);
257 }
124 } 258 }
125#if defined(Q_OS_WIN32) 259 }
126 // on windows, try to detect the drive letter of an Ipod 260 }
127 if(rootfolders.contains("iPod_Control", Qt::CaseInsensitive)) 261#if 0
128 { 262 // Ipods have a folder "iPod_Control" in the root.
129 // iPod_Control folder -> Ipod found 263 for(int i = 0; i < m_detected.size(); ++i) {
130 // detecting of the Ipod type is done below using ipodpatcher 264 struct Detected entry = m_detected.at(i);
131 m_mountpoint = mounts.at(i); 265 for(int j = 0; j < entry.usbdevices.size(); ++j) {
266 // limit this to Ipods only.
267 if(!entry.usbdevices.at(j).startsWith("ipod")
268 && !entry.device.startsWith("ipod")) {
269 continue;
270 }
271 // look for iPod_Control on all supported volumes.
272 for(int k = 0; k < mounts.size(); k++) {
273 QDir root(mounts.at(k));
274 QStringList rootfolders = root.entryList(QDir::Dirs
275 | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
276 if(rootfolders.contains("iPod_Control", Qt::CaseInsensitive)) {
277 entry.mountpoint = mounts.at(k);
278 m_detected.takeAt(i);
279 m_detected.append(entry);
280 }
132 } 281 }
133#endif
134 } 282 }
135
136 } 283 }
284#endif
137 285
286}
287
288
289void Autodetection::mergePatcher(void)
290{
138 int n; 291 int n;
139 // try ipodpatcher 292 // try ipodpatcher
140 // initialize sector buffer. Needed. 293 // initialize sector buffer. Needed.
@@ -142,13 +295,9 @@ bool Autodetection::detect()
142 ipod.sectorbuf = NULL; 295 ipod.sectorbuf = NULL;
143 ipod_alloc_buffer(&ipod, BUFFER_SIZE); 296 ipod_alloc_buffer(&ipod, BUFFER_SIZE);
144 n = ipod_scan(&ipod); 297 n = ipod_scan(&ipod);
298 // FIXME: handle more than one Ipod connected in ipodpatcher.
145 if(n == 1) { 299 if(n == 1) {
146 qDebug() << "[Autodetect] Ipod found:" << ipod.modelstr << "at" << ipod.diskname; 300 qDebug() << "[Autodetect] Ipod found:" << ipod.modelstr << "at" << ipod.diskname;
147 // if the found ipod is a macpod also notice it as device with problem.
148 if(ipod.macpod)
149 m_errdev = ipod.targetname;
150 else
151 m_device = ipod.targetname;
152 // since resolveMountPoint is doing exact matches we need to select 301 // since resolveMountPoint is doing exact matches we need to select
153 // the correct partition. 302 // the correct partition.
154 QString mp(ipod.diskname); 303 QString mp(ipod.diskname);
@@ -158,8 +307,22 @@ bool Autodetection::detect()
158#ifdef Q_OS_MACX 307#ifdef Q_OS_MACX
159 mp.append("s2"); 308 mp.append("s2");
160#endif 309#endif
161 m_mountpoint = Utils::resolveMountPoint(mp); 310 struct Detected d;
162 return true; 311 d.device = ipod.targetname;
312 d.mountpoint = Utils::resolveMountPoint(mp);
313 // if the found ipod is a macpod also notice it as device with problem.
314 if(ipod.macpod)
315 d.status = PlayerWrongFilesystem;
316 else
317 d.status = PlayerOk;
318 int index = findDetectedDevice(ipod.targetname);
319 if(index < 0) {
320 m_detected.append(d);
321 }
322 else {
323 m_detected.takeAt(index);
324 m_detected.append(d);
325 }
163 } 326 }
164 else { 327 else {
165 qDebug() << "[Autodetect] ipodpatcher: no Ipod found." << n; 328 qDebug() << "[Autodetect] ipodpatcher: no Ipod found." << n;
@@ -172,8 +335,8 @@ bool Autodetection::detect()
172 sansa_alloc_buffer(&sansa, BUFFER_SIZE); 335 sansa_alloc_buffer(&sansa, BUFFER_SIZE);
173 n = sansa_scan(&sansa); 336 n = sansa_scan(&sansa);
174 if(n == 1) { 337 if(n == 1) {
175 qDebug() << "[Autodetect] Sansa found:" << sansa.targetname << "at" << sansa.diskname; 338 qDebug() << "[Autodetect] Sansa found:"
176 m_device = QString("sansa%1").arg(sansa.targetname); 339 << sansa.targetname << "at" << sansa.diskname;
177 QString mp(sansa.diskname); 340 QString mp(sansa.diskname);
178#ifdef Q_OS_LINUX 341#ifdef Q_OS_LINUX
179 mp.append("1"); 342 mp.append("1");
@@ -181,97 +344,33 @@ bool Autodetection::detect()
181#ifdef Q_OS_MACX 344#ifdef Q_OS_MACX
182 mp.append("s1"); 345 mp.append("s1");
183#endif 346#endif
184 m_mountpoint = Utils::resolveMountPoint(mp); 347 struct Detected d;
185 return true; 348 d.device = QString("sansa%1").arg(sansa.targetname);
349 d.mountpoint = Utils::resolveMountPoint(mp);
350 d.status = PlayerOk;
351 int index = findDetectedDevice(d.device);
352 if(index < 0) {
353 m_detected.append(d);
354 }
355 else {
356 m_detected.takeAt(index);
357 m_detected.append(d);
358 }
186 } 359 }
187 else { 360 else {
188 qDebug() << "[Autodetect] sansapatcher: no Sansa found." << n; 361 qDebug() << "[Autodetect] sansapatcher: no Sansa found." << n;
189 } 362 }
190 sansa_dealloc_buffer(&sansa); 363 sansa_dealloc_buffer(&sansa);
191
192 if(m_mountpoint.isEmpty() && m_device.isEmpty()
193 && m_errdev.isEmpty() && m_incompat.isEmpty())
194 return false;
195 return true;
196}
197
198
199/** @brief detect devices based on usb pid / vid.
200 * @return true upon success, false otherwise.
201 */
202bool Autodetection::detectUsb()
203{
204 // usbids holds the mapping in the form
205 // ((VID<<16)|(PID)), targetname
206 // the ini file needs to hold the IDs as hex values.
207 QMap<int, QStringList> usbids = SystemInfo::usbIdMap(SystemInfo::MapDevice);
208 QMap<int, QStringList> usberror = SystemInfo::usbIdMap(SystemInfo::MapError);
209 QMap<int, QStringList> usbincompat = SystemInfo::usbIdMap(SystemInfo::MapIncompatible);
210
211 // usb pid detection
212 QList<uint32_t> attached;
213 attached = System::listUsbIds();
214
215 int i = attached.size();
216 while(i--) {
217 if(usbids.contains(attached.at(i))) {
218 m_device = usbids.value(attached.at(i)).at(0);
219 qDebug() << "[USB] detected supported player" << m_device;
220 return true;
221 }
222 if(usberror.contains(attached.at(i))) {
223 m_usberr = usberror.value(attached.at(i)).at(0);
224 qDebug() << "[USB] detected problem with player" << m_usberr;
225 return true;
226 }
227 QString idstring = QString("%1").arg(attached.at(i), 8, 16, QChar('0'));
228 if(!SystemInfo::platformValue(idstring, SystemInfo::CurName).toString().isEmpty()) {
229 m_incompat = idstring;
230 qDebug() << "[USB] detected incompatible player" << m_incompat;
231 return true;
232 }
233 }
234 return false;
235} 364}
236 365
237 366
238QList<struct Autodetection::Detected> Autodetection::detected(void) 367QString Autodetection::detectAjbrec(QString root)
239{
240 struct Detected d;
241
242 m_detected.clear();
243 if(!m_device.isEmpty()) {
244 d.device = m_device;
245 d.mountpoint = m_mountpoint;
246 d.status = PlayerOk;
247 m_detected.append(d);
248 }
249 else if(!m_errdev.isEmpty()) {
250 d.device = m_errdev;
251 d.status = PlayerWrongFilesystem;
252 m_detected.append(d);
253 }
254 else if(!m_usberr.isEmpty()) {
255 d.device = m_usberr;
256 d.status = PlayerMtpMode;
257 m_detected.append(d);
258 }
259 else if(!m_incompat.isEmpty()) {
260 d.device = m_incompat;
261 d.status = PlayerIncompatible;
262 m_detected.append(d);
263 }
264
265 return m_detected;
266}
267
268
269bool Autodetection::detectAjbrec(QString root)
270{ 368{
271 QFile f(root + "/ajbrec.ajz"); 369 QFile f(root + "/ajbrec.ajz");
272 char header[24]; 370 char header[24];
273 f.open(QIODevice::ReadOnly); 371 f.open(QIODevice::ReadOnly);
274 if(!f.read(header, 24)) return false; 372 if(!f.read(header, 24)) return QString();
373 f.close();
275 374
276 // check the header of the file. 375 // check the header of the file.
277 // recorder v1 had a 6 bytes sized header 376 // recorder v1 had a 6 bytes sized header
@@ -283,32 +382,44 @@ bool Autodetection::detectAjbrec(QString root)
283 qDebug() << "[Autodetect] ABJREC possible bin length:" << len 382 qDebug() << "[Autodetect] ABJREC possible bin length:" << len
284 << "file len:" << f.size(); 383 << "file len:" << f.size();
285 if((f.size() - 6) == len) 384 if((f.size() - 6) == len)
286 m_device = "recorder"; 385 return "recorder";
287 386
288 // size didn't match, now we need to assume we have a headerlength of 24. 387 // size didn't match, now we need to assume we have a headerlength of 24.
289 switch(header[11]) { 388 switch(header[11]) {
290 case 2: 389 case 2:
291 m_device = "recorderv2"; 390 return "recorderv2";
292 break; 391 break;
293 392
294 case 4: 393 case 4:
295 m_device = "fmrecorder"; 394 return "fmrecorder";
296 break; 395 break;
297 396
298 case 8: 397 case 8:
299 m_device = "ondiofm"; 398 return "ondiofm";
300 break; 399 break;
301 400
302 case 16: 401 case 16:
303 m_device = "ondiosp"; 402 return "ondiosp";
304 break; 403 break;
305 404
306 default: 405 default:
307 break; 406 break;
308 } 407 }
309 f.close(); 408 return QString();
310
311 if(m_device.isEmpty()) return false;
312 return true;
313} 409}
314 410
411
412int Autodetection::findDetectedDevice(QString device)
413{
414 int i = m_detected.size();
415 while(i--) {
416 if(m_detected.at(i).usbdevices.contains(device))
417 return i;
418 }
419 i = m_detected.size();
420 while(i--) {
421 if(m_detected.at(i).device == device)
422 return i;
423 }
424 return -1;
425}
diff --git a/rbutil/rbutilqt/base/autodetection.h b/rbutil/rbutilqt/base/autodetection.h
index 65a24abb8f..c3c7fc9168 100644
--- a/rbutil/rbutilqt/base/autodetection.h
+++ b/rbutil/rbutilqt/base/autodetection.h
@@ -25,6 +25,7 @@
25#include <QObject> 25#include <QObject>
26#include <QString> 26#include <QString>
27#include <QList> 27#include <QList>
28#include <QStringList>
28 29
29class Autodetection :public QObject 30class Autodetection :public QObject
30{ 31{
@@ -39,29 +40,29 @@ public:
39 PlayerMtpMode, 40 PlayerMtpMode,
40 PlayerWrongFilesystem, 41 PlayerWrongFilesystem,
41 PlayerError, 42 PlayerError,
43 PlayerAmbiguous,
42 }; 44 };
43 45
44 struct Detected { 46 struct Detected {
45 QString device; 47 QString device;
48 QStringList usbdevices;
46 QString mountpoint; 49 QString mountpoint;
47 enum PlayerStatus status; 50 enum PlayerStatus status;
48 }; 51 };
49 52
50 bool detect(); 53 bool detect();
51 54
52 QList<struct Detected> detected(void); 55 QList<struct Detected> detected(void) { return m_detected; }
53 56
54private: 57private:
55 QString resolveMountPoint(QString); 58 QString resolveMountPoint(QString);
56 bool detectUsb(void); 59 void detectUsb(void);
57 bool detectAjbrec(QString); 60 void mergeMounted(void);
61 void mergePatcher(void);
62 QString detectAjbrec(QString);
63 int findDetectedDevice(QString device);
58 64
59 QList<struct Detected> m_detected; 65 QList<struct Detected> m_detected;
60 QString m_device;
61 QString m_mountpoint;
62 QString m_errdev;
63 QString m_usberr;
64 QString m_incompat;
65 QList<int> m_usbconid; 66 QList<int> m_usbconid;
66}; 67};
67 68