00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "net/rime/chameleon.h"
00042
00043 #include "net/rime.h"
00044
00045 #include <string.h>
00046
00047
00048
00049
00050
00051
00052 #ifdef CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES
00053 #define CHAMELEON_WITH_MAC_LINK_ADDRESSES CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES
00054 #else
00055 #define CHAMELEON_WITH_MAC_LINK_ADDRESSES 0
00056 #endif
00057
00058 struct bitopt_hdr {
00059 uint8_t channel[2];
00060 };
00061
00062 static const uint8_t bitmask[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0,
00063 0xf8, 0xfc, 0xfe, 0xff };
00064
00065 #define DEBUG 0
00066 #if DEBUG
00067 #include <stdio.h>
00068 #define PRINTF(...) printf(__VA_ARGS__)
00069 #else
00070 #define PRINTF(...)
00071 #endif
00072
00073
00074 uint8_t CC_INLINE
00075 get_bits_in_byte(uint8_t *from, int bitpos, int vallen)
00076 {
00077 uint16_t shifted_val;
00078
00079 shifted_val = (from[0] << 8) | from[1];
00080
00081
00082
00083
00084
00085
00086
00087 return (((shifted_val << bitpos) >> 8) & bitmask[vallen]) >> (8 - vallen);
00088 }
00089
00090 void
00091 get_bits(uint8_t *to, uint8_t *from, int bitpos, int vallen)
00092 {
00093 int i, bits;
00094
00095
00096 if(vallen < 8) {
00097 *to = get_bits_in_byte(from, bitpos, vallen);
00098 } else {
00099 if(bitpos == 0) {
00100 for(i = 0; i < vallen / 8; ++i) {
00101
00102
00103 to[i] = from[i];
00104 }
00105 bits = vallen & 7;
00106 if(bits) {
00107 to[i] = get_bits_in_byte(&from[i], 0, bits);
00108 }
00109 } else {
00110 for(i = 0; i < vallen / 8; ++i) {
00111
00112
00113 to[i] = get_bits_in_byte(&from[i], bitpos, 8);
00114 }
00115 bits = vallen & 7;
00116 if(bits) {
00117 to[i] = get_bits_in_byte(&from[i], bitpos, bits);
00118 }
00119 }
00120 }
00121 }
00122
00123 static int
00124 header_size(const struct packetbuf_attrlist *a)
00125 {
00126 int size, len;
00127
00128
00129
00130
00131 size = 0;
00132 for(; a->type != PACKETBUF_ATTR_NONE; ++a) {
00133 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00134 if(a->type == PACKETBUF_ADDR_SENDER ||
00135 a->type == PACKETBUF_ADDR_RECEIVER) {
00136
00137 continue;
00138 }
00139 #endif
00140
00141
00142
00143
00144 len = a->len;
00145
00146
00147
00148 size += len;
00149 }
00150 return size;
00151 }
00152
00153 void CC_INLINE
00154 set_bits_in_byte(uint8_t *target, int bitpos, uint8_t val, int vallen)
00155 {
00156 unsigned short shifted_val;
00157 shifted_val = val << (8 - bitpos + 8 - vallen);
00158
00159
00160 target[0] |= shifted_val >> 8;
00161 target[1] |= shifted_val & 0xff;
00162 }
00163
00164 void
00165 set_bits(uint8_t *ptr, int bitpos, uint8_t *val, int vallen)
00166 {
00167 int i, bits;
00168
00169
00170
00171
00172 if(vallen < 8) {
00173 set_bits_in_byte(ptr, bitpos, *val , vallen);
00174 } else {
00175 if(bitpos == 0) {
00176 for(i = 0; i < vallen / 8; ++i) {
00177
00178
00179 ptr[i] = val[i];
00180 }
00181 bits = vallen & 7;
00182 if(bits) {
00183 set_bits_in_byte(&ptr[i], 0, val[i] >> (8 - bits), bits);
00184 }
00185 } else {
00186 for(i = 0; i < vallen / 8; ++i) {
00187
00188
00189 set_bits_in_byte(&ptr[i], bitpos, val[i], 8);
00190 }
00191 bits = vallen & 7;
00192 if(bits) {
00193 set_bits_in_byte(&ptr[i], 0, val[i] >> (8 - bits + bitpos), bits);
00194 }
00195 }
00196 }
00197 }
00198
00199 #if 0
00200 static void
00201 printbin(int n, int digits)
00202 {
00203 int i;
00204 char output[128];
00205
00206 for(i = 0; i < digits; ++i) {
00207 output[digits - i - 1] = (n & 1) + '0';
00208 n >>= 1;
00209 }
00210 output[i] = 0;
00211
00212 printf(output);
00213 }
00214
00215 static void
00216 printhdr(uint8_t *hdr, int len)
00217 {
00218 int i, j;
00219
00220 j = 0;
00221 for(i = 0; i < len; ++i) {
00222 printbin(hdr[i], 8);
00223 printf(", ");
00224 ++j;
00225 if(j == 10) {
00226 printf("\n");
00227 j = 0;
00228 }
00229 }
00230
00231 if(j != 0) {
00232 printf("\n");
00233 }
00234 }
00235 #endif
00236
00237 static int
00238 pack_header(struct channel *c)
00239 {
00240 const struct packetbuf_attrlist *a;
00241 int hdrbytesize;
00242 int byteptr, bitptr, len;
00243 uint8_t *hdrptr;
00244 struct bitopt_hdr *hdr;
00245
00246
00247
00248
00249 hdrbytesize = c->hdrsize / 8 + ((c->hdrsize & 7) == 0? 0: 1);
00250 if(packetbuf_hdralloc(hdrbytesize + sizeof(struct bitopt_hdr)) == 0) {
00251 PRINTF("chameleon-bitopt: insufficient space for headers\n");
00252 return 0;
00253 }
00254 hdr = (struct bitopt_hdr *)packetbuf_hdrptr();
00255 hdr->channel[0] = c->channelno & 0xff;
00256 hdr->channel[1] = (c->channelno >> 8) & 0xff;
00257
00258 hdrptr = ((uint8_t *)packetbuf_hdrptr()) + sizeof(struct bitopt_hdr);
00259 memset(hdrptr, 0, hdrbytesize);
00260
00261 byteptr = bitptr = 0;
00262
00263 for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) {
00264 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00265 if(a->type == PACKETBUF_ADDR_SENDER ||
00266 a->type == PACKETBUF_ADDR_RECEIVER) {
00267
00268 PRINTF("%d.%d: pack_header leaving sender/receiver to link layer\n");
00269 continue;
00270 }
00271 #endif
00272 PRINTF("%d.%d: pack_header type %s, len %d, bitptr %d, ",
00273 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00274 packetbuf_attr_strings[a->type], a->len, bitptr);
00275
00276 len = a->len;
00277 byteptr = bitptr / 8;
00278 if(PACKETBUF_IS_ADDR(a->type)) {
00279 set_bits(&hdrptr[byteptr], bitptr & 7,
00280 (uint8_t *)packetbuf_addr(a->type), len);
00281 PRINTF("address %d.%d\n",
00282
00283 ((uint8_t *)packetbuf_addr(a->type))[0],
00284 ((uint8_t *)packetbuf_addr(a->type))[1]);
00285 } else {
00286 packetbuf_attr_t val;
00287 val = packetbuf_attr(a->type);
00288 set_bits(&hdrptr[byteptr], bitptr & 7,
00289 (uint8_t *)&val, len);
00290 PRINTF("value %d\n",
00291
00292 val);
00293 }
00294
00295 bitptr += len;
00296 }
00297
00298
00299 return 1;
00300 }
00301
00302 static struct channel *
00303 unpack_header(void)
00304 {
00305 const struct packetbuf_attrlist *a;
00306 int byteptr, bitptr, len;
00307 int hdrbytesize;
00308 uint8_t *hdrptr;
00309 struct bitopt_hdr *hdr;
00310 struct channel *c;
00311
00312
00313
00314
00315 hdr = (struct bitopt_hdr *)packetbuf_dataptr();
00316 if(packetbuf_hdrreduce(sizeof(struct bitopt_hdr)) == 0) {
00317 PRINTF("chameleon-bitopt: too short packet\n");
00318 return NULL;
00319 }
00320 c = channel_lookup((hdr->channel[1] << 8) + hdr->channel[0]);
00321 if(c == NULL) {
00322 PRINTF("chameleon-bitopt: input: channel %u not found\n",
00323 (hdr->channel[1] << 8) + hdr->channel[0]);
00324 return NULL;
00325 }
00326
00327 hdrptr = packetbuf_dataptr();
00328 hdrbytesize = c->hdrsize / 8 + ((c->hdrsize & 7) == 0? 0: 1);
00329 if(packetbuf_hdrreduce(hdrbytesize) == 0) {
00330 PRINTF("chameleon-bitopt: too short packet\n");
00331 return NULL;
00332 }
00333 byteptr = bitptr = 0;
00334 for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) {
00335 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00336 if(a->type == PACKETBUF_ADDR_SENDER ||
00337 a->type == PACKETBUF_ADDR_RECEIVER) {
00338
00339 continue;
00340 }
00341 #endif
00342 PRINTF("%d.%d: unpack_header type %s, len %d, bitptr %d\n",
00343 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00344 packetbuf_attr_strings[a->type], a->len, bitptr);
00345
00346 len = a->len;
00347 byteptr = bitptr / 8;
00348 if(PACKETBUF_IS_ADDR(a->type)) {
00349 rimeaddr_t addr;
00350 get_bits((uint8_t *)&addr, &hdrptr[byteptr], bitptr & 7, len);
00351 PRINTF("%d.%d: unpack_header type %s, addr %d.%d\n",
00352 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00353 packetbuf_attr_strings[a->type],
00354 addr.u8[0], addr.u8[1]);
00355 packetbuf_set_addr(a->type, &addr);
00356 } else {
00357 packetbuf_attr_t val = 0;
00358 get_bits((uint8_t *)&val, &hdrptr[byteptr], bitptr & 7, len);
00359
00360 packetbuf_set_attr(a->type, val);
00361 PRINTF("%d.%d: unpack_header type %s, val %d\n",
00362 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00363 packetbuf_attr_strings[a->type],
00364 val);
00365 }
00366
00367 bitptr += len;
00368 }
00369 return c;
00370 }
00371
00372 CC_CONST_FUNCTION struct chameleon_module chameleon_bitopt = {
00373 unpack_header,
00374 pack_header,
00375 header_size
00376 };
00377