[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bluetooth-dev] Re: Porting to ARM



Peter Kjellerstedt wrote:

>
> struct iphdr
>   {
> #if __BYTE_ORDER == __LITTLE_ENDIAN
>     unsigned int ihl:4;
>     unsigned int version:4;
> #elif __BYTE_ORDER == __BIG_ENDIAN
>     unsigned int version:4;
>     unsigned int ihl:4;
> #else
> # error "Please fix <bits/endian.h>"
> #endif
>     u_int8_t tos;
>     u_int16_t tot_len;
>     ...
>   }
>
> It is not exactly beautiful code, but I believe it should work.
>
> //Peter

Hmm. I'm not sure that your example is correct. First , byte order does not
affect bits within the byte. Second, my linux/include/ip.h is using the macros
__LITTLE_ENDIAN_BITFIELD__, etc. -- where the pertinent substring is "BIT", as
opposed to byte.

So the example is not quite right. But will the idea still work? I could be
looking at it wrong, but I don't think it will.
Let's try it with the HCI header:

typedef struct cmd_pkt {
 u32 type:8;
#ifdef __LITTLE_ENDIAN
        u32 ocf:10;
        u32 ogf:6;
#elifdef __BIG_ENDIAN
        u32 ogf:6;
        u32 ocf:10;
#else
# error "Please fix <bits/endian.h>"
#endif
        u32 len:8;
        u8 data[256];
} __attribute__ ((packed)) cmd_pkt;

If I overlay this struct on the buffer and fill it out field by field, I think
that in the BIG_ENDIAN case the ocf and ogf fields will be laid out backwards
on the little-endian bytestream. I considered using a union so that we could do
a single field assignment to cover both the ocf and ogf bitfields, but
nonetheless the value will have to shifted and coerced into lining up right for
the assignment, so it doesn't really help to use unions.

I'm afraid that we're going to have to use something like this, and that we'll
have to do so everywhere bitfields appear that aren't evenly divisible by 8
bits:

*ptr++ = ocf_val & 0xff;
*ptr = ocf_val >> 8;
*ptr |= ogf_val << 2 & 0xfc;

Prove me wrong, please. But hurry, because I'm already changing code.

--Gordon