1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Wenger
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "autodetection.h"
22 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
26 #if defined(Q_OS_LINUX)
29 #if defined(Q_OS_MACX)
30 #include <sys/param.h>
31 #include <sys/ucred.h>
32 #include <sys/mount.h>
34 #if defined(Q_OS_WIN32)
45 Autodetection::Autodetection(QObject
* parent
): QObject(parent
)
50 bool Autodetection::detect()
58 // Try detection via rockbox.info / rbutil.log
59 QStringList mountpoints
= getMountpoints();
61 for(int i
=0; i
< mountpoints
.size();i
++)
63 // do the file checking
64 QDir
dir(mountpoints
.at(i
));
67 qDebug() << "file checking:" << mountpoints
.at(i
);
68 // check logfile first.
69 if(QFile(mountpoints
.at(i
) + "/.rockbox/rbutil.log").exists()) {
70 QSettings
log(mountpoints
.at(i
) + "/.rockbox/rbutil.log",
71 QSettings::IniFormat
, this);
72 if(!log
.value("platform").toString().isEmpty()) {
73 if(m_device
.isEmpty())
74 m_device
= log
.value("platform").toString();
75 m_mountpoint
= mountpoints
.at(i
);
76 qDebug() << "rbutil.log detected:" << m_device
<< m_mountpoint
;
81 // check rockbox-info.txt afterwards.
82 QFile
file(mountpoints
.at(i
) + "/.rockbox/rockbox-info.txt");
85 file
.open(QIODevice::ReadOnly
| QIODevice::Text
);
86 QString line
= file
.readLine();
87 if(line
.startsWith("Target: "))
89 line
.remove("Target: ");
90 if(m_device
.isEmpty())
91 m_device
= line
.trimmed(); // trim whitespaces
92 m_mountpoint
= mountpoints
.at(i
);
93 qDebug() << "rockbox-info.txt detected:" << m_device
<< m_mountpoint
;
97 // check for some specific files in root folder
98 QDir
root(mountpoints
.at(i
));
99 QStringList rootentries
= root
.entryList(QDir::Files
);
100 if(rootentries
.contains("archos.mod", Qt::CaseInsensitive
))
102 // archos.mod in root folder -> Archos Player
104 m_mountpoint
= mountpoints
.at(i
);
107 if(rootentries
.contains("ONDIOST.BIN", Qt::CaseInsensitive
))
109 // ONDIOST.BIN in root -> Ondio FM
110 m_device
= "ondiofm";
111 m_mountpoint
= mountpoints
.at(i
);
114 if(rootentries
.contains("ONDIOSP.BIN", Qt::CaseInsensitive
))
116 // ONDIOSP.BIN in root -> Ondio SP
117 m_device
= "ondiosp";
118 m_mountpoint
= mountpoints
.at(i
);
121 if(rootentries
.contains("ajbrec.ajz", Qt::CaseInsensitive
))
123 qDebug() << "ajbrec.ajz found. Trying detectAjbrec()";
124 if(detectAjbrec(mountpoints
.at(i
))) {
125 m_mountpoint
= mountpoints
.at(i
);
126 qDebug() << m_device
;
130 // detection based on player specific folders
131 QStringList rootfolders
= root
.entryList(QDir::Dirs
132 | QDir::NoDotAndDotDot
| QDir::Hidden
| QDir::System
);
133 if(rootfolders
.contains("GBSYSTEM", Qt::CaseInsensitive
))
135 // GBSYSTEM folder -> Gigabeat
136 m_device
= "gigabeatf";
137 m_mountpoint
= mountpoints
.at(i
);
140 #if defined(Q_OS_WIN32)
141 // on windows, try to detect the drive letter of an Ipod
142 if(rootfolders
.contains("iPod_Control", Qt::CaseInsensitive
))
144 // iPod_Control folder -> Ipod found
145 // detecting of the Ipod type is done below using ipodpatcher
146 m_mountpoint
= mountpoints
.at(i
);
156 n
= ipod_scan(&ipod
);
158 qDebug() << "Ipod found:" << ipod
.modelstr
<< "at" << ipod
.diskname
;
159 m_device
= ipod
.targetname
;
160 #if !defined(Q_OS_WIN32)
161 m_mountpoint
= resolveMountPoint(ipod
.diskname
);
163 #if defined(Q_OS_WIN32)
164 m_mountpoint
= getMountpointByDevice(ipod
.diskname
);
170 struct sansa_t sansa
;
171 n
= sansa_scan(&sansa
);
173 qDebug() << "Sansa found:" << sansa
.targetname
<< "at" << sansa
.diskname
;
174 m_device
= QString("sansa%1").arg(sansa
.targetname
);
175 #if !defined(Q_OS_WIN32)
176 m_mountpoint
= resolveMountPoint(sansa
.diskname
);
178 #if defined(Q_OS_WIN32)
179 m_mountpoint
= getMountpointByDevice(sansa
.diskname
);
184 if(m_mountpoint
.isEmpty() && m_device
.isEmpty() && m_errdev
.isEmpty() && m_incompat
.isEmpty())
190 QStringList
Autodetection::getMountpoints()
192 QStringList tempList
;
193 #if defined(Q_OS_WIN32)
194 QFileInfoList list
= QDir::drives();
195 for(int i
=0; i
<list
.size();i
++)
197 tempList
<< list
.at(i
).absolutePath();
200 #elif defined(Q_OS_MACX)
202 struct statfs
*mntinf
;
204 num
= getmntinfo(&mntinf
, MNT_WAIT
);
206 tempList
<< QString(mntinf
->f_mntonname
);
209 #elif defined(Q_OS_LINUX)
211 FILE *mn
= setmntent("/etc/mtab", "r");
213 return QStringList("");
216 while((ent
= getmntent(mn
)))
217 tempList
<< QString(ent
->mnt_dir
);
221 #error Unknown Plattform
226 QString
Autodetection::resolveMountPoint(QString device
)
228 qDebug() << "Autodetection::resolveMountPoint(QString)" << device
;
230 #if defined(Q_OS_LINUX)
231 FILE *mn
= setmntent("/etc/mtab", "r");
236 while((ent
= getmntent(mn
))) {
237 if(QString(ent
->mnt_fsname
).startsWith(device
)
238 && QString(ent
->mnt_type
).contains("vfat", Qt::CaseInsensitive
)) {
240 return QString(ent
->mnt_dir
);
247 #if defined(Q_OS_MACX)
249 struct statfs
*mntinf
;
251 num
= getmntinfo(&mntinf
, MNT_WAIT
);
253 if(QString(mntinf
->f_mntfromname
).startsWith(device
)
254 && QString(mntinf
->f_fstypename
).contains("vfat", Qt::CaseInsensitive
))
255 return QString(mntinf
->f_mntonname
);
264 /** @brief detect devices based on usb pid / vid.
265 * @return true upon success, false otherwise.
267 bool Autodetection::detectUsb()
269 // usbids holds the mapping in the form
270 // ((VID<<16)|(PID)), targetname
271 // the ini file needs to hold the IDs as hex values.
272 QMap
<int, QString
> usbids
= settings
->usbIdMap();
273 QMap
<int, QString
> usberror
= settings
->usbIdErrorMap();
274 QMap
<int, QString
> usbincompat
= settings
->usbIdIncompatMap();
277 QList
<uint32_t> attached
;
278 attached
= Detect::listUsbIds();
280 int i
= attached
.size();
282 if(usbids
.contains(attached
.at(i
))) {
283 m_device
= usbids
.value(attached
.at(i
));
284 qDebug() << "[USB] detected supported player" << m_device
;
287 if(usberror
.contains(attached
.at(i
))) {
288 m_errdev
= usberror
.value(attached
.at(i
));
289 qDebug() << "[USB] detected problem with player" << m_errdev
;
292 if(usbincompat
.contains(attached
.at(i
))) {
293 m_incompat
= usbincompat
.value(attached
.at(i
));
294 qDebug() << "[USB] detected incompatible player" << m_incompat
;
302 bool Autodetection::detectAjbrec(QString root
)
304 QFile
f(root
+ "/ajbrec.ajz");
306 f
.open(QIODevice::ReadOnly
);
307 if(!f
.read(header
, 24)) return false;
309 // check the header of the file.
310 // recorder v1 had a 6 bytes sized header
311 // recorder v2, FM, Ondio SP and FM have a 24 bytes header.
313 // recorder v1 has the binary length in the first 4 bytes, so check
315 int len
= (header
[0]<<24) | (header
[1]<<16) | (header
[2]<<8) | header
[3];
316 qDebug() << "possible bin length:" << len
;
317 qDebug() << "file len:" << f
.size();
318 if((f
.size() - 6) == len
)
319 m_device
= "recorder";
321 // size didn't match, now we need to assume we have a headerlength of 24.
324 m_device
= "recorderv2";
328 m_device
= "fmrecorder";
332 m_device
= "ondiofm";
336 m_device
= "ondiosp";
344 if(m_device
.isEmpty()) return false;