Closed ikarus23 closed 9 years ago
Output of a device with Mifare Classic support (Nexus 7 2012):
shell@grouper:/ $ ls /system/lib/libnfc*
/system/lib/libnfc.so
/system/lib/libnfc_jni.so
/system/lib/libnfc_ndef.so
Regarding the second approach: Checking /dev/*
is not possible without root...
Another approach:
try {
Class.forName( "android.nfc.tech.MifareClassic" );
} catch( ClassNotFoundException e ) {
// Class not found. Devices does not support Mifare Classic.
}
Devices with no MFC support should have no MifareClassic class.
Here is a testing version of MCT that will check for the class android.nfc.tech.MifareClassic
on startup. For devices with no Mifare Classic support there should be an error message saying "This device does not support Mifare Classic!".
Umm... Output of mine /system/lib is:
D:\lg\f60\system>adb shell ls /system/lib/libnfc*
/system/lib/libnfc-brcm-nci.so
/system/lib/libnfc_ndef.so
And I have non-rooted LG F60, and from ADB I can ls /dev/ directory without problem... And from Terminal Emulator too.
Hmm...
I have a rooted Nexus 7 (2012) but without root I can't read /dev
. Not via adb and not via Terminal Emulator. I think I will first check for the class and than fallback to the /system/lib/libnfc*
. It should be enough, even without checking /dev
.
Have you tried the testing version of MCT from my previous post?
Hmm weird thing...
And I forgot to write, I've tried, but didn't get any message about incompability on start.
Now I get it. There has been another misunderstanding. You thought your device has no MifareClassic class because the TagInfo app displayed no "MifareClassic" in "Target technology classes". What this app does is to show the result of Tag.getTechList(). In this list you can see all the technologies the tag and the phone share. But if MifareClassic is not in that list, it does not mean your device don't has this class. It just means that your device and the tag can not communicate via MifareClassic.
In other words: it is pretty much useless to check for the existence of the MifareClassic class.
I created another test version of MCT that checks the /system/lib/libnfc*
for libs that have "brcm" in its name. Please try it.
Yup, now I correctly get warning that your app is something like useless for my phone :) I think it will be good enough to just check for this libs, and if there will be any other chip that doesn't support mifare you'll just add its driver to checklist :) And just add LG F60, G2 mini and G3s to incompability list in readme - my friends have these and I've checked that they have Broadcomm too :)
Thank you very much! I will update the incompatibility list and close this issue at the time the new MFC support check algorithm is pushed.
Done. See: 3d752037efada14e885029efef518896345078b6
This is Nexus 4 with CyanogenMod:
shell@mako:/ $ ls /system/lib/libnfc*
/system/lib/libnfc-nci.so
/system/lib/libnfc_nci_jni.so
/system/lib/libnfc_ndef.so
Also I can list /dev
even without root permissions.
shell@mako:/ $ ls /dev/bcm*
/dev/bcm2079x-i2c
So, I think, it does make sense to try to list /dev
and then fall back to the /system/lib
method if there are not enough permissions.
Thanks for the info.
So, I think, it does make sense to try to list /dev and then fall back to the /system/lib method if there are not enough permissions.
Yep, in this case it makes perfectly sens. I will alter the support check algorithm accordingly.
@kirelagin By reading the output you provided I get MCT didn't complain at startup about something like "no Mifare Classic support", right? Pleas try this testing verstion. It should detect your bcm2079x Broadcom device and display an error message.
I didn’t have a chance to test your code on the device, but I believe it won’t work.
The reason is that you are calling isFile
while looking for the device node and the question you ask in the comment, whether devices are files, is a valid one. I believe, the answer is “no”. The reason is that isFile
in libcore is implemented as:
return S_ISREG(Libcore.os.stat(path).st_mode);
and S_ISREG
, in turn, is implemented as:
return (mode & S_IFMT) == S_IFREG;
According to POSIX, this means “regular file”. I’m not sure what is the exact definition of “regular”, but, well, let’s assume it is common knowledge that device nodes are special files, not regular. Indeed, isFile
of /dev/sda
on my laptop returns false
.
I don’t think there is a standard way to detect device nodes in Java, but I think you can copy the isFile
implementation. Here it is for reference:
public boolean isFile() {
try {
return S_ISREG(Libcore.os.stat(path).st_mode);
} catch (ErrnoException errnoException) {
// The RI returns false on error. (Even for errors like EACCES or ELOOP.)
return false;
}
}
You are looking for S_ISBLK
or S_ISCHR
, I’m not sure which one, I’ll let you know when I get back to my Nexus (but you can probably check on your phone with NFC).
And the last thing. I believe you should wrap both checks (for the device and for the lib) in a try
/catch
in case listFiles
denies access, right?
You are looking for
S_ISBLK
orS_ISCHR
Got my hands on the Nexus. It’s a character device, so S_ISCHR
.
Thank you for providing me with all this information, but before I will use the isFile()
version that checks for character devices I would like you to test the MCT version as it is. They java spec says:
Tests whether the file denoted by this abstract pathname is a normal file. A file is normal if it is not a directory and, in addition, satisfies other system-dependent criteria.
Maybe character devices do "satisfie other system-dependent criteria". I this case is would prefer the normal isFile()
method because it is more readable.
Surrounding everything with a try
/catch
sounds like good idea (even though on my nexus 7, where the access to /dev
is denied, it just returned null
without throwing any exception).
A friend of mine has a Nexus 4 with Cyanogenmod too. But on his device he can't list /dev/bcm*
without root
:
shell@mako:/ $ ls -la /dev/bcm*
/dev/bcm*: No such file or directory
This is because the device belongs to nfc
. Other users have no permissions at all:
root@mako:/dev # ls -la bcm*
crw-rw---- nfc nfc 10, 92 2015-04-04 17:49 bcm2079x-i2c
The build he is running is 12-20150325 nightly
What are you using? Who is the owner of this device? Which group does it belong to?
Come on, permissions of a file have nothing to do with your ability to see it in the listing.
The r
permission on the directory containing the file is what matters.
shell@mako:/ $ ls -ld /dev
drwxr-xr-x root root 2015-04-22 23:17 dev
It’s CM11 20140919 nightly.
I checked on my own phone with CM12 20150217 nightly and it still has r
:
shell@ville:/ $ ls -ld /dev
drwxr-xr-x root root 2015-04-22 17:31 dev
So, that’s strange. Either they changed this during March or something’s special about your friend‘s phone.
Anyway, you’ll be able to check if a file with a known name exists (as opposed to listing the directory) even if the directory doesn’t have r
for your user, but has x
. So if /dev
on your friend’s Nexus has x
for other users, checking for existence of /dev/bcm2079x-i2c
will work as expected. The problem here is that in this case you’ll be checking for the file with the fixed name, not for bcm*
. But you can do this progressively:
/dev/bcm2079x-i2c
(and maybe other known names) exists. If yes, then fail, else/dev/bcm*
. If found something, then fail, elselibnfc-brcm*
. If found, then fail, else/dev
directory isn't readable for everyone on every phone. It depends a lot on the manufacturer.
But after, or before checks that @kirelagin suggested, you could check for nxp-related files. Especially libnfc-nxp
, and some files in /dev
, but I don't know their names (I have bcm based phone). But when you find NXP-related files, you can be sure there's Mifare support in this phone.
Another way could be ls /sys/module
, because if NFC is in use, there should be some kernel module loaded, but to be onest I'm not able to find one in my output.
@kirelagin You are absolutely right about the permission thing. My bad.
- check if /dev/bcm2079x-i2c (and maybe other known names) exists. If yes, then fail, else
- try to list /dev/bcm*. If found something, then fail, else
- try to find libnfc-brcm*. If found, then fail, else
- you don't know
Sounds like a pretty solid solution. I will do that, but maybe without the /dev/bcm*
. Broadcom produces also other products like wifi chips. I'm not sure if there are other devices by Broadcom in /dev
starting with bcm*
which are not NFC controllers.
@domints
Are you sure about the libnfc-nxp
? I know this is the name of the library for NFC chips by NXP on Android. But my Nexus 7 (2012) only shows:
shell@grouper:/ $ ls /system/lib/libnfc*
/system/lib/libnfc.so
/system/lib/libnfc_jni.so
/system/lib/libnfc_ndef.so
I searched the whole device for files with *nxp*
in their name. I found none. The only other NXP related file i know of is /dev/pn544
. But this is a device again...
This is a new testing version of MCT which directly checks for /dev/bcm2079-i2c
.
File device = new File("/dev/bcm2079x-i2c");
if (device.exists()) {
...
}
Please try it.
Yep, got the warning on my Nexus 4 with CM.
What about broaden your search?
if % is jokersign, the search for devices starting with "/dev/bcm2790%" ??
@kirelagin Perfect, thank you!
@iceman1001
For doing something like this directory listing is needed which requires the r
and the x
permission. Probing for the full path/name only requires the x
permission. The permissions on /dev
are very rare on Android. Therefore I chose the approach which works with less permissions.
I see, thanks for explaining it.
The changes are now in the master
branch.
See: https://github.com/ikarus23/MifareClassicTool/commit/44cf28d172c5fb888de932073865a062fbf64db9
domints said:
domints also said: