static void _api_at_cmd(xbee_t *dev, uint8_t *cmd, uint8_t size, resp_t *resp) { /* acquire TX lock */ mutex_lock(&(dev->tx_lock)); /* construct API frame */ dev->tx_buf[0] = API_START_DELIMITER; dev->tx_buf[1] = (size + 2) >> 8; dev->tx_buf[2] = (size + 2) & 0xff; dev->tx_buf[3] = API_ID_AT; dev->tx_buf[4] = 1; /* use fixed frame id */ memcpy(dev->tx_buf + 5, cmd, size); dev->tx_buf[size + 5] = _cksum(dev->tx_buf, size + 5); /* reset the response data counter */ dev->resp_count = 0; /* start send data */ uart_write(dev->uart, dev->tx_buf, size + 6); /* wait for results */ while (dev->resp_limit != dev->resp_count) { mutex_lock(&(dev->resp_lock)); } /* populate response data structure */ resp->status = dev->resp_buf[3]; resp->data_len = dev->resp_limit - 5; if (resp->data_len > 0) { memcpy(resp->data, &(dev->resp_buf[4]), resp->data_len); } }
static void _api_at_cmd(xbee_t *dev, uint8_t *cmd, uint8_t size, resp_t *resp) { DEBUG("[xbee] AT_CMD: %s\n", cmd); /* acquire TX lock */ mutex_lock(&(dev->tx_lock)); /* construct API frame */ dev->cmd_buf[0] = API_START_DELIMITER; dev->cmd_buf[1] = (size + 2) >> 8; dev->cmd_buf[2] = (size + 2) & 0xff; dev->cmd_buf[3] = API_ID_AT; dev->cmd_buf[4] = 1; /* use fixed frame id */ memcpy(dev->cmd_buf + 5, cmd, size); dev->cmd_buf[size + 5] = _cksum(3, dev->cmd_buf, size + 5); /* reset the response data counter */ dev->resp_count = 0; /* start send data */ uart_write(dev->p.uart, dev->cmd_buf, size + 6); xtimer_ticks64_t sent_time = xtimer_now64(); xtimer_t resp_timer; resp_timer.callback = isr_resp_timeout; resp_timer.arg = dev; xtimer_set(&resp_timer, RESP_TIMEOUT_USEC); /* wait for results */ while ((dev->resp_limit != dev->resp_count) && (xtimer_less( xtimer_diff32_64(xtimer_now64(), sent_time), xtimer_ticks_from_usec(RESP_TIMEOUT_USEC)))) { mutex_lock(&(dev->resp_lock)); } xtimer_remove(&resp_timer); if (dev->resp_limit != dev->resp_count) { DEBUG("[xbee] api_at_cmd: response timeout\n"); resp->status = 255; mutex_unlock(&(dev->tx_lock)); return; } /* populate response data structure */ resp->status = dev->resp_buf[3]; resp->data_len = dev->resp_limit - 5; if (resp->data_len > 0) { memcpy(resp->data, &(dev->resp_buf[4]), resp->data_len); } mutex_unlock(&(dev->tx_lock)); }
static void xbee_isr(netdev_t *netdev) { xbee_t *dev = (xbee_t *)netdev; if (dev->rx_count == dev->rx_limit) { /* make sure the checksum checks out */ if (_cksum(0, dev->rx_buf, dev->rx_limit) != 0) { DEBUG("[xbee] isr: invalid RX checksum\n"); dev->rx_count = 0; } else { DEBUG("[xbee] isr: data available, waiting for read\n"); dev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE); } } }
static int xbee_send(netdev_t *dev, const struct iovec *vector, unsigned count) { xbee_t *xbee = (xbee_t *)dev; size_t size; uint8_t csum; assert(xbee && vector && (count > 0)); /* calculate the checksum and the packet size */ size = vector[0].iov_len; csum = _cksum(3, (uint8_t *)vector[0].iov_base, size); for (unsigned i = 1; i < count; i++) { size += vector[i].iov_len; for (size_t p = 0; p < vector[i].iov_len; p++) { csum -= ((uint8_t *)vector[i].iov_base)[p]; } } /* make sure the data fits into a packet */ if (size >= XBEE_MAX_PKT_LENGTH) { DEBUG("[xbee] send: data to send is too large for TX buffer\n"); return -1; } /* send the actual data packet */ DEBUG("[xbee] send: now sending out %i byte\n", (int)size); mutex_lock(&(xbee->tx_lock)); for (unsigned i = 0; i < count; i++) { uart_write(xbee->p.uart, vector[i].iov_base, vector[i].iov_len); } uart_write(xbee->p.uart, &csum, 1); mutex_unlock(&(xbee->tx_lock)); /* return number of payload byte */ return (int)size; }
/* * Synopsis: * Write ye old hexdump to file trace_fd. * * Description: * Hexdump a buffer to the file trace_fd stream. * * Each 16 bytes of the source buffer is formated and written as 76 chars * plus new line. The characters '>' and '<' represent either read or * write direction, respectively. * 0 > 67 65 74 20 70 69 6e 67 3a 61 62 63 64 65 66 0a get ping:abcdef. 16 > 3a 35 34 20 43 44 54 09 31 32 37 2e 30 2e 30 2e :54 CDT.127.0.0. 32 > 01 02 03 ... 0.........1.........2.........3.........4.........5.........6.........7......... * * Derived from a hexdump written by Andy Fullford, eons ago. * * https://github.com/akfullfo */ void hexdump(unsigned char *src, int src_size, char direction) { char *t; unsigned char *s, *s_end; int need; char tbuf[64 * 1024], *tgt; int tgt_size; char buf[1024]; if (src_size == 0) { static char zero[] = "hexdump: 0 bytes in source buffer\n"; _write(zero); return; } tgt = tbuf; tgt_size = sizeof tbuf; static char hexchar[] = "0123456789abcdef"; /* * Insure we have plenty of room in the target buffer. * * Each line of ascii output formats up to 16 bytes in the source * buffer, so the number of lines is the ceiling(src_size/16). * The number of characters per line is 76 characters plus the * trailing new line. * * ((src_size - 1) / 16 + 1) * (76 + 1) + 1 * * with the entire ascii string terminated with a null byte. */ need = ((src_size - 1) / 16 + 1) * (76 + 1) + 1; /* * Not enough space in the target buffer ... probably ought * to truncate instead of punting. */ if (need > tgt_size) { snprintf(tgt, tgt_size, "hexdump: source bigger than target: %d > %d\n", need, tgt_size); _write(tgt); return; } s = src; s_end = s + src_size; t = tgt; while (s < s_end) { int i; /* * Start of line in the target. */ char *l = t; /* * Write the offset into the source buffer. */ sprintf(l, "%6lu", (long unsigned)(s - src)); /* * Write direction of flow */ l[6] = l[7] = ' '; l[8] = direction; l[9] = ' '; /* * Format up to next 16 bytes from the source. */ for (i = 0; s < s_end && i < 16; i++) { l[10 + i * 3] = ' '; l[10 + i * 3 + 1] = hexchar[(*s >> 4) & 0x0F]; l[10 + i * 3 + 2] = hexchar[*s & 0x0F]; if (isprint(*s)) l[60 + i] = *s; else l[60 + i] = '.'; s++; } /* * Pad out last line with white space. */ while (i < 16) { l[10 + i * 3] = l[10 + i * 3 + 1] = l[10 + i * 3 + 2] = ' '; l[60 + i] = ' '; i++; } l[58] = l[59] = ' '; l[76] = '\n'; t = l + 77; } tgt[need - 1] = 0; snprintf(buf, sizeof buf, "\ndump of %d bytes, cksum %hu\n", src_size, _cksum(src, src_size)); _write(buf); _write(tgt); _write("\n"); }