/* Gets the escaped stringified version of an attribute list. * * The string returned must be free()'d by the caller. * * If find_delta is set to true, only the attributes that have changed since * the last serialize are updated. */ SLPError SLPAttrSerialize(SLPAttributes attr_h, size_t *count, char **str, SLPBoolean find_delta) { struct xx_SLPAttributes *slp_attr = (struct xx_SLPAttributes *)attr_h; var_t *var; /* For iterating. */ unsigned int size; /* Size of the string to allocate. */ unsigned int var_count; /* To count the number of variables. */ char *build_str; /* The string that is being built. */ char *cur; /* Current location within the already allocated str. */ size = 0; var_count = 0; /***** Find the size of string needed for the attribute string. *****/ for (var = slp_attr->attrs; var != NULL; var = var->next) { /*** Skip old attributes. ***/ if (find_delta == SLP_TRUE && var->modified == SLP_FALSE) { continue; } /*** Get size of tag ***/ size += var->tag_len; /*** Count the size needed for the value list ***/ if (var->type != SLP_KEYWORD) { value_t *value; /** Get size of data **/ value = var->list; while (value) { size += value->escaped_len; value = value->next; } /** Count number of commas needed for multivalued attributes. **/ assert(var->list_size >= 0); size += (var->list_size - 1) * VAR_SEPARATOR_LEN; /** Count the semantics needed to store a multivalue list **/ size += VAR_NON_KEYWORD_SEMANTIC_LEN; } else { assert(var->list == NULL); } /*** Count number of variables ***/ var_count++; } /*** Count the number of characters between attributes. ***/ if (var_count > 0) { size += (var_count - 1) * VAR_SEPARATOR_LEN; } /***** Create the string. *****/ build_str = (char *)malloc( size + 1); if (build_str == NULL) { return SLP_MEMORY_ALLOC_FAILED; } build_str[0] = '\0'; /***** Add values *****/ cur = build_str; for (var = slp_attr->attrs; var != NULL; var = var->next) { /*** Skip old attributes. ***/ if (find_delta == SLP_TRUE && var->modified == SLP_FALSE) { continue; } if (var->type == SLP_KEYWORD) { /**** Handle keywords. ****/ strcpy(cur, var->tag); cur += var->tag_len; } else { /**** Handle everything else. ****/ char *to_add; size_t to_add_len; value_t *value; /*** Add the prefix. ***/ strcpy(cur, VAR_PREFIX); cur += VAR_PREFIX_LEN; /*** Add the tag. ***/ strcpy(cur, var->tag); cur += var->tag_len; /*** Add the infix. ***/ strcpy(cur, VAR_INFIX); cur += VAR_INFIX_LEN; /*** Insert value (list) ***/ value = var->list; assert(value); while (value) { /* foreach member value of an attribute. */ assert(var->type != SLP_KEYWORD); switch(var->type) { case(SLP_BOOLEAN): assert(value->next == NULL); /* Can't be a multivalued list. */ assert(value->data.va_bool == SLP_TRUE || value->data.va_bool == SLP_FALSE); if (value->data.va_bool == SLP_TRUE) { to_add = BOOL_TRUE_STR; to_add_len = BOOL_TRUE_STR_LEN; } else { to_add = BOOL_FALSE_STR; to_add_len = BOOL_FALSE_STR_LEN; } strcpy(cur, to_add); cur += to_add_len; break; case(SLP_STRING): cur = escape_into(cur, value->data.va_str, -1); break; case(SLP_INTEGER): sprintf(cur, "%ld", value->data.va_int); cur += value->escaped_len; break; case(SLP_OPAQUE): strcpy(cur, OPAQUE_PREFIX); cur += OPAQUE_PREFIX_LEN; cur = escape_opaque_into(cur, value->data.va_str, value->unescaped_len); break; default: printf("Unknown type (%s:%d).\n", __FILE__, __LINE__); return SLP_INTERNAL_SYSTEM_ERROR; } value = value->next; /*** Add separator (if necessary) ***/ if (value != NULL) { strcpy(cur, VAR_SEPARATOR); cur += VAR_SEPARATOR_LEN; } } /*** Add the suffix. ***/ strcpy(cur, VAR_SUFFIX); cur += VAR_SUFFIX_LEN; } /*** Add separator (if necessary) ***/ if (var->next != NULL) { strcpy(cur, VAR_SEPARATOR); cur += VAR_SEPARATOR_LEN; } /*** Reset the modified flag. ***/ var->modified = SLP_FALSE; } assert((cur - build_str) == size && size == strlen(build_str)); /***** Append a null (This is actually done by strcpy, but its better to * be safe than sorry =) *****/ *cur = '\0'; *str = build_str; return SLP_OK; }
static netdev_tx_t ieee802154_xbee_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee802154_mac_cb* cb; int framelen, datalen; char *frame; struct xbee_priv *priv = netdev_priv(dev); struct xbee_tx_header header = { .length = 0x00, .api_id = 0x00, .frame_id = 0x02, .options = 0x04 }; dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; if(main_tty == NULL) { printk(KERN_ALERT "No tty attached!\nMake sure ldisc_daemon is running\n"); return 0; } printk(KERN_ALERT "[NET tx called, %d bytes in sk_buff, pkt type %hu, protocol %hu]\n", skb->len, skb->pkt_type, skb->protocol); cb = mac_cb(skb); //header.address = cpu_to_be64(0x000000000000FFFF); // So far broadcast header.address = cpu_to_be64p( (__be64*) &(cb->dest.extended_addr) ); printk(KERN_ALERT "MAC DST addr %llx\n", cb->dest.extended_addr); header.length = cpu_to_be16(skb->len + 1 + 10); datalen = skb->len + 1; // Allocate buffer to hold entire serial frame, including start byte and checksum frame = kmalloc(sizeof(struct xbee_tx_header) + (2*datalen) + 2, GFP_KERNEL); /* Assemble the frame */ /* Escaping the XBee header */ printk(KERN_ALERT "Adding XBEE header- length is %lu\n", sizeof(header) + 1); framelen = escape_into((frame + 1), &header, sizeof(header)); printk(KERN_ALERT "Adding data - length is %u\n", datalen); framelen += escape_into((frame + framelen + 1 ), (skb->data), datalen ); framelen++; // Checksum char at the beginning /* save the timestamp */ dev->trans_start = jiffies; //Stop the interface from sending more data, get the spinlock, and send it! netif_stop_queue(dev); spin_lock(&priv->lock); xbee_hw_tx(frame, framelen, dev); //Free the skbuff, we've copied all the data out dev_kfree_skb(skb); spin_unlock(&priv->lock); return NETDEV_TX_OK; } /* * Copies bytes from one array into another, escaping them if necessary. * Returns the size of the new array, including character escapes. * The destination array MUST be at least twice the size of the source */ static int escape_into(char *dest, const void *srcarray, int len) { int i, j=0; const char *src = srcarray; for(i=0; i<len; i++) { char unesc = *(src + i); // We support API mode 1 (escape characters is for API 2, if we want to enable mode 2 we need to implement escape management at RX) if( unesc == 0x7D || unesc == 0x7E || unesc == 0x11 || unesc == 0x13) { dest[j] = 0x7D; dest[j+1] = unesc ^ 0x20; j+=2; } else { dest[j] = unesc; j++; } } return j; }