Mifare cards: distinguish between 4-byte and 7-byte UIDs - uniqueidentifier

I have a card reader that always report 64 bits, and can read cards with 4 or 7 byte UIDs.
As an example, I see it can report:
04-18-c5-82-00-00-00-00 - a 4-byte UID in the form uid0-uid1-uid2-uid3-00-00-00-00
04-18-c5-82-f1-3b-81-00 - a 7-byte UID in the form uid0-uid1-uid2-uid3-uid4-uid5-uid6-00
What prevents a 7-byte UID from having uid4, uid5 and uid6 set to zero? Is this covered in a spec? If so, which spec?

What prevents a 7-byte UID from having uid4, uid5 and uid6 set to zero?
Nothing. The format of the UID (as used by MIFARE cards) is defined in ISO/IEC 14443-3. Specifically for MIFARE cards, NXP has (or at least had?) some further allocation logic for 4 byte UIDs, but that's not publicly available.
Is it possible to distinguish the two cases?
If the reader outputs the UIDs exactly in the form that you showed in your example, then the answer is no (at least not reliably). However, some readers output the UID on 8 bytes and include the cascade tag for 7-byte-UIDs. Thus, all 7-byte-UIDs start with 0x88 for those readers. This does not seem to be the case with your reader.
Are there possible strategies to distinguish the two cases?
Some strategies come to my mind to distinguish 4-byte-UIDs from 7-byte-UIDs.
The first byte of a 7-byte-UID is the manufacturer code (as defined in ISO/IEC 7816-6 (see How to detect manufacturer from NFC tag using Android? on how to obtain the list). Thus, if you have a limited set of manufacturers (e.g. if you only use MIFARE cards with chips from NXP), you could interpret all UIDs that start with NXP's manufacturer code (0x04) as 7-byte-UIDs. Nevertheless, you should be aware that 4-byte-UIDs are allowed to start with 0x04 as well. Hence, this method is not 100% reliable and may fail for some cases.
The first byte of 4-byte-UIDs must not contain any of the following values: 'x8' (with x != '0'), 'xF'. If you find the first byte to match any of those values, you can assume the UID to consist of 7 bytes.

if you can get the ATQA response you can distinguish it. The lower byte of the ATQA shows you how long the UID is. (4/7/10Byte) As far as I know there is no other way to distinguish with 100% assurance
br

I know its bit late to the party, but for any one who is having the same doubt;
the documented way of creating a 7 Byte UID out of 4 Byte UID is in the Annex-6 of this pdf.
In case the page goes down, a shameless rip off from that page is given below.
Any and all mistakes if you find in the below code snippet rightfully belongs to NXP guys, not me.
But how do you know whether the tag is a 4 byte or 7 byte uid one?
From the ATQA response. Refer page 15/36 of the document 1 and page 8/15 of document 2 .
In case the document goes down, here is the relevant excerpt from the document 1.
The MF1S50yyX/V1 answers to a REQA or WUPA command with the ATQA value
shown in Table 11 and to a Select CL1 command (CL2 for the 7-byte UID variant) with the SAK value shown in Table 12.
Remark: The ATQA coding in bits 7 and 8 indicate the UID size according to ISO/IEC 14443 independent from the settings of the UID usage.
6. Annex, Source code to derive NUID out of a Double Size UID
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#define BYTE unsigned char
unsigned short UpdateCrc(unsigned char ch, unsigned short *lpwCrc)
{
ch = (ch^(unsigned char)((*lpwCrc) & 0x00FF));
ch = (ch^(ch<<4));
*lpwCrc = (*lpwCrc >> 8)^((unsigned short)ch << 8)^((unsigned
short)ch<<3)^((unsigned short)ch>>4);
return(*lpwCrc);
}
void ComputeCrc(unsigned short wCrcPreset, unsigned char *Data, int
Length, unsigned short &usCRC)
{
unsigned char chBlock;
do {
chBlock = *Data++;
UpdateCrc(chBlock, &wCrcPreset);
} while (--Length);
usCRC = wCrcPreset;
return;
}
void Convert7ByteUIDTo4ByteNUID(unsigned char *uc7ByteUID, unsigned char
*uc4ByteUID)
{
unsigned short CRCPreset = 0x6363;
unsigned short CRCCalculated = 0x0000;
ComputeCrc(CRCPreset, uc7ByteUID, 3,CRCCalculated);
uc4ByteUID[0] = (CRCCalculated >>8)&0xFF;//MSB
uc4ByteUID[1] = CRCCalculated &0xFF; //LSB
CRCPreset = CRCCalculated;
ComputeCrc(CRCPreset, uc7ByteUID+3, 4,CRCCalculated);
uc4ByteUID[2] = (CRCCalculated >>8)&0xFF;//MSB
uc4ByteUID[3] = CRCCalculated &0xFF; //LSB
uc4ByteUID[0] = uc4ByteUID[0]|0x0F;
uc4ByteUID[0] = uc4ByteUID[0]& 0xEF;
}
int main(void)
{
int i;
unsigned char uc7ByteUID[7] =
{0x04,0x18,0x3F,0x09,0x32,0x1B,0x85};//4F505D7D
unsigned char uc4ByteUID[4] = {0x00};
Convert7ByteUIDTo4ByteNUID(uc7ByteUID,uc4ByteUID);
printf("7-byte UID = ");
for(i = 0;i<7;i++)
printf("%02X",uc7ByteUID[i]);
printf("\t4-byte FNUID = ");
for(i = 0;i<4;i++)
printf("%02X",uc4ByteUID[i]);
getch();
return(0);
}

If you came here (as I did) to find a proper way to automatically get the UID from a card independent if it is a 4, 7 or 10 byte UID, I do it dynamically as following (found this logic somewhere on the internet but can't find it anymore to give proper credits. 10 Bytes not tested):
(this is C# code and is using winscard.dll under the hood):
public static UInt64 getCardUIDasUInt64() // *** only for mifare 1k cards ***
{
UInt64 UID = 0;
byte[] receivedUID = new byte[10]; // ***
Card.SCARD_IO_REQUEST request = new Card.SCARD_IO_REQUEST();
request.dwProtocol = (UInt32)Protocol; // *** use the detected protocol instead of statically assigned protocol type *** // Card.SCARD_PROTOCOL_T1;
request.cbPciLength = (UInt32)System.Runtime.InteropServices.Marshal.SizeOf(typeof(Card.SCARD_IO_REQUEST));
byte[] sendBytes = new byte[] { 0xFF, 0xCA, 0x00, 0x00, 0x00 }; //get UID command for Mifare cards
//byte[] sendBytes = new byte[] { 0xFF, 0xCA, 0x00, 0x00, 0x04 }; //get UID command for Mifare cards
int receivedBytesLength = receivedUID.Length;
int status = Card.SCardTransmit(hCard, ref request, ref sendBytes[0], sendBytes.Length, ref request, ref receivedUID[0], ref receivedBytesLength);
if (status == Card.SCARD_S_SUCCESS)
{
if (receivedBytesLength >= 2)
{
// do we have an error
if ((receivedUID[receivedBytesLength - 2] != 0x90) ||
(receivedUID[receivedBytesLength - 1] != 0x00))
{
throw new Exception(receivedUID[receivedBytesLength - 2].ToString());
}
else if (receivedBytesLength > 2)
{
for (UInt32 i = 0; i != receivedBytesLength - 2; i++)
{
UID <<= 8;
UID |= (UInt64)(receivedUID[i]);
};
}
}
else
{
throw new Exception(ResourceHandling.getTextResource("Error_Card_Read"));
}
}
return UID;
}
If you need the UID in hex, then use this (in addition to above code):
public static string getCardUIDasHex() // *** only for mifare 1k cards ***
{
UInt64 cardUID = getCardUIDasUInt64();
return string.Format("{0:X}", cardUID);
}
Maybe this is also of help to someone else as in the internet (also here in SO) there are many places which just read out the 1st four bytes of the UID which is just not correct anymore today.

Related

How do I read passive NFC/RFID units with PN532?

I got the little red "ELECHOUSE V3" kit off of eBay with a white card, and a blue keyfob transponder, and I've written a C program which creates and decodes packets and I can send it commands and it responds with AC packets, and I can read the version and the status. I'm not using any RFID library, I'm just using plain C and making my own simple library because I want to understand it and I want to release a simple single file demonstration for people who really want to understand it rather than just using some arduino lib or whatever. So that's all the questions I'm not asking.
So here's the question I am asking:
What is the exact commands to send to scan for the presence of passive (non powered) transponders? I do not know for sure what kind they are, but they came with the kit and are probably ISO 14443 / 14443A.
Actually, I tried the tags on my Samsung Galaxy S4, and it says they are ISO 14443-3A NXP MIFARE Classic 1K - Not Supported. But it still shows the serial numbers for them.
What are the exact commands to scan for all supported card types?
To send a command I use my function like this:
sendcmd("0x4A 0x01 0x00");
(The TFI of 0xD4 is automatically added to the commands, and the preamble/len/lcs/checksums are all calculated and dealt with.)
I do get ACKS back for my commands, but can't figure out which commands to send to scan for cards or read them.
If I can get the PN532 to spit card scan data back at me I should be able to parse it using the PN532 datasheet.
Thank you very much,
Jesse
Ahh OK.. After trying everything that seemed related indicated in the data sheet with no success, I turned ham radio on to 13.56Mhz CW/LSB and there was nothing to be heard.. So just for kicks I tried the RFRegulationTest command, and that unlocked the whole thing! Seems to be a test command which turns on the transmitter and leaves it on till you issue another command... But it initializes something as needed!
So here's the commands it takes to make the NXP NP532 scan for cards:
(I'm using RS232 at 115200bps, but should be similar for other interfaces.)
You send to it:
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0xFF 0x03 0xFD 0xD4 0x58 0x00 0xD4
and you'll get an ACK and transmitter will key on:
0x00 0x00 0xFF 0x00 0xFF 0x00
And at this point the transmitter will key up. Maybe let it do that for 100mS or something, then you can start scanning for cards:
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0xFF 0x04 0xFC 0xD4 0x4A 0x02 0x00 0xE0
The chip will then turn on the radio transmitter and start scanning for cards until a card comes in range, then it reads the serial number, shuts down the transmitter, and gives you a packet which contains:
0x4B, 0x01/0x02 (Depending on whether 1 or 2 cards was detected), followed by various info about the card like it's serial number.
You can also set the max number of tries it'll try when given the 0x4A 0x02 0x00 command, by setting the number of tries to a number below 0xFF, like this:
sendcmd("0x32 0x05 0xFF 0x01 0x10")
in which case when you give the read command (0x4A 0x02 0x00) it'll try for a fraction of a second (0x10 times) then give up and send a packet that contains:
0x4B, 0x00
which means "Cards found: Zero."
See the datasheet for all the details, it does tell you everything you need to know, except I never could figure out how to enable the transmitter until I ran the rf test command.
Anyway, just keep sending the second command over and over a few times a second or slower if you like, and each time you send that command it will scan and let you know if there is a card within range!
Or if you set retries to 0xFF then it'll try forever until it detects a card, then you only have to re-send the scan-for-card command when it finds one.
The long strings of 0xFF is just to wake the device up because it goes to sleep and misses the first few bytes you send.
The examples I give of what to send it that start with a bunch of 0xFF's are the whole full packet, including preambles, length field, checksums and everything calculated. You can send them directly to make it scan for cards.
The initial RF test command and the retry set command only needs to be run once on powerup, after that just keep re-sending the read command as needed.
My PN532 chip reports itself as Version: 1.6
Here's my little sample program:
(The RS232 initialization part I lifted from an SO post - thanks to whoever wrote that!)
(It's for Linux. Compile with gcc nfc.c -o nfc.e )
(Should be able to port it to any platform, you just have to deal with the serial port - the rest is platform independent.)
(Also note that this simply scans for cards and returns serial number/NFCID, and only for Mifare, ISO/IEC14443-3 Type A cards at 106kbps in passive mode. If you want to actually read/write to the memory on the cards, you have to write more code, but this at least demonstrates what it takes to get started and how the command structure works, and provides some handy routines for sending and decoding packets.)
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int debug=0;
int fd;
void init_rs232(void);
void sendpacket(unsigned char * payload, int len);
void sendcmd(char * payload);
int main(void)
{
printf("Welcome!\n");
init_rs232();
int waitfor;
#define PACKET 1
#define ACK 2
sendcmd("0x58 0x00");waitfor=ACK; //RFRegulationTest -- This command is used for radio regulation test.
int cstate=0; //Chat state, config state, whatever..
int lc=0;
while(1)
{
lc++; //Send a scan command every second or so.
if(lc>1000)
{
lc=0;
sendcmd("0x4A 0x02 0x00"); //InListPassiveTarget -- The goal of this command is to detect as many targets (maximum MaxTg) as possible (max two) in passive mode.
}
if(cstate==1) //ACK's set the bottom bit in state, allowing it to go onto the next state.
{
sendcmd("0x02");waitfor=PACKET; //Read the version out of the PN532 chip.
cstate++;
}
if(cstate==3) //ACK's set the bottom bit in state, allowing it to go onto the next state.
{
sendcmd("0x04");waitfor=PACKET; //Get current status.
cstate++;
}
if(cstate==5)
{
waitfor=PACKET;
sendcmd("0x32 0x05 0xFF 0x01 0x10");//Max retries - last byte is for passive: 0=1 try, 1=2 tries, 254=255 tries, 0xFF=infinite retries.
//If last byte is 0xFF, then unit starts scanning for cards indefinitely. As soon as it detects a card, it stops scanning and returns info.
//If last byte is less than 0xFF, it tries scans and as soon as it finds a card returns info on it and stops trying, but
//if it never finds a card in the specified number of retries, it gives up and returns 0x4B, 0x00 (Cards found: Zero.)
cstate++;
}
//Alternative way to send a new scan command each time the previous one gives up or finds a card:
// if(cstate==7)
// {
// waitfor=PACKET;
// sendcmd("0x4A 0x02 0x00"); //InListPassiveTarget
// cstate--;
// }
static unsigned char buffin [1000024];
static unsigned char buf[1],bufo[1];
int n;
static int bi=0;
unsigned char len,lcs,tfi,dcs;
bufo[0]=buf[0];
n=read(fd,buf,sizeof(buf));
if(n!=0)
{
if(n>0)
{
if(bi<1000000)
{
static int state=0;
if(state==0) //Waiting for preamble..
{
if((bufo[0]==0)&&(buf[0]==0xFF)){state=10;}
}
else if(state==10) //Waiting for Len
{
len=buf[0];
state=20;
}
else if(state==20) //Waiting for len checksum
{
if((len==0xFF)&&(buf[0]==0xFF)){printf("ERROR: BIG PACKET. Bye.\n");exit(-2);}
if((len==0x00)&&(buf[0]==0xFF)){state=21;}
else if((len==0xFF)&&(buf[0]==0x00)){state=21;}
else
{
lcs=buf[0]+len;
if(lcs){printf("ERROR: len checksum failed! 0x%02X\n",buf[0]);}
state=30;
}
}
else if(state==21) //Waiting for the 0x00 after ack/nack..
{
state=0;
if(buf[0]==0x00)
{
if(bufo[0]==0xFF)
{
if(debug){printf("ACK!\n");}
if(waitfor==ACK){cstate=cstate|1;}
}
if(bufo[0]==0x00){printf("NACK!\n");}
}else{
printf("ERROR: Invalid length, or ack/nack missing postamble...\n");
}
}
else if(state==30) //Waiting for tfi..
{
tfi=buf[0];
//printf("tfi=0x%02X\n",tfi);
dcs=tfi;
bi=0;
state=40;
}
else if(state==40) //Saving bytes...
{
//printf("Saving payload byte 0x%02X\n",buf[0]);
buffin[bi++]=buf[0];
dcs=dcs+buf[0];
if(bi>=len){state=50;}
}
else if(state==50) //Calculating the checksum..
{
state=0;
dcs=dcs+buf[0];
if(dcs)
{
printf("ERROR: Data Checksum Failed! (0x%02X)\n",dcs);
}else{
if(waitfor==PACKET){cstate=cstate|1;}
//printf("Good Packet: tfi=0x%02X, len=%d\n",tfi,len-1);
if(tfi==0xD5)
{
if(buffin[0]==0x03){printf("PN532 Version: %d.%d, features:%d\n",buffin[2],buffin[3],buffin[4]);}
if(buffin[0]==0x05)
{
printf("Status: Last Error:%d, Field:%d, Targets:%d, SAM Status:0x%02X\n",buffin[1],buffin[2],buffin[3],buffin[len-2]);
static char bitrates[255][10]={"106kbps","212kbps","424kbps"};
static char modtypes[255][100];
strcpy(modtypes[0x00],"Mifare, ISO/IEC14443-3 Type A, ISO/IEC14443-3 Type B, ISO/IEC18092 passive 106 kbps");
strcpy(modtypes[0x10],"FeliCa, ISO/IEC18092 passive 212/424 kbps");
strcpy(modtypes[0x01],"ISO/IEC18092 Active mode");
strcpy(modtypes[0x02],"Innovision Jewel tag");
if(buffin[3]==1){printf("Target %d: rx bps:%s, tx bps:%s, modulation type: %s.\n",buffin[4],bitrates[buffin[5]],bitrates[buffin[6]],modtypes[buffin[7]]);}
if(buffin[3]==2){printf("Target %d: rx bps:%s, tx bps:%s, modulation type: %s.\n",buffin[8],bitrates[buffin[9]],bitrates[buffin[10]],modtypes[buffin[11]]);}
}
if(buffin[0]==0x4B)
{
printf("FOUND %d CARDS!\n",buffin[1]);
//ONLY VALID FOR Mifare/ ISO type A 106KBPS:
int i,ii,iii;
i=0;ii=2;
while(i<buffin[1])
{
printf("Target # %d:", buffin[ii++]);
printf("SENS_RES=0x%02X%02X, ",buffin[ii],buffin[ii+1]);ii++;ii++;
printf("SEL_RES=0x%02X, ",buffin[ii++]);
printf("NFCIDLength=%d, ",buffin[ii++]);
printf("NFCID=");
iii=0;
while(iii<buffin[ii-1])
{
printf("%02X",buffin[ii+iii]);
iii++;
if(iii<buffin[ii-1]){printf(":");}
}
ii=ii+iii;
printf("\n");
i++;
}
}
//Just a debugging thing for printing out the contents of valid packets.
//int i=0;while(i<(len-1)){printf("0x%02X, ",buffin[i++]);}printf("\n");
}
else if(tfi==0x7F)
{
printf("Received error packet 0x7F with zero size.\n");
}else{
printf("ERROR: Got unknown %d byte packet with tfi=0x%02X!\n",len-1,tfi);
}
}
}
else
{
printf("Uhoh!\n");
}
//printf("Got byte 0x%02X, now state is %d\n",(unsigned char)buf[0],state);
}else{
printf("ERROR: bi=%d which is too big.. Starting over.\n",bi);
bi=0;
}
}else{
printf("ERROR %d while reading serial port: %s\n",errno,strerror(errno));
exit(-1);
}
}
usleep(1000);
}
return(0);
}
void init_rs232(void)
{
char *portname = "/dev/ttyUSB0";
fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
printf("error %d opening %s: %s", errno, portname, strerror (errno));
exit(-1);
}
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf("error %d from tcgetattr(%s)\n", errno,strerror(errno));
exit(-1);
}
cfsetospeed (&tty, B115200);
cfsetispeed (&tty, B115200);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 0; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= 0; //This was parity
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf("error %d from tcsetattr(%s)\n", errno,strerror(errno));
exit(-1);
}
}
void sendpacket(unsigned char * payload, int len)
{
int tfi;
static unsigned char buffer[66000];
int i,bo;
unsigned char lcs,dcs;
tfi=0xD4;
i=0;
bo=0;
while(i<=8){i++;buffer[bo++]=0xFF;} //Pre-padding.. 8-800 OK, 900 too much, 7 too little. Needs to be 0xFF I guess.. Probably wakes it up.
buffer[bo++]=0x00; //Preamble.
buffer[bo++]=0xFF; //Preamble.
len++;
lcs=-len; //Length Checksum.. (yes...)
buffer[bo++]=len;
buffer[bo++]=lcs;
buffer[bo++]=tfi;
dcs=tfi;
i=0;
while((i<65900)&&(i<(len-1)))
{
buffer[bo]=payload[i];
dcs=dcs+buffer[bo];
bo++;
i++;
}
dcs=(-dcs);
buffer[bo++]=dcs;
write(fd,buffer,bo);
//printf("Sent %d bytes\n",bo);
//printf("Whole packet: ");
//i=0;
//while(i<bo)
//{
// printf("0x%02X ",buffer[i]);
// i++;
//}
//printf("\n");
}
void sendcmd(char * payload) //Accepts space separated argument list like "0xFF 0x0A 255 'USERID' 0 0"
{ //strings are quoted in half quotes. half quotes inside a string are escaped \\'
int i,v; //full quotes inside a string are escaped like \"
static unsigned char buffer[1024]; //back slashes inside a string are escaped like \\\\ .
static int bo; //(The first escape or escape pair is for the C compiler, the second for this function:
bo=0; // The actual contents of the string are just \' and \\)
i=0; // Numeric formats supported are hex (0xNN), base ten (123), and octal (0377).
if(debug){printf("sendcmd: ");}
while(payload[i])
{
if((payload[i]!='\'')&&(payload[i]!=' '))
{
v=strtoul(&payload[i],NULL,0);
buffer[bo++]=v;
if(debug){printf("0x%02X, ",v);}
while(payload[i]>' '){i++;}
}
else if(payload[i]=='\'')
{
i++;
int keeprun;
keeprun=1;
while(keeprun)
{
if(payload[i]=='\\')
{
i++;
}else{
if(payload[i]=='\''){keeprun=0;}
}
if((keeprun)&&(payload[i]))
{
buffer[bo++]=payload[i];
if(debug){printf("%c",payload[i]);}
}
i++;
}
if(debug){printf(", ");}
}
else
{
i++;
}
}
if(debug){printf("\n");}
sendpacket(buffer,bo);
}

How to use mmap for devmemon MT7620n

I`m trying to access the GPIOs of a MT7620n via register settings. So far I can access them by using /sys/class/gpio/... but that is not fast enough for me.
In the Programming guide of the MT7620 page 84 you can see that the GPIO base address is at 0x10000600 and the single registers have an offset of 4 Bytes.
MT7620 Programming Guide
Something like:
devmem 0x10000600
from the shell works absolutely fine but I cannot access it from inside of a c Programm.
Here is my code:
#define GPIOCHIP_0_ADDDRESS 0x10000600 // base address
#define GPIO_BLOCK 4
volatile unsigned long *gpiochip_0_Address;
int gpioSetup()
{
int m_mfd;
if ((m_mfd = open("/dev/mem", O_RDWR)) < 0)
{
printf("ERROR open\n");
return -1;
}
gpiochip_0_Address = (unsigned long*)mmap(NULL, GPIO_BLOCK, PROT_READ|PROT_WRITE, MAP_SHARED, m_mfd, GPIOCHIP_0_ADDDRESS);
close(m_mfd);
if(gpiochip_0_Address == MAP_FAILED)
{
printf("mmap() failed at phsical address:%d %s\n", GPIOCHIP_0_ADDDRESS, strerror(errno));
return -2;
}
return 0;
}
The Output I get is:
mmap() failed at phsical address:268436992 Invalid argument
What do I have to take care of? Do I have to make the memory accessable before? I´m running as root.
Thanks
EDIT
Peter Cordes is right, thank you so much.
Here is my final solution, if somebody finds a bug, please tell me ;)
#define GPIOCHIP_0_ADDDRESS 0x10000600 // base address
volatile unsigned long *gpiochip_0_Address;
int gpioSetup()
{
const size_t pagesize = sysconf(_SC_PAGE_SIZE);
unsigned long gpiochip_pageAddress = GPIOCHIP_0_ADDDRESS & ~(pagesize-1); //get the closest page-sized-address
const unsigned long gpiochip_0_offset = GPIOCHIP_0_ADDDRESS - gpiochip_pageAddress; //calculate the offset between the physical address and the page-sized-address
int m_mfd;
if ((m_mfd = open("/dev/mem", O_RDWR)) < 0)
{
printf("ERROR open\n");
return -1;
}
page_virtual_start_Address = (unsigned long*)mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, m_mfd, gpiochip_pageAddress);
close(m_mfd);
if(page_virtual_start_Address == MAP_FAILED)
{
printf("ERROR mmap\n");
printf("mmap() failed at phsical address:%d %d\n", GPIOCHIP_0_ADDDRESS, strerror(errno));
return -2;
}
gpiochip_0_Address = page_virtual_start_Address + (gpiochip_0_offset/sizeof(long));
return 0;
}
mmap's file offset argument has to be page-aligned, and that's one of the documented reasons for mmap to fail with EINVAL.
0x10000600 is not a multiple of 4k, or even 1k, so that's almost certainly your problem. I don't think any systems have pages as small as 512B.
mmap a whole page that includes the address you want, and access the MMIO registers at an offset within that page.
Either hard-code it, or maybe do something like GPIOCHIP_0_ADDDRESS & ~(page_size-1) to round down an address to a page-aligned boundary. You should be able to do something that gets the page size as a compile-time constant so it still compiles efficiently.

C Program Strange Characters retrieved due to language setting on Windows

If the below code is compiled with UNICODE as compiler option, the GetComputerNameEx API returns junk characters.
Whereas if compiled without UNICODE option, the API returns truncated value of the hostname.
This issue is mostly seen with Asia-Pacific languages like Chinese, Japanese, Korean to name a few (i.e., non-English).
Can anyone throw some light on how this issue can be resolved.
# define INFO_SIZE 30
int main()
{
int ret;
TCHAR infoBuf[INFO_SIZE+1];
DWORD bufSize = (INFO_SIZE+1);
char *buf;
buf = (char *) malloc(INFO_SIZE+1);
if (!GetComputerNameEx((COMPUTER_NAME_FORMAT)1,
(LPTSTR)infoBuf, &bufSize))
{
printf("GetComputerNameEx failed (%d)\n", GetLastError());
return -1;
}
ret = wcstombs(buf, infoBuf, (INFO_SIZE+1));
buf[INFO_SIZE] = '\0';
return 0;
}
In the languages you mentioned, most characters are represented by more than one byte. This is because these languages have alphabets of much more than 256 characters. So you may need more than 30 bytes to encode 30 characters.
The usual pattern for calling a function like wcstombs goes like this: first get the amount of bytes required, then allocate a buffer, then convert the string.
(edit: that actually relies on a POSIX extension, which also got implemented on Windows)
size_t size = wcstombs(NULL, infoBuf, 0);
if (size == (size_t) -1) {
// some character can't be converted
}
char *buf = new char[size + 1];
size = wcstombs(buf, infoBuf, size + 1);

vsnprintf on an ATMega2560

I am using a toolkit to do some Elliptical Curve Cryptography on an ATMega2560. When trying to use the print functions in the toolkit I am getting an empty string. I know the print functions work because the x86 version prints the variables without a problem. I am not experienced with ATMega and would love any help on this matter. The print code is included below.
Code to print a big number (it itself calls a util_print)
void bn_print(bn_t a) {
int i;
if (a->sign == BN_NEG) {
util_print("-");
}
if (a->used == 0) {
util_print("0\n");
} else {
#if WORD == 64
util_print("%lX", (unsigned long int)a->dp[a->used - 1]);
for (i = a->used - 2; i >= 0; i--) {
util_print("%.*lX", (int)(2 * (BN_DIGIT / 8)),
(unsigned long int)a->dp[i]);
}
#else
util_print("%llX", (unsigned long long int)a->dp[a->used - 1]);
for (i = a->used - 2; i >= 0; i--) {
util_print("%.*llX", (int)(2 * (BN_DIGIT / 8)),
(unsigned long long int)a->dp[i]);
}
#endif
util_print("\n");
}
}
The code to actually print a big number variable:
static char buffer[64 + 1];
void util_printf(char *format, ...) {
#ifndef QUIET
#if ARCH == AVR
char *pointer = &buffer[1];
va_list list;
va_start(list, format);
vsnprintf(pointer, 128, format, list);
buffer[0] = (unsigned char)2;
va_end(list);
#elif ARCH == MSP
va_list list;
va_start(list, format);
vprintf(format, list);
va_end(list);
#else
va_list list;
va_start(list, format);
vprintf(format, list);
fflush(stdout);
va_end(list);
#endif
#endif
}
edit: I do have UART initialized and can output printf statments to a console.
I'm one of the authors of the RELIC toolkit. The current util_printf() function is used to print inside the Avrora simulator, for debugging purposes. I'm glad that you could adapt the code to your purposes. As a side note, the buffer size problem was already fixed in more recent releases of the toolkit.
Let me know you have further problems with the library. You can either contact me personally or write directly to the discussion group.
Thank you!
vsnprintf store it's output on the given buffer (which in this case is the address point by pointer variable), in order for it to show on the console (through UART) you must send your buffer using printf (try to add printf("%s", pointer) after vsnprintf), if you're using avr-libc don't forget to initialized std stream first before making any call to printf function
oh btw your code is vulnerable to buffer overflow attack, buffer[64 + 1] means your buffer size is only 65 bytes, vsnprintf(pointer, 128, format, list); means that the maximum buffer defined by your application is 128 bytes, try to change it below 65 bytes in order to avoid overflow
Alright so I found a workaround to print the bn numbers to a stdout on an ATMega2560. The toolkit comes with a function that writes a variable to a string (bn_write_str). So I implemented my own print function as such:
void print_bn(bn_t a)
{
char print[BN_SIZE]; // max precision of a bn number
int bi = bn_bits(a); // get the number of bits of the number
bn_write_str(print, bi, a, 16) // 16 indicates the radix (hexadecimal)
printf("%s\n"), print);
}
This function will print a bn number in hexadecimal format.
Hope this helps anyone using the RELIC toolkit with an AVR.
This skips the util_print calls.

Confused by example code to check endianness

Hi I'm confused by the example code given here to check if a machine is little or big endian:
Little Endian or Big Endian?
int isLittleEndian( void )
{
unsigned int temp = 0x12345678;
char * tempAddress = &temp;
if( *tempAddress == 0x12 )
{
return 0; // Indicating False
} else {
return 1; // Indicating True
}
}
Versus this description of little and big endianness given here:
http://support.microsoft.com/kb/102025
The second link says on an LE machine 0x1234 is stored in memory as 0x34 0x12, however the isLittleEndian() function in the first link is returning true if the first byte is 0x12. Isn't that a contradiction of the 2nd link? If not then what is it I've misunderstood?
No, the function returns false if the first byte is 0x12. Which is as it should be, and jives with the description of endianness.

Resources