Unpack hex-encoded NSData - objective-c

on peripheral:didReceiveWriteRequest a CBATTRequest returns hex-encoded NSData via request.value.
This is what I have tried
// Define struct
typedef struct __attribute__((packed)) {
UInt8 pktNo;
UInt8 ctrlCmd;
UInt8 txPowerRequest;
UInt16 uuid;
UInt16 userPayload; // how to store 15 octets?
} Packet;
// Unpack
Packet *packet = (Packet *)request.value.bytes;
if (packet) {
UInt8 pktNo = packet->pktNo;
UInt8 cmd = packet->ctrlCmd;
UInt8 tx = packet->txPowerRequest;
UInt16 uuid = packet->uuid;
UInt16 payload = packet->userPayload;
NSLog(#"pktNo: %hhu, cmd: %hhu, tx: %hhu, uuid: %hu, payload: %hu", pktNo, cmd, tx, uuid, payload);
}
Console
pktNo: 121, cmd: 202, tx: 130, uuid: 48321, payload: 21421
First, these numbers look inaccurate, and I'm uncertain about what format this is even in, since the following analogous values I got from debugging tool don't seem to match.
Default: raw strings?
packet Packet * 0x281af0cc0 0x0000000281af0cc0
pktNo UInt8 'y'
ctrlCmd UInt8 '\xca'
txPowerRequest UInt8 '\x82'
uuid UInt16 48321
userPayload UInt16 21421

The hex string representation of your NSData is apparently:
<79ca82c1 bcad530e 016a1435 127993ee 01ef7579>
That translates to:
The 0x79 is the PKT, 121 in decimal
The 0xca is the CMD, 202 in decimal
The 0x82 is the TXP, 130 in decimal
The 0xbcc1 is the UUID, 48321 in decimal
The PAYLOAD is ad 53 0e 01 6a 14 35 12 79 93 ee 01 ef 75 79
So, you can use:
typedef struct __attribute__((packed)) {
UInt8 pktNo;
UInt8 ctrlCmd;
UInt8 txPowerRequest;
UInt16 uuid;
UInt8 userPayload[15];
} Packet;
Which you can populate with:
Packet packet = {};
assert(data.length == sizeof(Packet));
memcpy(&packet, data.bytes, sizeof(Packet));
Note, I didn’t just set the packet to a pointer to the bytes of the NSData, because if the NSData is deallocated, you don’t want to use a pointer to that deallocated memory. Instead, copy the bytes to your packet struct (perhaps checking to make sure the two match in size).
In the interest of full disclosure, the above makes a somewhat cavalier assumption that endianness of the payload matches that of device running your app. You theoretically might want to make the UUID a UInt8 uuid[2], instead, and then if you need the UUID value, recalculate it from those two octets.

Related

Why the bitfield's least significant bit is promoted to MSb during typecasting in the below program?

Why do we get this value as output:- ffffffff
struct bitfield {
signed char bitflag:1;
};
int main()
{
unsigned char i = 1;
struct bitfield *var = (struct bitfield*)&i;
printf("\n %x \n", var->bitflag);
return 0;
}
I know that in a memory block of size equal to the data-type, the first bit is used to represent if it is positive(0) or negative(1); when interpreted as a signed data-type. But, still can't figure out why -1 (ffffffff) is printed. When the struct with only one bit set, I was expecting that when it gets promoted to a 1 byte char. Because, my machine is a little-endian and I was expecting that one bit in the field to be interpreted as the LSb in my 1 byte character.
Can somehow please explain. I'm really confused.

recvfrom for storing in 2D Char array

trying to collect 1261 UDP packet in 2D Char array using recvfrom function
define RxBuffSize 1514
define TotalPacket 1261
char RxBuff[RxBuffSize] = {0};
and the code i am trying to use is:
for (Count =0; Count <= TotalPacket; Count++)
{
recvfrom(sock, RxBuff[Count],RxBuffSize,0,(struct sockaddr *)&Sender_addr, &Sender_addrlen);
}
or no idea how to start just wanted to store all 1261 packets into RxBuff so that I can access packet data by its packet number for getting the data from packet by its packet number.
printf("%x ",Payload[packetno][data]);
You'll need enough space to store all of the packets contiguously. You can either statically allocate a 2D array
char RxBuff [RxBuffSize][1261];
or use calloc
char *RxBuff = calloc(RxBuffSize, 1261);
Then loop over recvfrom 1261 times just like in your question:
for (Count = 0; Count <= TotalPacket; Count++)
{
recvfrom(sock, RxBuff[Count],RxBuffSize,0,(struct sockaddr *)&Sender_addr, &Sender_addrlen);
}

read a text file into a binary tree but get run time error

I'm having run time error in addStu function when trying to read data from input file to binary tree, is there anything wrong with the format or pointer usage?
This is my code for reading file:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "BST_ADT.h"
// Structure
typedef struct
{
char* name;
char* market;
char* initial;
float stock;
}STUDENT;
// Prototype Delarations
void addStu (BST_TREE* list);
//void deleteStu (BST_TREE* list);
//void findStu (BST_TREE* list);
//void printList (BST_TREE* list);
//int compareStu (void* stu1, void* stu2);
//void processStu (void* dataPtr);
int main (void)
{
// Local Definitions
BST_TREE* list;
// Statements
list = BST_Create(compareStu);
addStu(list);
deleteStu(list);
findStu (list);
printList(list);
return 0;
}
/*===================== addStu =========================*/
void addStu (BST_TREE* list)
{
// Local Declarations
STUDENT* stuPtr;
FILE* fp;
char fileName[25];
char buffer [100];
// Statements
stuPtr = (STUDENT*)malloc (sizeof (STUDENT));
printf("Enter the file name: ");
gets(fileName);
fp = fopen(fileName, "r");
if(fp == NULL)
{
printf("Error cannot open the file!\n");
exit(101);
}
while(fgets(buffer, 100, fp) != NULL)
{
if (!stuPtr)
printf("MEmory overflow!\n"), exit(101);
sscanf(buffer, "%s %s %s %f", stuPtr->name, stuPtr->market, stuPtr->initial, &(stuPtr->stock));;
} // end while
BST_Insert(list, stuPtr);
} //addStu
this is my input:
Microsoft Corporation; NASDAQ MSFT 259.94B
Yahoo! Inc.; NASDAQ YHOO 37.67B
Baidu.com, Inc. (ADR); NASDAQ BIDU 8.64B
CNET Networks, Inc.; NASDAQ CNET 1.13B
QuickLogic Corporation; NASDAQ QUIK 88.62M
Answers Corporation; NASDAQ ANSW 53.49M
Apple Inc.; NASDAQ AAPL 114.17B
EarthLink, Inc.; NASDAQ ELNK 890.68M
Amazon.com, Inc.; NASDAQ AMZN 28.28B
IAC/InterActiveCorp; NASDAQ IACI 6.09B
Time Warner Inc.; NYSE TWX 57.29B
You havent initialize the strings in your structure. Bear in mind that char* name is a POINTER to a string, NOT the string itself. Same with the other strings. In a 32 bit app, the size of char* is actually 4 bytes. That means your entire structure is 16 bytes (3 * 4 byte pointers + 1 4 byte float).
You will need to allocate space for your strings and assign them to your structure before you can try populating them from the file data. Otherwise your structure will be pointing to whatever garbage was on the heap at the pointer name* as the address of your string.
EDIT:
Try allocating some space for your strings:
stuPtr->name = (char*) malloc(128 * sizeof(char));
This will create a string large enough to hold 127 chars. Do the same for your other strings.
A very, very long time since I've used used C, but the fact that you are not allocating space for STUDENT elements shouts out.
When you declare
// Structure
typedef struct
{
char* name;
char* market;
char* initial;
float stock;
}STUDENT;
You are declaring space for 16 bytes (assuming 4 byte pointers and floats).
Now each of the pointers name, market and initial have undefined values when created as a STUDENT. They point to random space - if you VERY lucky they are initialised to nulls.
A better definition for STUDENT would be
typedef struct
{
char name[MAX_NAME_SIZE];
char market[MAX_MARKET_SIZE];
char initial[MAX_INITIAL_SIZE];
float stock;
}STUDENT;
Where the MAXs are defines to be added earlier.
The other alternative would be to assign space just after creation
stuPtr = (STUDENT*)malloc (sizeof (STUDENT));
stuPtr->name = (char *)malloc(MAX_NAME_SIZE);
stuPtr->market = (char *)malloc(MAX_MARKET_SIZE);
stuPtr->initial = (char *)malloc(MAX_INITIAL_SIZE);
Array names are pointers to the first element of an array, so name and &name[0] are the same.
Hope this helps.
Andrew

Artnet Packet Structure

Even though I have found so many Libraries that allows programmers to use the Artnet/ArtnetDMX protocol I haven't found the correct structure to send out Artnet in code (To a socket).
The structure is given but, I just can't figure out in what order bytes should be send.
Do i send a byte to a universe One by One, or do I need to send a Byte array with all the values?
Doesn anyone have experience in sending Artnet over UDP?
This the structure given on wikipedia: http://i.stack.imgur.com/wUjzd.png
I use the following struct for Art-Net v2
typedef struct {
char ID[8]; //"Art-Net"
UInt16 OpCode; // See Doc. Table 1 - OpCodes eg. 0x5000 OpOutput / OpDmx
UInt16 version; // 0x0e00 (aka 14)
UInt8 seq; // monotonic counter
UInt8 physical; // 0x00
UInt8 subUni; // low universe (0-255)
UInt8 net; // high universe (not used)
UInt16 length; // data length (2 - 512)
uint8_t data[512]; // universe data
} ArtnetDmx;
If you want to write an Art-Net application you should really read the documentation located on Artistic Licence.
I would follow the version 2 (14) specification as that version 3 is quite rare in the wild.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Artnet
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string id;
public short opCode;
public byte protocolHi;
public byte protocolLo;
public byte sequence;
public byte physical;
public short universe;
public short length;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
public byte[] data;
}

Union struct: printing struct member of type uint32_t skips two bytes and prints wrong value

Need help with union struct. I'm receiving byte stream that consists of various packets, so I'm putting the byte data into union struct and accessing needed data via struct members. The problem is with uint32_t type member - the read skips its two bytes and shows wrong value when accessing via its member. Here's full demo code:
PacketUtils.h
#include <stdint.h>
typedef struct {
uint8_t startSymbol;
uint8_t packetType;
uint32_t deviceId;
uint16_t packetCRC;
} PacketData;
typedef union {
uint8_t *bytes; // stores raw bytes
PacketData *packet;
} Packet;
// Puts bytes into predefined struct
void getPacketFromBytes(void *bytes, Packet *packetRef);
PacketUtils.c
#include <stdio.h>
#include "UnionStruct.h"
void getPacketFromBytes(void *bytes, Packet *packetRef)
{
uint8_t *rawBytes = (uint8_t *)bytes;
packetRef->bytes = rawBytes;
}
Calling code:
// sample byte data
uint8_t packetBytes[] = {0x11, 0x02, 0x01, 0x01, 0x01, 0x03, 0xbb, 0xbd};
Packet packetRef;
getPacketFromBytes(packetBytes, &packetRef);
printf("%x\n", packetRef.packet->startSymbol); // good - prints 0x11
printf("%x\n", packetRef.packet->packetType); // good - prints 0x02
printf("%x\n", packetRef.packet->deviceId); // bad - prints bd bb 03 01
printf("%x\n", packetRef.packet->packetCRC); // bad - prints 36 80 (some next values in memory)
Everything is OK when PacketData struct consist of uint8_t or uint16_t type members then the print shows correct values. However, printing deviceId of type uint32_t skips two bytes (0x01 0x01) and grabs last 4 bytes. Printing packetCRC prints the values out of given byte array - some two values in memory, like packetBytes[12] and packetBytes[13]. I can't figure out why it skips two bytes...
The problem is due to the fields being padded out to default alignment on your platform. On most modern architectures 32-bit values are most efficient when read/written to a 32-bit word aligned address.
In gcc you can avoid this by using a special attribute to indicate that the structure is "packed". See here:
http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Type-Attributes.html
So struct definition would look something like this:
typedef struct {
uint8_t startSymbol;
uint8_t packetType;
uint32_t deviceId;
uint16_t packetCRC;
} PacketData __attribute__((packed));
The 32-bit number will be aligned on a 4-byte boundary only. If you move it to the start of your struct, it may just work as you want.
Processors usually are optimised to fetch data on multiples of the datum size - 4 bytes for 32-bit, 8 bytes for 64-bit... - and the compiler knows this and adds gaps into the data structures to make sure that the processor can fetch the data efficiently.
If you don't want to deal with the padding and can't move the data structure around, you could define
typedef struct {
uint8_t startSymbol;
uint8_t packetType;
uint16_t deviceIdLow;
uint16_t deviceIdHigh;
uint16_t packetCRC;
} PacketData;
and then just write
uint32_t deviceID = packetRef.packet->deviceIdLow | (packetRef.packet->deviceIdLow << 16);