|
View:
New views
11 Messages
—
Rating Filter:
Alert me
|
|
|
Programming between big and little endianI have a program that compiles and works fine on Debian for the NSLU2.
I try to compile it under unslung and it compiles and links with no errors. Yet the program fails at the first case statement that checks a 32 bit value passed to it. could this be that uNSLUng 6.10 is big endian and Debian for the NSLU2 is little endian ? I define this value in the header file. #define CHALLENGE_TEXT_LEN 8 enum { NET_HOSTFS_CMD_HELLO = 0x00DA5800, NET_HOSTFS_CMD_IOINIT, NET_HOSTFS_CMD_IOEXIT, NET_HOSTFS_CMD_IOOPEN, NET_HOSTFS_CMD_IOCLOSE, NET_HOSTFS_CMD_IOREAD, NET_HOSTFS_CMD_IOWRITE, NET_HOSTFS_CMD_IOLSEEK, NET_HOSTFS_CMD_IOIOCTL, NET_HOSTFS_CMD_IOREMOVE, NET_HOSTFS_CMD_IOMKDIR, NET_HOSTFS_CMD_IORMDIR, NET_HOSTFS_CMD_IODOPEN, NET_HOSTFS_CMD_IODCLOSE, NET_HOSTFS_CMD_IODREAD, NET_HOSTFS_CMD_IOGETSTAT, NET_HOSTFS_CMD_IOCHSTAT, NET_HOSTFS_CMD_IORENAME, NET_HOSTFS_CMD_IODEVCTL, NET_HOSTFS_CMD_GETKEY //GETKEY } This is my code section switch (cmd) { case NET_HOSTFS_CMD_HELLO: process_func = process_hello; break; case NET_HOSTFS_CMD_IOINIT: process_func = process_ioinit; break; case NET_HOSTFS_CMD_IOEXIT: process_func = process_ioexit; break; case NET_HOSTFS_CMD_IOOPEN: process_func = process_ioopen; break; case NET_HOSTFS_CMD_IOCLOSE: process_func = process_ioclose; break; case NET_HOSTFS_CMD_IOREAD: process_func = process_ioread; break; case NET_HOSTFS_CMD_IOWRITE: process_func = process_iowrite; break; case NET_HOSTFS_CMD_IOLSEEK: process_func = process_iolseek; break; case NET_HOSTFS_CMD_IOREMOVE: process_func = process_ioremove; break; case NET_HOSTFS_CMD_IOMKDIR: process_func = process_iomkdir; break; case NET_HOSTFS_CMD_IORMDIR: process_func = process_iormdir; break; case NET_HOSTFS_CMD_IODOPEN: process_func = process_iodopen; break; case NET_HOSTFS_CMD_IODCLOSE: process_func = process_iodclose; break; case NET_HOSTFS_CMD_IODREAD: process_func = process_iodread; break; case NET_HOSTFS_CMD_IOGETSTAT: process_func = process_iogetstat; break; case NET_HOSTFS_CMD_IOCHSTAT: process_func = process_iochstat; break; case NET_HOSTFS_CMD_IORENAME: process_func = process_iorename; break; case NET_HOSTFS_CMD_GETKEY: process_func = process_getkey; break; default: printf("Unknown command [%d] sock [%d]: 0x%08X\n", spawn_idx, sock, cmd); } This is the result I get from my program running Listening for incoming connections... Accepted new connection from IP 192.168.1.7 Adding multi-session for IP 192.168.1.7 Adding multi-session for IP 192.168.1.7 Adding multi-session for IP 192.168.1.7 Creating child for index #0... Assigning pid (526) to index #0 cmd [0] sock [4]: 0058DA00 Unknown command [0] sock [4]: 0x0058DA00 It looks like I am getting the correct input yet it fails to compare Or is it my command is 32 bit and uNSLUng 6.10 does not handle 32 bit correctly ? |
|
|
Re: Programming between big and little endianRoger Gilbert wrote:
> I have a program that compiles and works fine on Debian for the NSLU2. > > I try to compile it under unslung and it compiles and links with no errors. > > Yet the program fails at the first case statement that checks a 32 bit > value passed to it. > > could this be that uNSLUng 6.10 is big endian and Debian for the NSLU2 > is little endian ? > > I define this value in the header file. > > #define CHALLENGE_TEXT_LEN 8 > > enum > { > NET_HOSTFS_CMD_HELLO = 0x00DA5800, > NET_HOSTFS_CMD_IOINIT, > NET_HOSTFS_CMD_IOEXIT, > NET_HOSTFS_CMD_IOOPEN, > NET_HOSTFS_CMD_IOCLOSE, > NET_HOSTFS_CMD_IOREAD, > NET_HOSTFS_CMD_IOWRITE, > NET_HOSTFS_CMD_IOLSEEK, > NET_HOSTFS_CMD_IOIOCTL, > NET_HOSTFS_CMD_IOREMOVE, > NET_HOSTFS_CMD_IOMKDIR, > NET_HOSTFS_CMD_IORMDIR, > NET_HOSTFS_CMD_IODOPEN, > NET_HOSTFS_CMD_IODCLOSE, > NET_HOSTFS_CMD_IODREAD, > NET_HOSTFS_CMD_IOGETSTAT, > NET_HOSTFS_CMD_IOCHSTAT, > NET_HOSTFS_CMD_IORENAME, > NET_HOSTFS_CMD_IODEVCTL, > NET_HOSTFS_CMD_GETKEY //GETKEY > } > > > This is my code section > > switch (cmd) > { > case NET_HOSTFS_CMD_HELLO: > process_func = process_hello; > break; > > case NET_HOSTFS_CMD_IOINIT: > process_func = process_ioinit; > break; > > case NET_HOSTFS_CMD_IOEXIT: > process_func = process_ioexit; > break; > > case NET_HOSTFS_CMD_IOOPEN: > process_func = process_ioopen; > break; > > case NET_HOSTFS_CMD_IOCLOSE: > process_func = process_ioclose; > break; > > case NET_HOSTFS_CMD_IOREAD: > process_func = process_ioread; > break; > > case NET_HOSTFS_CMD_IOWRITE: > process_func = process_iowrite; > break; > > case NET_HOSTFS_CMD_IOLSEEK: > process_func = process_iolseek; > break; > > case NET_HOSTFS_CMD_IOREMOVE: > process_func = process_ioremove; > break; > > case NET_HOSTFS_CMD_IOMKDIR: > process_func = process_iomkdir; > break; > > case NET_HOSTFS_CMD_IORMDIR: > process_func = process_iormdir; > break; > > case NET_HOSTFS_CMD_IODOPEN: > process_func = process_iodopen; > break; > > case NET_HOSTFS_CMD_IODCLOSE: > process_func = process_iodclose; > break; > > case NET_HOSTFS_CMD_IODREAD: > process_func = process_iodread; > break; > > case NET_HOSTFS_CMD_IOGETSTAT: > process_func = process_iogetstat; > break; > > case NET_HOSTFS_CMD_IOCHSTAT: > process_func = process_iochstat; > break; > > case NET_HOSTFS_CMD_IORENAME: > process_func = process_iorename; > break; > > case NET_HOSTFS_CMD_GETKEY: > process_func = process_getkey; > break; > > default: > printf("Unknown command [%d] sock [%d]: 0x%08X\n", > spawn_idx, sock, cmd); > } > > > This is the result I get from my program running > > Listening for incoming connections... > Accepted new connection from IP 192.168.1.7 > Adding multi-session for IP 192.168.1.7 > Adding multi-session for IP 192.168.1.7 > Adding multi-session for IP 192.168.1.7 > Creating child for index #0... > Assigning pid (526) to index #0 > cmd [0] sock [4]: 0058DA00 > Unknown command [0] sock [4]: 0x0058DA00 > > > It looks like I am getting the correct input yet it fails to compare > > Or is it my command is 32 bit and uNSLUng 6.10 does not handle 32 bit > correctly ? That looks to be an endian-related problem -- note that the cmd differs from the value you specified in the enum. In this case, I'm willing to bet that you are reading values that should be converted to/from network byte order -- see the documentation on the htonl() function, for example. Mike (mwester) |
|
|
Re: Programming between big and little endianCan you tell me where to find that documentation ?
--- On Mon, 7/14/08, Mike (mwester) <mwester@...> wrote: From: Mike (mwester) <mwester@...> Subject: Re: [nslu2-linux] Programming between big and little endian To: nslu2-linux@... Date: Monday, July 14, 2008, 5:32 PM Roger Gilbert wrote: > I have a program that compiles and works fine on Debian for the NSLU2. > > I try to compile it under unslung and it compiles and links with no errors. > > Yet the program fails at the first case statement that checks a 32 bit > value passed to it. > > could this be that uNSLUng 6.10 is big endian and Debian for the NSLU2 > is little endian ? > > I define this value in the header file. > > #define CHALLENGE_TEXT_ LEN 8 > > enum > { > NET_HOSTFS_CMD_ HELLO = 0x00DA5800, > NET_HOSTFS_CMD_ IOINIT, > NET_HOSTFS_CMD_ IOEXIT, > NET_HOSTFS_CMD_ IOOPEN, > NET_HOSTFS_CMD_ IOCLOSE, > NET_HOSTFS_CMD_ IOREAD, > NET_HOSTFS_CMD_ IOWRITE, > NET_HOSTFS_CMD_ IOLSEEK, > NET_HOSTFS_CMD_ IOIOCTL, > NET_HOSTFS_CMD_ IOREMOVE, > NET_HOSTFS_CMD_ IOMKDIR, > NET_HOSTFS_CMD_ IORMDIR, > NET_HOSTFS_CMD_ IODOPEN, > NET_HOSTFS_CMD_ IODCLOSE, > NET_HOSTFS_CMD_ IODREAD, > NET_HOSTFS_CMD_ IOGETSTAT, > NET_HOSTFS_CMD_ IOCHSTAT, > NET_HOSTFS_CMD_ IORENAME, > NET_HOSTFS_CMD_ IODEVCTL, > NET_HOSTFS_CMD_ GETKEY //GETKEY > } > > > This is my code section > > switch (cmd) > { > case NET_HOSTFS_CMD_ HELLO: > process_func = process_hello; > break; > > case NET_HOSTFS_CMD_ IOINIT: > process_func = process_ioinit; > break; > > case NET_HOSTFS_CMD_ IOEXIT: > process_func = process_ioexit; > break; > > case NET_HOSTFS_CMD_ IOOPEN: > process_func = process_ioopen; > break; > > case NET_HOSTFS_CMD_ IOCLOSE: > process_func = process_ioclose; > break; > > case NET_HOSTFS_CMD_ IOREAD: > process_func = process_ioread; > break; > > case NET_HOSTFS_CMD_ IOWRITE: > process_func = process_iowrite; > break; > > case NET_HOSTFS_CMD_ IOLSEEK: > process_func = process_iolseek; > break; > > case NET_HOSTFS_CMD_ IOREMOVE: > process_func = process_ioremove; > break; > > case NET_HOSTFS_CMD_ IOMKDIR: > process_func = process_iomkdir; > break; > > case NET_HOSTFS_CMD_ IORMDIR: > process_func = process_iormdir; > break; > > case NET_HOSTFS_CMD_ IODOPEN: > process_func = process_iodopen; > break; > > case NET_HOSTFS_CMD_ IODCLOSE: > process_func = process_iodclose; > break; > > case NET_HOSTFS_CMD_ IODREAD: > process_func = process_iodread; > break; > > case NET_HOSTFS_CMD_ IOGETSTAT: > process_func = process_iogetstat; > break; > > case NET_HOSTFS_CMD_ IOCHSTAT: > process_func = process_iochstat; > break; > > case NET_HOSTFS_CMD_ IORENAME: > process_func = process_iorename; > break; > > case NET_HOSTFS_CMD_ GETKEY: > process_func = process_getkey; > break; > > default: > printf("Unknown command [%d] sock [%d]: 0x%08X\n", > spawn_idx, sock, cmd); > } > > > This is the result I get from my program running > > Listening for incoming connections. .. > Accepted new connection from IP 192.168.1.7 > Adding multi-session for IP 192.168.1.7 > Adding multi-session for IP 192.168.1.7 > Adding multi-session for IP 192.168.1.7 > Creating child for index #0... > Assigning pid (526) to index #0 > cmd [0] sock [4]: 0058DA00 > Unknown command [0] sock [4]: 0x0058DA00 > > > It looks like I am getting the correct input yet it fails to compare > > Or is it my command is 32 bit and uNSLUng 6.10 does not handle 32 bit > correctly ? That looks to be an endian-related problem -- note that the cmd differs from the value you specified in the enum. In this case, I'm willing to bet that you are reading values that should be converted to/from network byte order -- see the documentation on the htonl() function, for example. Mike (mwester) |
|
|
Re: Programming between big and little endianRoger Gilbert wrote:
> Can you tell me where to find that documentation ? google htonl This is a very common library; it's been around since the dawn of TCP/IP and should be referenced and part of the examples for any bit of TCP/IP programming you find in any competent reference manual. Mike (mwester) |
|
|
Re: Programming between big and little endian> Can you tell me where to find that documentation ? Try a man page under Linux, or just Google it. Just a couple of notes to help you: > > enum > > { > > NET_HOSTFS_CMD_ HELLO = 0x00DA5800, On a little-endian host, these bytes will look like: 00 58 DA 00 whereas on a big-endian host, they will look like: 00 DA 58 00 So on your server, you use that header, and send the bytes in big-endian network byte-order using something like this: uint32_t cmd = htonl(NET_HOSTFS_CMD); write(fd, &cmd, 4); whereas on your client, you read the big-endian bytes, and convert them to host-order using something like: uint32_t cmd; read(fd, &cmd, 4); cmd = ntohl(cmd); switch (cmd) { case NET_HOSTFS_CMD: This complimentary sequence ensures that the enum definition is used in the hosts native endian format, but the command sequences over the wire are in big-endian, or network byte-order, format. In addition to endianness issues, if you are transmitting data structures, you'll want to worry about alignment (packing of structure members). Cheers, Dave |
|
|
Re: Programming between big and little endianYes I am transmitting large data structures.
This is a system that runs a disk data structure over wifi. The NSLU2 translates commands from the wireless sends or reads to a usb hard drive and sends the resultant data back to the wireless link. If course there is very heavy error checking. --- On Mon, 7/14/08, David Hawkins <dwh@...> wrote: From: David Hawkins <dwh@...> Subject: Re: [nslu2-linux] Programming between big and little endian To: nslu2-linux@... Date: Monday, July 14, 2008, 6:10 PM > Can you tell me where to find that documentation ? Try a man page under Linux, or just Google it. Just a couple of notes to help you: > > enum > > { > > NET_HOSTFS_CMD_ HELLO = 0x00DA5800, On a little-endian host, these bytes will look like: 00 58 DA 00 whereas on a big-endian host, they will look like: 00 DA 58 00 So on your server, you use that header, and send the bytes in big-endian network byte-order using something like this: uint32_t cmd = htonl(NET_HOSTFS_ CMD); write(fd, &cmd, 4); whereas on your client, you read the big-endian bytes, and convert them to host-order using something like: uint32_t cmd; read(fd, &cmd, 4); cmd = ntohl(cmd); switch (cmd) { case NET_HOSTFS_CMD: This complimentary sequence ensures that the enum definition is used in the hosts native endian format, but the command sequences over the wire are in big-endian, or network byte-order, format. In addition to endianness issues, if you are transmitting data structures, you'll want to worry about alignment (packing of structure members). Cheers, Dave |
|
|
Re: Programming between big and little endianThank you very much
--- On Mon, 7/14/08, Mike (mwester) <mwester@...> wrote: From: Mike (mwester) <mwester@...> Subject: Re: [nslu2-linux] Programming between big and little endian To: nslu2-linux@... Date: Monday, July 14, 2008, 6:08 PM Roger Gilbert wrote: > Can you tell me where to find that documentation ? google htonl This is a very common library; it's been around since the dawn of TCP/IP and should be referenced and part of the examples for any bit of TCP/IP programming you find in any competent reference manual. Mike (mwester) |
|
|
Re: Programming between big and little endianHi Roger,
> Yes I am transmitting large data structures. > > This is a system that runs a disk data structure over wifi. > > The NSLU2 translates commands from the wireless sends or reads to a usb > hard drive and sends the resultant data back to the wireless link. > > If course there is very heavy error checking. I'm curious, what's wrong with using NFS? Note that NFS uses RPC (remote procedure calls) and XDR (external data representation). XDR is a machine independent binary format. The byte order is defined as big-endian, and the packing rules for 8-bit data, 16-bit data, 32-bit data, etc are defined. NFS data is encoded and decoded into XDR format before being transmitted over-the-wire. So if you are reinventing the wheel here, you might want to take a look at this stuff. Unix Network Programming, by W. R. Stevens has some nice discussion on this. On the otherhand if you are defining your own protocol, and you happen to use C++, the ACE C++ library has an implementation of the Common Data Represenation (CDR) machine independent binary format. CDR uses a 'reader-make-right' scheme where the endianness of a serialized object is encoded at the start of the data stream, and the reader has to byte-swap if its a different endianness. Cheers, Dave |
|
|
Re: Programming between big and little endianThe hand held unit has no structures. Never intended to have mass storage other than a flash card. The driver we have done makes the hand held think it has a storage card that is as big as the usb hard drive you plug into the NSLU2. So if you plug in a 750 gig hard drive the hand held thinks it has a 750 gig flash card.
The protocol is self defined and not based on any other standards. --- On Mon, 7/14/08, David Hawkins <dwh@...> wrote: From: David Hawkins <dwh@...> Subject: Re: [nslu2-linux] Programming between big and little endian To: nslu2-linux@... Date: Monday, July 14, 2008, 6:39 PM Hi Roger, > Yes I am transmitting large data structures. > > This is a system that runs a disk data structure over wifi. > > The NSLU2 translates commands from the wireless sends or reads to a usb > hard drive and sends the resultant data back to the wireless link. > > If course there is very heavy error checking. I'm curious, what's wrong with using NFS? Note that NFS uses RPC (remote procedure calls) and XDR (external data representation) . XDR is a machine independent binary format. The byte order is defined as big-endian, and the packing rules for 8-bit data, 16-bit data, 32-bit data, etc are defined. NFS data is encoded and decoded into XDR format before being transmitted over-the-wire. So if you are reinventing the wheel here, you might want to take a look at this stuff. Unix Network Programming, by W. R. Stevens has some nice discussion on this. On the otherhand if you are defining your own protocol, and you happen to use C++, the ACE C++ library has an implementation of the Common Data Represenation (CDR) machine independent binary format. CDR uses a 'reader-make- right' scheme where the endianness of a serialized object is encoded at the start of the data stream, and the reader has to byte-swap if its a different endianness. Cheers, Dave |
|
|
Re: Programming between big and little endianHi Roger,
> The hand held unit has no structures. Never intended to > have mass storage other than a flash card. The driver > we have done makes the hand held think it has a storage > card that is as big as the usb hard drive you plug into > the NSLU2. So if you plug in a 750 gig hard drive the hand > held thinks it has a 750 gig flash card. > > The protocol is self defined and not based on any other standards. Sorry, this isn't clear to me. Perhaps you could provide a few more details - if you're allowed :) Let me see if I have this correct ... So you have a handheld unit with a WiFi connection to the NSLU2. The handheld unit has a 'driver' that converts its file access into Wifi transactions to the NSLU2. By the sounds of it, the NSLU2 runs a server application that the handheld 'driver' communicates with. An 'application' on the handheld reads and writes files using its filesystem driver interface, eg. read()/write() function calls. The handheld 'driver' sends write data or read requests to the server running on the NSLU2, and that server performs NSLU2 harddrive accesses. As far as the handheld is concerned its writing byte-streams to a file, whereas infact the byte-stream is being transmitted to the NSLU2 and it writes to a file. BTW; is the handheld running an OS, or bare-metal code with a Wifi connection? What is the processor? Regarding structures and endianness, there's another aspect to note: Lets say the handheld writes a file with the integer value 0x11223344. If I open that same file on a PC, then depending on the enddianness of the handheld processor I would read 0x11223344, or 0x44332211. This issue is no different than me writing an integer to a file using a big-endian PowerPC processor, and then opening it to interpret it using an x86 processor. Now lets say I have some PC support software for the user of the handheld. That PC can also have a Wifi server, and run identically to the NSLU2. With the ntohl/hlton additions to your server, the server running on the x86 will now appear no different than the server running on the NSLU2. They'll both serve the command codes in big-endian format. Now what about support software. I would assume for debugging purposes you'd want to be able to read any file written by the handheld. You have two solutions there; use the knowledge of the handheld processor endianness to interpret the file, or have the handheld write in a machine independent binary format. Obviously the second method is more complex, but it does make changing the processor in the handheld easier, since the support software would not change. In my applications I have multiple big-endian or little-endian processors communicating with little-endian x86 processors. The processors all communicate using CDR encoded data, thus eliminating any machine specific code (the machine specific code is determined during compilation by the CDR encode and decode functions). Note that these are just a few comments on available options, no offense regarding your solution is intended. Cheers, Dave |
|
|
Re: Programming between big and little endianDave,
I am an old school real time machine code programmer. I am just learning to program in C, this is all new to me. I did not write this original code. I was just trying to find out why it did not work when I compiled it to run on the NSLU2. The code functions perfectly on the little endian X86 in with Windows XP as the host. At least when it was programmed they used cygwin so it would run on the windows platform. The handheld side I do not have the source code for. It is a black box that just works. I only have the server side software that I am trying to debug.. Between reading someone else's code with zero comments in it, my trying to stretch my brain just learning C, and not having the other side, I am sort of a non swimmer in the deep end of the pool. I have never programmed network sockets so I am trying to learn that at the same time. Half of what you said I will have to Wiki or Google so that I can break it down into what I can understand. I should have learned C years ago. But at that time, the compilers were not that good and I had to count instruction cycle times in clock cycles of the processors I was working in. I was doing image recognition in assembler. I thought this was a good project to get my feet wet and learn on. I think I may have bit off more than I can chew, but I am stubborn and will keep at it. --- On Mon, 7/14/08, David Hawkins <dwh@...> wrote: From: David Hawkins <dwh@...> Subject: Re: [nslu2-linux] Programming between big and little endian To: nslu2-linux@... Date: Monday, July 14, 2008, 7:59 PM Hi Roger, > The hand held unit has no structures. Never intended to > have mass storage other than a flash card. The driver > we have done makes the hand held think it has a storage > card that is as big as the usb hard drive you plug into > the NSLU2. So if you plug in a 750 gig hard drive the hand > held thinks it has a 750 gig flash card. > > The protocol is self defined and not based on any other standards. Sorry, this isn't clear to me. Perhaps you could provide a few more details - if you're allowed :) Let me see if I have this correct ... So you have a handheld unit with a WiFi connection to the NSLU2. The handheld unit has a 'driver' that converts its file access into Wifi transactions to the NSLU2. By the sounds of it, the NSLU2 runs a server application that the handheld 'driver' communicates with. An 'application' on the handheld reads and writes files using its filesystem driver interface, eg. read()/write( ) function calls. The handheld 'driver' sends write data or read requests to the server running on the NSLU2, and that server performs NSLU2 harddrive accesses. As far as the handheld is concerned its writing byte-streams to a file, whereas infact the byte-stream is being transmitted to the NSLU2 and it writes to a file. BTW; is the handheld running an OS, or bare-metal code with a Wifi connection? What is the processor? Regarding structures and endianness, there's another aspect to note: Lets say the handheld writes a file with the integer value 0x11223344. If I open that same file on a PC, then depending on the enddianness of the handheld processor I would read 0x11223344, or 0x44332211. This issue is no different than me writing an integer to a file using a big-endian PowerPC processor, and then opening it to interpret it using an x86 processor. Now lets say I have some PC support software for the user of the handheld. That PC can also have a Wifi server, and run identically to the NSLU2. With the ntohl/hlton additions to your server, the server running on the x86 will now appear no different than the server running on the NSLU2. They'll both serve the command codes in big-endian format. Now what about support software. I would assume for debugging purposes you'd want to be able to read any file written by the handheld. You have two solutions there; use the knowledge of the handheld processor endianness to interpret the file, or have the handheld write in a machine independent binary format. Obviously the second method is more complex, but it does make changing the processor in the handheld easier, since the support software would not change. In my applications I have multiple big-endian or little-endian processors communicating with little-endian x86 processors. The processors all communicate using CDR encoded data, thus eliminating any machine specific code (the machine specific code is determined during compilation by the CDR encode and decode functions). Note that these are just a few comments on available options, no offense regarding your solution is intended. Cheers, Dave |
| Free Forum Powered by Nabble | Forum Help |