static void advertising_packet(const void *data, uint8_t size) { const uint8_t *ptr = data; uint8_t pdu_type, length, win_size, hop, sca; bool tx_add, rx_add; uint32_t access_addr, crc_init; uint16_t win_offset, interval, latency, timeout; const char *str; if (size < 2) { print_text(COLOR_ERROR, "packet too short"); packet_hexdump(data, size); return; } pdu_type = ptr[0] & 0x0f; tx_add = !!(ptr[0] & 0x40); rx_add = !!(ptr[0] & 0x80); length = ptr[1] & 0x3f; switch (pdu_type) { case 0x00: str = "ADV_IND"; break; case 0x01: str = "ADV_DIRECT_IND"; break; case 0x02: str = "ADV_NONCONN_IND"; break; case 0x03: str = "SCAN_REQ"; break; case 0x04: str = "SCAN_RSP"; break; case 0x05: str = "CONNECT_REQ"; break; case 0x06: str = "ADV_SCAN_IND"; break; default: str = "Reserved"; break; } print_field("Type: %s (0x%2.2x)", str, pdu_type); print_field("TxAdd: %u", tx_add); print_field("RxAdd: %u", rx_add); print_field("Length: %u", length); if (length != size - 2) { print_text(COLOR_ERROR, "packet size mismatch"); packet_hexdump(data + 2, size - 2); return; } switch (pdu_type) { case 0x00: /* ADV_IND */ case 0x02: /* AVD_NONCONN_IND */ case 0x06: /* ADV_SCAN_IND */ case 0x04: /* SCAN_RSP */ if (length < 6) { print_text(COLOR_ERROR, "payload too short"); packet_hexdump(data + 2, length); return; } packet_print_addr("Advertiser address", data + 2, tx_add); packet_print_ad(data + 8, length - 6); break; case 0x01: /* ADV_DIRECT_IND */ if (length < 12) { print_text(COLOR_ERROR, "payload too short"); packet_hexdump(data + 2, length); return; } packet_print_addr("Advertiser address", data + 2, tx_add); packet_print_addr("Inititator address", data + 8, rx_add); break; case 0x03: /* SCAN_REQ */ if (length < 12) { print_text(COLOR_ERROR, "payload too short"); packet_hexdump(data + 2, length); return; } packet_print_addr("Scanner address", data + 2, tx_add); packet_print_addr("Advertiser address", data + 8, rx_add); break; case 0x05: /* CONNECT_REQ */ if (length < 34) { print_text(COLOR_ERROR, "payload too short"); packet_hexdump(data + 2, length); return; } packet_print_addr("Inititator address", data + 2, tx_add); packet_print_addr("Advertiser address", data + 8, rx_add); access_addr = ptr[14] | ptr[15] << 8 | ptr[16] << 16 | ptr[17] << 24; crc_init = ptr[18] | ptr[19] << 8 | ptr[20] << 16; print_field("Access address: 0x%8.8x", access_addr); print_field("CRC init: 0x%6.6x", crc_init); set_crc_init(access_addr, crc24_bit_reverse(crc_init)); win_size = ptr[21]; win_offset = ptr[22] | ptr[23] << 8; interval = ptr[24] | ptr[25] << 8; latency = ptr[26] | ptr[27] << 8; timeout = ptr[28] | ptr[29] << 8; print_field("Transmit window size: %u", win_size); print_field("Transmit window offset: %u", win_offset); print_field("Connection interval: %u", interval); print_field("Connection slave latency: %u", latency); print_field("Connection supervision timeout: %u", timeout); packet_print_channel_map_ll(ptr + 30); hop = ptr[35] & 0x1f; sca = (ptr[35] & 0xe0) >> 5; switch (sca) { case 0: str = "251 ppm to 500 ppm"; break; case 1: str = "151 ppm to 250 ppm"; break; case 2: str = "101 ppm to 150ppm"; break; case 3: str = "76 ppm to 100 ppm"; break; case 4: str = "51 ppm to 75 ppm"; break; case 5: str = "31 ppm to 50 ppm"; break; case 6: str = "21 ppm to 30 ppm"; break; case 7: str = "0 ppm to 20 ppm"; break; default: str = "Invalid"; break; } print_field("Hop increment: %u", hop); print_field("Sleep clock accuracy: %s (%u)", str, sca); break; default: packet_hexdump(data + 2, length); break; } }
static void write_bd_addr_cmd(const void *data, uint8_t size) { packet_print_addr("Address", data, false); }