How to properly receive hex data from serial communication in linux - c

I have been searching for this similar issue on internet but haven't found any good solution. I am in ubuntu and I am receiving serial hex data on serial port. I have connected my system using null modem cable to windows system and windows system is running docklight software which is sending hex data like below:
2E FF AA 4F CC 0D
Now by saving the data, I do not mean that I want to print data on terminal. I just want to save this data as it is in a buffer so that I an later process it.
To read the data I am doing
res = read (fd, buf, sizeof buf)
//where buf is
unsigned char buf[255];
At this point after reading, buf contains some random chars. From some links on internet, I got a way to convert it into hex:
unsinged char hexData[255];
for (int i = 0; i < res; i++)
{
sprintf((char*)hexData+i*2, "%02X", buf[i]);
}
Now this hexData contains 2EFFAA4FCC0D, which is ok for my purpose. (I do not know if it is the right way of doing it or not). Now lets say I want to convert E from the hexData into decimal. But at this point, E will be considered as character not a hex so may be I'll get 69 instead of 14.
How can I save hex data in a variable. Should I save it as array of chars or int. Thanks.

You already have data in binary form in buf
But if you still need to convert hex to decimal, you can use sscanf
sscanf(&hexBuf[i],"%02X",&intVar);// intVar is integer variable
It wll convert hex byte formed by hexBuf[i] and hexBuf[i+1] to binary in intVar, When you printf intVar with %d you will get to see the decimal value
You can store intVar as element of unsigned character array

You may want to think about what you're trying to achieve.
Hexadecimal is just a representation. The byte you are receiving could be shown as hexadecimal pairs, as binary octet or as a series of (more or less) printable characters (what you see if you print your unsigned char array).
If what you need is storing only the hexadecimal representation of those bytes, convert them to hexadecimal as you are doing, but remember you'll need an array twice as big as your buffer (since a single byte will be represented by two hexadecimal characters once you convert it).
Usually, the best thing to do is to keep them as an array of bytes (chars), that is, your buf array, and only convert them when you need to show the hexadecimal representation.

Related

directly cast a char *nib as int hex

in pure and portable c.
So I am having trouble casting what has to be a variable, from a variable. char *nib to int hex. The idea being I had a char *nib ="ab"; or "0xab" or anything that directly represents two characters as a char *. then casting it as a integer. and writing it to a file to get a one to one write. so I start with char *nib="0xab"; then I write it as a int presumably, and to a hexdump or edit and the result is just ab.
I've been able to do this as a constant directly declaring... but the nib is always static.
this has to be a one to one starting with a two char string or nib. Not converting anything, purly casting.
So can you write it directly to a file without converting it? three look up tables seems like a bit much for a value what has the name length
There is no way to cast 2 characters (2 bytes) into one byte because cast does not change binary representation of the value.
The closest you can get to casting string that looks like hex to some value that will show something similar is use 0-15 characters via escape sequence like char* nib = "\x0A\x0B" and cast ( *((short*)nib)) that to 2-byte value (0x0A0B in this case) and store that to a file (I'm not sure if there is portable integer type of 2 bytes - short often is 2 bytes wide but does not have to be 2 bytes). Unfortunately I don't think there is a portable way to store 2 byte integer value to a file as different architectures may have different byte order.
Writing string value character by character is likely safest approach. Or convert string to int a usual way and use your own read/write code for integers to ensure portability.

How to check whether a hexadecimal number(%x) starts with a certain number or not in C?

I'm working on an operating system related project now and there is one step which requires to check whether a hexadecimal number starts with 3 or not, using C.
Currently my idea is to convert that hexadecimal number into a string and check the initial character but just cannot find out any documentation for doing that. Anybody has any idea? Maybe just a hint.
There are lots of methods to convert a number to a hex string (sprintf comes to mind; How can I convert an integer to a hexadecimal string in C? list a few more) – but, why should you?
A full hex number is formed by converting each nibble (4 bits) to a hexadecimal 'digit'. To get just the first, you can divide your value by 16 until you have reached the final (= 'first', in the left-to-right notation common for both decimal and hexadecimal values) digit. If that's a 3 you are done.
Assuming value is an unsigned number:
while (value > 15)
value >>= 4;
and then check if value == 3.
Your idea is not bad, you can use sprintf, it functions like printf/fprintf but instead of printing
on screen (or to be more precise: writing into a FILE* buffer), it stores the contents in a char buffer.
char value[16]; // more than enough space for 4 byte values
int reg = 0x3eef;
sprintf(value, "%x", reg);
if(value[0] == '3')
printf("The hexadecimal number 0x%s starts with a 3.\n", value);

uint64 to string in C

I have a uint64 value that I want to convert into a string because it has to be inserted as the payload of an HTTP POST request.
I've already tried many solutions (ltoa, this solution ) but my problem still remains.
My function is the following:
void check2(char* fingerprint, guint64 s_id) {
//stuff
char poststr[400] = "action=CheckFingerprint&sessionid=";
//convert s_id to, for example, char* myChar
strcat(poststr, myChar);
}
I want to convert s_id to char*. I've tried:
1) char ses[8]; ltoa(s_id,ses,10) but I have a segmentation fault;
2) char *buf; sprintf(buf, "%" PRIu64, s_id);
I'm working on a APIs, so I have seen that when this guint64 variable is printed, it has the following form:
JANUS_LOG(LOG_INFO, "Creating new session: %"SCNu64"\n", session_id);
sprintf is the right way to go with an unsigned 64 bit format specifier.
You'll need to allocate enough space for 16 hex digits and the null byte. Here I've allocated 20 bytes to accommodate a leading 0x as well and then I rounded it up to 20 for no good reason other than it feels better than 19.
char foo[20];
sprintf(foo, "0x%016" PRIx64, (uint64_t)numberToConvert);
will print the number in hex with leading 0x and leading zeros padded up to 16. You do not need the cast if numberToConvert is already a uint64_t
i have a uint64 value that i want to convert into char* because of it have to be inserted as payload of an HTTP POST request.
What you have is a fundamental misunderstanding.
To insert a text representation of your value into a document, you need to convert it to a sequence of characters, which is quite a different thing from a pointer to a character (char *). One of your options, which seems to be what you're really after, is to convert the value to a sequence of characters in the form of a C string -- that is, a null-terminated array of characters. You would then have or be able to obtain a pointer to the first character in the sequence.
That explains what's wrong with this attempted solution:
char *buf;
sprintf(buf, "%" PRIu64, s_id);
You are trying to write the string representation of your number into the array pointed-to by buf, but it doesn't point to one. Not having been initialized or assigned, its value is indeterminate.
Even if you your buf pointed to an array, it is essential that the array be long enough to accommodate all the digits of the value's decimal representation, plus a terminator. That's probably what's wrong with your other attempt:
char ses[8]; ltoa(s_id,ses,10)
An unsigned, 64-bit binary number may require up to 20 decimal digits, plus you need space for a terminator. The array you're providing is not nearly large enough, unless you can be confident that the actual values you're going to write will not exceed 9,999,999 (which is well within the range of a 32-bit integer).

itoa providing 7-bit output to character input

I am trying to convert a character to its binary using inbuilt library (itoa) in C(gcc v-5.1) using example from Conversion of Char to Binary in C , but i'm getting a 7-bit output for a character input to itoa function.But since a character in C is essentially an 8-bit integer, i should get an 8-bit output.Can anyone explain why is it so??
code performing binary conversion:
enter for (temp=pt;*temp;temp++)
{
itoa(*temp,opt,2); //convert to binary
printf("%s \n",opt);
strcat(s1,opt); //add to encrypted text
}
PS:- This is my first question in stackoverflow.com, so sorry for any mistakes in advance.
You could use printf( "%2X\n", *opt ); to print a 8-bit value as 2 hexadecimal symbols.
It would print the first char of opt. Then, you must increment the pointer to the next char with opt++;.
The X means you want it to be printed as uppercase hexadecimal characters (use x for lowercase) and the 2 will make sure it will print 2 symbols even if opt is lesser than 0x10.
In other words, the value 0xF will be printed 0x0F... (actually 0F, you could use printf( "%#2X\n", *opt ); to print the 0x).
If you absolutely want a binary value you have to make a function that will print the right 0 and 1. There are many of them on the internet. If you want to make yours, reading about bitwise operations could help you (you have to know about bitwise operations if you want to work with binaries anyways).
Now that you can print it as desired (hex as above or with your own binary function), you can redirect the output of printf with the sprintf function.
Its prototype is int sprintf( char* str, const char* format, ... ). str is the destination.
In your case, you will just need to replace the strcat line with something like sprintf( s1, "%2X\n", *opt); or sprintf( s1, "%s\n", your_binary_conversion_function(opt) );.
Note that using the former, you would have to increment s1 by 2 for each char in opt because one 8-bit value is 2 hexadecimal symbols.
You might also have to manage s1's memory by yourself, if it was not the case before.
Sources :
MK27's second answer
sprintf prototype
The function itoa takes an int argument for the value to be converted. If you pass it a value of char type it will be promoted to int. So how would the function know how many leading zeros you were expecting? And then if you had asked for radix 10 how many leading zeros would you expect? Actually, it suppresses leading zeros.
See ASCII Table, note the hex column and that for the ASCII characters the msb is 0. Printable ASCII characters range from 0x20 thru 0x7f. Unicode shares the characters 0x00 thru 0x7f.
Hex 20 thru 7f are binary 00100000 thru 01111111.
Not all binary values are printable characters and in some encodings are not legal values.
ASCII, hexadecimal, octal and binary are just ways of representing binary values. Printable characters are another way but not all binary values can be displayed, this is the main data that needs to be displayed or treated as character text is generally converted to hex-ascii or Base64.

Write Hex in C (byte)

I have to write a byte in hex to a file but I have a problem. For example.
If I have:
unsigned char a = 0x0;
and I write to a file using fwrite:
FILE *fp = fopen("file.txt",wb);
fwrite(&a,sizeof(unsigned char),1,fp);
fclose(fp);
When I open file I always see 20h, why not 00h?
So, I try to use:
fprintf(fp,"%x",a);
In this case I see 0h, but I need a full byte, not a nibble.
What should I do?
The first example is hard to believe, it ought to generate a file with a single byte with the value 0 in it. That's not really a text file though, so I guess your tools might fool you.
The second attempt is better, assuming you want a text file with a text representation of the value in it. To make it two hexadecimal digits, specify a width and padding:
fprintf(fp, "%02x", a);
Please note that there is no such thing as "a hex value". A value is a value; it can be represented as hex, but that's not part of the value. 100 decimal is the same thing as 64 in hex, and 1100100 in binary. The base only matters when representing the number as a string of digits, the number itself can't "be hex".

Resources