started client/server implementation

This commit is contained in:
matthias.ringwald 2009-07-01 21:55:08 +00:00
parent e8e0f5cb85
commit 6511fa645e
6 changed files with 333 additions and 193 deletions

View File

@ -15,6 +15,8 @@
9C7ECB840FCC85650085DAC5 /* bt_control_iphone.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECB820FCC85650085DAC5 /* bt_control_iphone.c */; };
9C7ECBB50FCC95DD0085DAC5 /* hci_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECBB40FCC95DD0085DAC5 /* hci_dump.c */; };
9C88500E0FBF6702004980E4 /* l2cap.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C88500C0FBF6702004980E4 /* l2cap.c */; };
9CC813A20FFC0774002816F9 /* btstack.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A10FFC0774002816F9 /* btstack.c */; };
9CC813A50FFC0A51002816F9 /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A40FFC0A51002816F9 /* daemon.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -49,6 +51,10 @@
9C88500C0FBF6702004980E4 /* l2cap.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = l2cap.c; path = src/l2cap.c; sourceTree = "<group>"; };
9C88500D0FBF6702004980E4 /* l2cap.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = l2cap.h; path = src/l2cap.h; sourceTree = "<group>"; };
9CA3C0900FB8B3C4005F48DE /* TODO.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = TODO.txt; sourceTree = "<group>"; };
9CC813A00FFC0774002816F9 /* btstack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = btstack.h; path = src/btstack.h; sourceTree = "<group>"; };
9CC813A10FFC0774002816F9 /* btstack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = btstack.c; path = src/btstack.c; sourceTree = "<group>"; };
9CC813A30FFC0A51002816F9 /* daemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = daemon.h; path = src/daemon.h; sourceTree = "<group>"; };
9CC813A40FFC0A51002816F9 /* daemon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = daemon.c; path = src/daemon.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -79,6 +85,10 @@
9C7ECB810FCC85650085DAC5 /* bt_control.h */,
9C7ECB820FCC85650085DAC5 /* bt_control_iphone.c */,
9C7ECB830FCC85650085DAC5 /* bt_control_iphone.h */,
9CC813A00FFC0774002816F9 /* btstack.h */,
9CC813A10FFC0774002816F9 /* btstack.c */,
9CC813A30FFC0A51002816F9 /* daemon.h */,
9CC813A40FFC0A51002816F9 /* daemon.c */,
9C46FC350FA906F700ABEF05 /* hci.h */,
9C46FC340FA906F700ABEF05 /* hci.c */,
9C46FC380FA906F700ABEF05 /* hci_transport.h */,
@ -164,6 +174,8 @@
9C7ECBB50FCC95DD0085DAC5 /* hci_dump.c in Sources */,
9C1F0E9A0FDAE023008F472F /* run_loop.c in Sources */,
9C1F0F340FDB024B008F472F /* socket_server.c in Sources */,
9CC813A20FFC0774002816F9 /* btstack.c in Sources */,
9CC813A50FFC0A51002816F9 /* daemon.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

10
src/btstack.c Normal file
View File

@ -0,0 +1,10 @@
/*
* btstack.c
*
* Created by Matthias Ringwald on 7/1/09.
*
* BTstack client API
*/
#include "btstack.h"

9
src/btstack.h Normal file
View File

@ -0,0 +1,9 @@
/*
* btstack.h
*
* Created by Matthias Ringwald on 7/1/09.
*
* BTstack client API
*
*/

287
src/daemon.c Normal file
View File

@ -0,0 +1,287 @@
/*
* daemon.c
*
* Created by Matthias Ringwald on 7/1/09.
*
* BTstack background daemon
*
*/
#include "daemon.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#ifdef __APPLE__
#include <Availability.h>
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_2_0
#define __IPHONE__
#endif
#endif
#include "hci.h"
#include "hci_transport_h4.h"
#include "hci_dump.h"
#include "bt_control_iphone.h"
#include "l2cap.h"
#include "run_loop.h"
#include "socket_server.h"
#include "daemon.h"
hci_con_handle_t con_handle_out = 0;
hci_con_handle_t con_handle_in = 0;
uint16_t dest_cid;
#define BT_HID
// #define POWER_CYCLE_TEST
// #define MITM
void event_handler(uint8_t *packet, int size){
// printf("Event type: %x, opcode: %x, other %x\n", packet[0], packet[3] | packet[4] << 8);
#if defined(BT_HID) || defined(MITM)
bd_addr_t addr = {0x00, 0x03, 0xc9, 0x3d, 0x77, 0x43 }; // Think Outside Keyboard
// bt stack activated, get started
if (packet[0] == BTSTACK_EVENT_HCI_WORKING) {
hci_send_cmd(&hci_write_class_of_device, 0x7A020C); // used on iPhone
}
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_class_of_device) ) {
hci_send_cmd(&hci_write_local_name, "BT in the Middle");
}
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_local_name) ) {
#if 1
hci_send_cmd(&hci_write_authentication_enable, 1);
}
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
#endif
#if 0
hci_send_cmd(&hci_write_inquiry_mode, 2);
}
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_inquiry_mode) ) {
#endif
#if 0
hci_send_cmd(&hci_set_event_mask, 0xffffffff, 0x1fffffff);
}
uint8_t eir[] = {
0x0d, 0x09, 0x4d, 0x69, 0x6c, 0x61, 0x73, 0x20, 0x69, 0x50, 0x68, 0x6f, 0x6e, 0x65, 0x0f, 0x02,
0x00, 0x12, 0x1f, 0x11, 0x07, 0x11, 0x2f, 0x11, 0x0a, 0x11, 0x16, 0x11, 0x15, 0x11, 0x27, 0xff,
0x00, 0x4c, 0x02, 0x24, 0x02, 0x86, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
if ( COMMAND_COMPLETE_EVENT(packet, hci_set_event_mask) ) {
#endif
#if 0
hci_send_cmd(&hci_write_extended_inquiry_response, 0, eir);
}
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_extended_inquiry_response) ) {
#endif
#if 0
hci_send_cmd(&hci_write_simple_pairing_mode, 1);
}
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_simple_pairing_mode) ) {
#endif
#if 0
hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, 15, 0);
}
if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE)
#endif
#if 1
hci_send_cmd(&hci_create_connection, &addr, 0x18, 0, 0, 0, 0);
#endif
}
if (packet[0] == HCI_EVENT_CONNECTION_REQUEST){
bt_flip_addr(addr, &packet[2]);
hci_send_cmd(&hci_accept_connection_request, &addr, 1);
}
if (packet[0] == HCI_EVENT_PIN_CODE_REQUEST){
printf("Please enter PIN 1234 on remote device\n");
}
// connection established -> start L2CAP conection
if (packet[0] == HCI_EVENT_CONNECTION_COMPLETE){
if (packet[2] == 0){
// get new connection handle
if (! con_handle_out) {
con_handle_out = READ_BT_16(packet, 3);
} else {
con_handle_in = READ_BT_16(packet, 3);
}
#ifndef MITM
// request l2cap connection
printf("> CONNECTION REQUEST\n");
l2cap_send_signaling_packet(con_handle_out, CONNECTION_REQUEST, sig_seq_nr++, 0x13, local_cid);
#else
printf("Connected to target device, please start!\n");
#endif
}
}
#endif
#ifdef POWER_CYCLE_TEST
if (packet[0] == BTSTACK_EVENT_HCI_WORKING) {
hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, 10, 0);
}
if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE){
// power cycle
hci_power_control( HCI_POWER_OFF );
//
printf ("Power off!\n");
sleep(10);
printf ("Restart!\n");
hci_power_control( HCI_POWER_ON );
}
#endif
}
void acl_handler(uint8_t *packet, int size){
#ifdef MITM
// forward packet on "other" connection
hci_con_handle_t incoming_hdl = READ_BT_16(packet, 0) & 0xfff;
hci_con_handle_t outgoing_hdl = 0;
#if 0
if (incoming_hdl == con_handle_in){
outgoing_hdl = con_handle_out;
} else if (incoming_hdl == con_handle_out){
outgoing_hdl = con_handle_in;
} else {
printf("Incoming acl packet on handle %u\n!", incoming_hdl);
}
#else
outgoing_hdl = incoming_hdl;
#endif
if (outgoing_hdl){
bt_store_16( packet, 0, (READ_BT_16(packet, 0) & 0xf000) | outgoing_hdl);
hci_send_acl_packet(packet, size);
}
#else
uint16_t source_cid;
uint16_t result;
uint8_t config_options[] = { 1, 2, 150, 0}; // mtu = 48
// connection response
if (packet[8] == CONNECTION_RESPONSE){
dest_cid = READ_BT_16(packet, 12);
source_cid = READ_BT_16(packet, 14);
result = READ_BT_16(packet, 16);
uint16_t status = READ_BT_16(packet, 18);
printf("< CONNECTION_RESPONSE: id %u, dest cid %u, src cid %u, result %u, status %u\n", packet[9], dest_cid, source_cid, result, status);
if (result == 0){
printf("> CONFIGURE_REQUEST: id %u\n", sig_seq_nr);
l2cap_send_signaling_packet(con_handle_out, CONFIGURE_REQUEST, sig_seq_nr++, dest_cid, 0, 4, &config_options);
}
}
else if (packet[8] == CONFIGURE_RESPONSE){
source_cid = READ_BT_16(packet, 12);
uint16_t flags = READ_BT_16(packet, 14);
result = READ_BT_16(packet, 16);
printf("< CONFIGURE_RESPONSE: id %u, src cid %u, flags %u, result %u!!!\n", packet[9], source_cid, flags, result);
hexdump(&packet[18], size-18);
}
else if (packet[8] == CONFIGURE_REQUEST){
printf("< CONFIGURE_REQUEST: id %u\n", packet[9]);
hexdump(&packet[16], size-16);
printf("> CONFIGURE_RESPONSE: id %u\n", packet[9]);
l2cap_send_signaling_packet(con_handle_out, CONFIGURE_RESPONSE, packet[9], local_cid, 0, 0, size - 16, &packet[16]);
}
else {
printf("Unknown ACL ^^^ \n");
}
#endif
}
static hci_transport_t * transport;
static hci_uart_config_t config;
int daemon_main (int argc, const char * argv[]){
#if 0
pid_t parent_pid = fork();
if (parent_pid > 0) {
// parent returns
return 0;
}
#endif
bt_control_t * control = NULL;
#ifndef __IPHONE__
//
if (argc <= 1){
printf("HCI Daemon tester. Specify device name for Ericsson ROK 101 007\n");
return 1;
}
// Ancient Ericsson ROK 101 007 (ca. 2001)
config.device_name = argv[1];
config.baudrate = 57600;
config.flowcontrol = 1;
#else
// iPhone
config.device_name = "/dev/tty.bluetooth";
config.baudrate = 115200;
// config.baudrate = 230400; // ok
// config.baudrate = 460800; // ok
// config.baudrate = 921600; // ok
// config.baudrate = 2400000; // does not work (yet)
config.flowcontrol = 1;
control = &bt_control_iphone;
#endif
// use logger: format HCI_DUMP_PACKETLOGGER or HCI_DUMP_BLUEZ
hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
// H4 UART
transport = hci_transport_h4_instance();
// init HCI
hci_init(transport, &config, control);
// init L2CAP
l2cap_init();
//
// register callbacks
//
hci_register_event_packet_handler(&event_handler);
hci_register_acl_packet_handler(&acl_handler);
// turn on
hci_power_control(HCI_POWER_ON);
// configure run loop
run_loop_add( (data_source_t *) transport);
// create server
data_source_t *socket_server = socket_server_create_tcp(1919);
run_loop_add( socket_server );
// go!
run_loop_execute();
return 0;
}

10
src/daemon.h Normal file
View File

@ -0,0 +1,10 @@
/*
* daemon.h
*
* Created by Matthias Ringwald on 7/1/09.
*
* BTstack background daemon
*
*/
int daemon_main (int argc, const char * argv[]);

View File

@ -8,204 +8,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include "hci.h"
#include "hci_transport_h4.h"
#include "hci_dump.h"
#include "bt_control_iphone.h"
#include "l2cap.h"
#include "run_loop.h"
#include "socket_server.h"
static hci_transport_t * transport;
static hci_uart_config_t config;
hci_con_handle_t con_handle_out = 0;
hci_con_handle_t con_handle_in = 0;
uint16_t dest_cid;
// #define BT_HID
// #define POWER_CYCLE_TEST
#define MITM
void event_handler(uint8_t *packet, int size){
// printf("Event type: %x, opcode: %x, other %x\n", packet[0], packet[3] | packet[4] << 8);
#if defined(BT_HID) || defined(MITM)
bd_addr_t addr = {0x00, 0x03, 0xc9, 0x3d, 0x77, 0x43 }; // Think Outside Keyboard
// bd_addr_t addr = { 0x00, 0x16, 0xcb, 0x09, 0x94, 0xa9}; // MacBook Pro
// bt stack activated, set authentication enabled
if (packet[0] == BTSTACK_EVENT_HCI_WORKING) {
#if 0
hci_send_cmd(&hci_write_authentication_enable, 1);
// hci_send_cmd(&hci_host_buffer_size, 400, 255, 1, 0, 0);
}
if ( COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable) ) {
// hci_write_authentication_enable done, send connect
#endif
hci_send_cmd(&hci_create_connection, &addr, 0x18, 0, 0, 0, 0);
}
if (packet[0] == HCI_EVENT_CONNECTION_REQUEST){
bt_flip_addr(addr, &packet[2]);
hci_send_cmd(&hci_accept_connection_request, &addr, 1);
}
if (packet[0] == HCI_EVENT_PIN_CODE_REQUEST){
printf("Please enter PIN 1234 on remote device\n");
}
// connection established -> start L2CAP conection
if (packet[0] == HCI_EVENT_CONNECTION_COMPLETE){
if (packet[2] == 0){
// get new connection handle
if (! con_handle_out) {
con_handle_out = READ_BT_16(packet, 3);
} else {
con_handle_in = READ_BT_16(packet, 3);
}
#ifndef MITM
// request l2cap connection
printf("> CONNECTION REQUEST\n");
l2cap_send_signaling_packet(con_handle_out, CONNECTION_REQUEST, sig_seq_nr++, 0x13, local_cid);
#else
printf("Connected to target device, please start!\n");
#endif
}
}
#endif
#ifdef POWER_CYCLE_TEST
if (packet[0] == BTSTACK_EVENT_HCI_WORKING) {
hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, 10, 0);
}
if (packet[0] == HCI_EVENT_INQUIRY_COMPLETE){
// power cycle
hci_power_control( HCI_POWER_OFF );
//
printf ("Power off!\n");
sleep(10);
printf ("Restart!\n");
hci_power_control( HCI_POWER_ON );
}
#endif
}
void acl_handler(uint8_t *packet, int size){
#ifdef MITM
// forward packet on "other" connection
hci_con_handle_t incoming_hdl = READ_BT_16(packet, 0) & 0xfff;
hci_con_handle_t outgoing_hdl = 0;
if (incoming_hdl == con_handle_in){
outgoing_hdl = con_handle_out;
} else if (incoming_hdl == con_handle_out){
outgoing_hdl = con_handle_in;
} else {
printf("Incoming acl packet on handle %u\n!", incoming_hdl);
}
if (outgoing_hdl){
bt_store_16( packet, 0, (READ_BT_16(packet, 0) & 0xf000) | outgoing_hdl);
hci_send_acl_packet(packet, size);
}
#else
uint16_t source_cid;
uint16_t result;
uint8_t config_options[] = { 1, 2, 150, 0}; // mtu = 48
// connection response
if (packet[8] == CONNECTION_RESPONSE){
dest_cid = READ_BT_16(packet, 12);
source_cid = READ_BT_16(packet, 14);
result = READ_BT_16(packet, 16);
uint16_t status = READ_BT_16(packet, 18);
printf("< CONNECTION_RESPONSE: id %u, dest cid %u, src cid %u, result %u, status %u\n", packet[9], dest_cid, source_cid, result, status);
if (result == 0){
printf("> CONFIGURE_REQUEST: id %u\n", sig_seq_nr);
l2cap_send_signaling_packet(con_handle_out, CONFIGURE_REQUEST, sig_seq_nr++, dest_cid, 0, 4, &config_options);
}
}
else if (packet[8] == CONFIGURE_RESPONSE){
source_cid = READ_BT_16(packet, 12);
uint16_t flags = READ_BT_16(packet, 14);
result = READ_BT_16(packet, 16);
printf("< CONFIGURE_RESPONSE: id %u, src cid %u, flags %u, result %u!!!\n", packet[9], source_cid, flags, result);
hexdump(&packet[18], size-18);
}
else if (packet[8] == CONFIGURE_REQUEST){
printf("< CONFIGURE_REQUEST: id %u\n", packet[9]);
hexdump(&packet[16], size-16);
printf("> CONFIGURE_RESPONSE: id %u\n", packet[9]);
l2cap_send_signaling_packet(con_handle_out, CONFIGURE_RESPONSE, packet[9], local_cid, 0, 0, size - 16, &packet[16]);
}
else {
printf("Unknown ACL ^^^ \n");
}
#endif
}
#include "daemon.h"
int main (int argc, const char * argv[]) {
bt_control_t * control = NULL;
// start daemon
daemon_main(argc, argv);
#if 1
//
if (argc <= 1){
printf("HCI Daemon tester. Specify device name for Ericsson ROK 101 007\n");
exit(1);
}
// Ancient Ericsson ROK 101 007 (ca. 2001)
config.device_name = argv[1];
config.baudrate = 57600;
config.flowcontrol = 1;
#else
// iPhone
config.device_name = "/dev/tty.bluetooth";
config.baudrate = 115200;
// config.baudrate = 230400; // ok
// config.baudrate = 460800; // ok
// config.baudrate = 921600; // ok
// config.baudrate = 2400000; // does not work (yet)
config.flowcontrol = 1;
control = &bt_control_iphone;
#endif
// use logger: format HCI_DUMP_PACKETLOGGER or HCI_DUMP_BLUEZ
hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
// H4 UART
transport = hci_transport_h4_instance();
// init HCI
hci_init(transport, &config, control);
//
// register callbacks
//
hci_register_event_packet_handler(&event_handler);
hci_register_acl_packet_handler(&acl_handler);
// init L2CAP
l2cap_init();
// turn on
hci_power_control(HCI_POWER_ON);
// create server
data_source_t *socket_server = socket_server_create_tcp(1919);
// configure run loop
run_loop_add( (data_source_t *) transport);
run_loop_add( socket_server );
// go!
run_loop_execute();
// daemon does not returs so far
return 0;
}