mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-16 08:42:28 +00:00
extract code for HCI Command packet construction into hci_cmds.c
This commit is contained in:
parent
8cdb50c161
commit
d8905019be
@ -1,5 +1,5 @@
|
|||||||
bin_PROGRAMS = test
|
bin_PROGRAMS = test
|
||||||
test_SOURCES = test.c ../src/btstack.c ../src/hci.c \
|
test_SOURCES = test.c ../src/btstack.c ../src/hci.c \
|
||||||
../src/l2cap.c ../src/linked_list.c ../src/run_loop.c \
|
../src/l2cap.c ../src/linked_list.c ../src/run_loop.c \
|
||||||
../src/hci_dump.c ../src/socket_connection.c
|
../src/hci_dump.c ../src/hci_cmds.c ../src/socket_connection.c
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
9C00F7321017ACC3008DAB17 /* socket_connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7301017ACC3008DAB17 /* socket_connection.c */; };
|
9C00F7321017ACC3008DAB17 /* socket_connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7301017ACC3008DAB17 /* socket_connection.c */; };
|
||||||
|
9C00F7D71019082F008DAB17 /* hci_cmds.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7D61019082F008DAB17 /* hci_cmds.c */; };
|
||||||
|
9C00F7D81019082F008DAB17 /* hci_cmds.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7D61019082F008DAB17 /* hci_cmds.c */; };
|
||||||
9C1F0E9A0FDAE023008F472F /* run_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C1F0E980FDAE023008F472F /* run_loop.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 */; };
|
9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C2071F210014D3200A07EA4 /* hci_transport_usb.c */; };
|
||||||
9C20720F10025E0500A07EA4 /* libusb-1.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C20720E10025E0500A07EA4 /* libusb-1.0.dylib */; };
|
9C20720F10025E0500A07EA4 /* libusb-1.0.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C20720E10025E0500A07EA4 /* libusb-1.0.dylib */; };
|
||||||
@ -45,6 +47,8 @@
|
|||||||
8DD76FB20486AB0100D96B5E /* project */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = project; sourceTree = BUILT_PRODUCTS_DIR; };
|
8DD76FB20486AB0100D96B5E /* project */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = project; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
9C00F7301017ACC3008DAB17 /* socket_connection.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = socket_connection.c; path = src/socket_connection.c; sourceTree = "<group>"; };
|
9C00F7301017ACC3008DAB17 /* socket_connection.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = socket_connection.c; path = src/socket_connection.c; sourceTree = "<group>"; };
|
||||||
9C00F7311017ACC3008DAB17 /* socket_connection.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = socket_connection.h; path = src/socket_connection.h; sourceTree = "<group>"; };
|
9C00F7311017ACC3008DAB17 /* socket_connection.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = socket_connection.h; path = src/socket_connection.h; sourceTree = "<group>"; };
|
||||||
|
9C00F7D51019082F008DAB17 /* hci_cmds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hci_cmds.h; path = src/hci_cmds.h; sourceTree = "<group>"; };
|
||||||
|
9C00F7D61019082F008DAB17 /* hci_cmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hci_cmds.c; path = src/hci_cmds.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
||||||
@ -132,6 +136,8 @@
|
|||||||
9C1F0E980FDAE023008F472F /* run_loop.c */,
|
9C1F0E980FDAE023008F472F /* run_loop.c */,
|
||||||
9C00F7301017ACC3008DAB17 /* socket_connection.c */,
|
9C00F7301017ACC3008DAB17 /* socket_connection.c */,
|
||||||
9C00F7311017ACC3008DAB17 /* socket_connection.h */,
|
9C00F7311017ACC3008DAB17 /* socket_connection.h */,
|
||||||
|
9C00F7D51019082F008DAB17 /* hci_cmds.h */,
|
||||||
|
9C00F7D61019082F008DAB17 /* hci_cmds.c */,
|
||||||
);
|
);
|
||||||
name = Source;
|
name = Source;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -232,6 +238,7 @@
|
|||||||
9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */,
|
9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */,
|
||||||
9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */,
|
9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */,
|
||||||
9C00F7321017ACC3008DAB17 /* socket_connection.c in Sources */,
|
9C00F7321017ACC3008DAB17 /* socket_connection.c in Sources */,
|
||||||
|
9C00F7D71019082F008DAB17 /* hci_cmds.c in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -247,6 +254,7 @@
|
|||||||
9C7B5D0D100FC9CE0065D87E /* linked_list.c in Sources */,
|
9C7B5D0D100FC9CE0065D87E /* linked_list.c in Sources */,
|
||||||
9C7B5D0E100FC9D00065D87E /* run_loop.c in Sources */,
|
9C7B5D0E100FC9D00065D87E /* run_loop.c in Sources */,
|
||||||
9C7B5D12100FC9F00065D87E /* l2cap.c in Sources */,
|
9C7B5D12100FC9F00065D87E /* l2cap.c in Sources */,
|
||||||
|
9C00F7D81019082F008DAB17 /* hci_cmds.c in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -8,6 +8,7 @@ BTdaemon_SOURCES = \
|
|||||||
bt_control_iphone.c \
|
bt_control_iphone.c \
|
||||||
daemon.c \
|
daemon.c \
|
||||||
hci.c \
|
hci.c \
|
||||||
|
hci_cmds.c \
|
||||||
hci_dump.c \
|
hci_dump.c \
|
||||||
hci_transport_h4.c \
|
hci_transport_h4.c \
|
||||||
$(usb_support) \
|
$(usb_support) \
|
||||||
@ -20,6 +21,7 @@ include_HEADERS = \
|
|||||||
bt_control.h \
|
bt_control.h \
|
||||||
bt_control_iphone.h \
|
bt_control_iphone.h \
|
||||||
hci.h \
|
hci.h \
|
||||||
|
hci_cmds.h \
|
||||||
hci_dump.h \
|
hci_dump.h \
|
||||||
hci_transport.h \
|
hci_transport.h \
|
||||||
hci_transport_h4.h \
|
hci_transport_h4.h \
|
||||||
|
177
src/hci.c
177
src/hci.c
@ -10,108 +10,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "hci.h"
|
#include "hci.h"
|
||||||
|
#include "hci_dump.h"
|
||||||
/**
|
|
||||||
* Link Control Commands
|
|
||||||
*/
|
|
||||||
hci_cmd_t hci_inquiry = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x01), "311"
|
|
||||||
// LAP, Inquiry length, Num_responses
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_inquiry_cancel = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x02), ""
|
|
||||||
// no params
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_create_connection = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x05), "B21121"
|
|
||||||
// BD_ADDR, Packet_Type, Page_Scan_Repetition_Mode, Reserved, Clock_Offset, Allow_Role_Switch
|
|
||||||
};
|
|
||||||
|
|
||||||
hci_cmd_t hci_accept_connection_request = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x09), "B1"
|
|
||||||
// BD_ADDR, Role: become master, stay slave
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_link_key_request_negative_reply = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x0c), "B"
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_pin_code_request_reply = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x0d), "B1P"
|
|
||||||
// BD_ADDR, pin length, PIN: c-string
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_remote_name_request = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x19), "B112"
|
|
||||||
// BD_ADDR, Page_Scan_Repetition_Mode, Reserved, Clock_Offset
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_remote_name_request_cancel = {
|
|
||||||
OPCODE(OGF_LINK_CONTROL, 0x1A), "B"
|
|
||||||
// BD_ADDR
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller & Baseband Commands
|
|
||||||
*/
|
|
||||||
hci_cmd_t hci_set_event_mask = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x01), "44"
|
|
||||||
// event_mask lower 4 octets, higher 4 bytes
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_reset = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x03), ""
|
|
||||||
// no params
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_delete_stored_link_key = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x12), "B1"
|
|
||||||
// BD_ADDR, Delete_All_Flag
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_write_local_name = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x13), "N"
|
|
||||||
// Local name (UTF-8, Null Terminated, max 248 octets)
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_write_page_timeout = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x18), "2"
|
|
||||||
// Page_Timeout * 0.625 ms
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_write_scan_enable = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x1A), "1"
|
|
||||||
// Scan_enable: no, inq, page, inq+page
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_write_authentication_enable = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x20), "1"
|
|
||||||
// Authentication_Enable
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_write_class_of_device = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x24), "3"
|
|
||||||
// Class of Device
|
|
||||||
};
|
|
||||||
hci_cmd_t hci_host_buffer_size = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x33), "2122"
|
|
||||||
// Host_ACL_Data_Packet_Length:, Host_Synchronous_Data_Packet_Length:, Host_Total_Num_ACL_Data_Packets:, Host_Total_Num_Synchronous_Data_Packets:
|
|
||||||
};
|
|
||||||
|
|
||||||
hci_cmd_t hci_write_inquiry_mode = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x45), "1"
|
|
||||||
// Inquiry mode: 0x00 = standard, 0x01 = with RSSI, 0x02 = extended
|
|
||||||
};
|
|
||||||
|
|
||||||
hci_cmd_t hci_write_extended_inquiry_response = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x52), "1E"
|
|
||||||
// FEC_Required, Exstended Inquiry Response
|
|
||||||
};
|
|
||||||
|
|
||||||
hci_cmd_t hci_write_simple_pairing_mode = {
|
|
||||||
OPCODE(OGF_CONTROLLER_BASEBAND, 0x56), "1"
|
|
||||||
// mode: 0 = off, 1 = on
|
|
||||||
};
|
|
||||||
|
|
||||||
hci_cmd_t hci_read_bd_addr = {
|
|
||||||
OPCODE(OGF_INFORMATIONAL_PARAMETERS, 0x09), ""
|
|
||||||
// no params
|
|
||||||
};
|
|
||||||
|
|
||||||
hci_cmd_t hci_get_btstack_state = {
|
|
||||||
OPCODE(OGF_BTSTACK, HCI_BTSTACK_GET_STATE), ""
|
|
||||||
// no params ->
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// the stack is here
|
// the stack is here
|
||||||
static hci_stack_t hci_stack;
|
static hci_stack_t hci_stack;
|
||||||
@ -371,80 +270,6 @@ int hci_send_cmd_packet(uint8_t *packet, int size){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr){
|
|
||||||
|
|
||||||
hci_cmd_buffer[0] = cmd->opcode & 0xff;
|
|
||||||
hci_cmd_buffer[1] = cmd->opcode >> 8;
|
|
||||||
int pos = 3;
|
|
||||||
|
|
||||||
const char *format = cmd->format;
|
|
||||||
uint16_t word;
|
|
||||||
uint32_t longword;
|
|
||||||
uint8_t * ptr;
|
|
||||||
while (*format) {
|
|
||||||
switch(*format) {
|
|
||||||
case '1': // 8 bit value
|
|
||||||
case '2': // 16 bit value
|
|
||||||
case 'H': // hci_handle
|
|
||||||
word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
|
|
||||||
hci_cmd_buffer[pos++] = word & 0xff;
|
|
||||||
if (*format == '2') {
|
|
||||||
hci_cmd_buffer[pos++] = word >> 8;
|
|
||||||
} else if (*format == 'H') {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
longword = va_arg(argptr, uint32_t);
|
|
||||||
// longword = va_arg(argptr, int);
|
|
||||||
hci_cmd_buffer[pos++] = longword;
|
|
||||||
hci_cmd_buffer[pos++] = longword >> 8;
|
|
||||||
hci_cmd_buffer[pos++] = longword >> 16;
|
|
||||||
if (*format == '4'){
|
|
||||||
hci_cmd_buffer[pos++] = longword >> 24;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'B': // bt-addr
|
|
||||||
ptr = va_arg(argptr, uint8_t *);
|
|
||||||
hci_cmd_buffer[pos++] = ptr[5];
|
|
||||||
hci_cmd_buffer[pos++] = ptr[4];
|
|
||||||
hci_cmd_buffer[pos++] = ptr[3];
|
|
||||||
hci_cmd_buffer[pos++] = ptr[2];
|
|
||||||
hci_cmd_buffer[pos++] = ptr[1];
|
|
||||||
hci_cmd_buffer[pos++] = ptr[0];
|
|
||||||
break;
|
|
||||||
case 'P': // c string passed as pascal string with leading 1-byte len
|
|
||||||
ptr = va_arg(argptr, uint8_t *);
|
|
||||||
memcpy(&hci_cmd_buffer[pos], ptr, 16);
|
|
||||||
pos += 16;
|
|
||||||
break;
|
|
||||||
case 'N': // UTF-8 string, null terminated
|
|
||||||
ptr = va_arg(argptr, uint8_t *);
|
|
||||||
memcpy(&hci_cmd_buffer[pos], ptr, 248);
|
|
||||||
pos += 248;
|
|
||||||
break;
|
|
||||||
case 'E': // Extended Inquiry Information 240 octets
|
|
||||||
ptr = va_arg(argptr, uint8_t *);
|
|
||||||
memcpy(&hci_cmd_buffer[pos], ptr, 240);
|
|
||||||
pos += 240;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
format++;
|
|
||||||
};
|
|
||||||
hci_cmd_buffer[2] = pos - 3;
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t hci_create_cmd(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, ...){
|
|
||||||
va_list argptr;
|
|
||||||
va_start(argptr, cmd);
|
|
||||||
uint16_t len = hci_create_cmd_internal(hci_cmd_buffer, cmd, argptr);
|
|
||||||
va_end(argptr);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pre: numcmds >= 0 - it's allowed to send a command to the controller
|
* pre: numcmds >= 0 - it's allowed to send a command to the controller
|
||||||
|
53
src/hci.h
53
src/hci.h
@ -11,6 +11,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "hci_cmds.h"
|
||||||
#include "hci_transport.h"
|
#include "hci_transport.h"
|
||||||
#include "bt_control.h"
|
#include "bt_control.h"
|
||||||
|
|
||||||
@ -19,26 +20,12 @@
|
|||||||
#define READ_BT_24( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16))
|
#define READ_BT_24( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16))
|
||||||
#define READ_BT_32( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16) | (((uint32_t) buffer[pos+3])) << 24)
|
#define READ_BT_32( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[pos+1]) << 8) | (((uint32_t)buffer[pos+2]) << 16) | (((uint32_t) buffer[pos+3])) << 24)
|
||||||
|
|
||||||
// calculate combined ogf/ocf value
|
|
||||||
#define OPCODE(ogf, ocf) (ocf | ogf << 10)
|
|
||||||
|
|
||||||
// get HCI CMD OGF
|
|
||||||
#define READ_CMD_OGF(buffer) (buffer[1] >> 2)
|
|
||||||
#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])
|
|
||||||
|
|
||||||
// packet header lengh
|
// packet header lengh
|
||||||
#define HCI_CMD_DATA_PKT_HDR 0x03
|
#define HCI_CMD_DATA_PKT_HDR 0x03
|
||||||
#define HCI_ACL_DATA_PKT_HDR 0x04
|
#define HCI_ACL_DATA_PKT_HDR 0x04
|
||||||
#define HCI_SCO_DATA_PKT_HDR 0x03
|
#define HCI_SCO_DATA_PKT_HDR 0x03
|
||||||
#define HCI_EVENT_PKT_HDR 0x02
|
#define HCI_EVENT_PKT_HDR 0x02
|
||||||
|
|
||||||
// OGFs
|
|
||||||
#define OGF_LINK_CONTROL 0x01
|
|
||||||
#define OGF_CONTROLLER_BASEBAND 0x03
|
|
||||||
#define OGF_INFORMATIONAL_PARAMETERS 0x04
|
|
||||||
#define OGF_BTSTACK 0x3d
|
|
||||||
#define OGF_VENDOR 0x3f
|
|
||||||
|
|
||||||
// Events from host controller to host
|
// Events from host controller to host
|
||||||
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
|
#define HCI_EVENT_INQUIRY_COMPLETE 0x01
|
||||||
#define HCI_EVENT_INQUIRY_RESULT 0x02
|
#define HCI_EVENT_INQUIRY_RESULT 0x02
|
||||||
@ -75,12 +62,8 @@
|
|||||||
#define HCI_EVENT_BTSTACK_WORKING 0x80
|
#define HCI_EVENT_BTSTACK_WORKING 0x80
|
||||||
#define HCI_EVENT_BTSTACK_STATE 0x81
|
#define HCI_EVENT_BTSTACK_STATE 0x81
|
||||||
|
|
||||||
// cmds for BTstack
|
|
||||||
#define HCI_BTSTACK_GET_STATE 0x01
|
|
||||||
|
|
||||||
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode)
|
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default INQ Mode
|
* Default INQ Mode
|
||||||
*/
|
*/
|
||||||
@ -115,11 +98,6 @@ typedef enum {
|
|||||||
HCI_STATE_HALTING
|
HCI_STATE_HALTING
|
||||||
} HCI_STATE;
|
} HCI_STATE;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t opcode;
|
|
||||||
const char *format;
|
|
||||||
} hci_cmd_t;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SEND_NEGATIVE_LINK_KEY_REQUEST = 1 << 0,
|
SEND_NEGATIVE_LINK_KEY_REQUEST = 1 << 0,
|
||||||
SEND_PIN_CODE_RESPONSE = 1 << 1
|
SEND_PIN_CODE_RESPONSE = 1 << 1
|
||||||
@ -185,9 +163,9 @@ uint32_t hci_run();
|
|||||||
void hexdump(void *data, int size);
|
void hexdump(void *data, int size);
|
||||||
|
|
||||||
// create and send hci command packets based on a template and a list of parameters
|
// create and send hci command packets based on a template and a list of parameters
|
||||||
uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr);
|
|
||||||
uint16_t hci_create_cmd(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, ...);
|
|
||||||
int hci_send_cmd(hci_cmd_t *cmd, ...);
|
int hci_send_cmd(hci_cmd_t *cmd, ...);
|
||||||
|
|
||||||
|
// send complete CMD packet
|
||||||
int hci_send_cmd_packet(uint8_t *packet, int size);
|
int hci_send_cmd_packet(uint8_t *packet, int size);
|
||||||
|
|
||||||
// send ACL packet
|
// send ACL packet
|
||||||
@ -198,28 +176,3 @@ extern void bt_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
|
|||||||
extern void bt_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
|
extern void bt_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
|
||||||
extern void bt_flip_addr(bd_addr_t dest, bd_addr_t src);
|
extern void bt_flip_addr(bd_addr_t dest, bd_addr_t src);
|
||||||
|
|
||||||
// HCI Commands - see hci.c for info on parameters
|
|
||||||
extern hci_cmd_t hci_inquiry;
|
|
||||||
extern hci_cmd_t hci_inquiry_cancel;
|
|
||||||
extern hci_cmd_t hci_link_key_request_negative_reply;
|
|
||||||
extern hci_cmd_t hci_pin_code_request_reply;
|
|
||||||
extern hci_cmd_t hci_set_event_mask;
|
|
||||||
extern hci_cmd_t hci_reset;
|
|
||||||
extern hci_cmd_t hci_create_connection;
|
|
||||||
extern hci_cmd_t hci_host_buffer_size;
|
|
||||||
extern hci_cmd_t hci_write_authentication_enable;
|
|
||||||
extern hci_cmd_t hci_write_local_name;
|
|
||||||
extern hci_cmd_t hci_write_page_timeout;
|
|
||||||
extern hci_cmd_t hci_write_class_of_device;
|
|
||||||
extern hci_cmd_t hci_remote_name_request;
|
|
||||||
extern hci_cmd_t hci_remote_name_request_cancel;
|
|
||||||
extern hci_cmd_t hci_read_bd_addr;
|
|
||||||
extern hci_cmd_t hci_delete_stored_link_key;
|
|
||||||
extern hci_cmd_t hci_write_scan_enable;
|
|
||||||
extern hci_cmd_t hci_accept_connection_request;
|
|
||||||
extern hci_cmd_t hci_write_inquiry_mode;
|
|
||||||
extern hci_cmd_t hci_write_extended_inquiry_response;
|
|
||||||
extern hci_cmd_t hci_write_simple_pairing_mode;
|
|
||||||
|
|
||||||
// BTSTACK client/server commands - see hci.c for info on parameters
|
|
||||||
extern hci_cmd_t hci_get_btstack_state;
|
|
201
src/hci_cmds.c
Normal file
201
src/hci_cmds.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* hci_cmds.c
|
||||||
|
*
|
||||||
|
* Created by Matthias Ringwald on 7/23/09.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hci_cmds.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* construct HCI Command based on template
|
||||||
|
*
|
||||||
|
* Format:
|
||||||
|
* 1,2,3,4: one to four byte value
|
||||||
|
* H: HCI connection handle
|
||||||
|
* B: Bluetooth Baseband Address (BD_ADDR)
|
||||||
|
* P: 16 byte Pairing code
|
||||||
|
* N: Name up to 248 chars
|
||||||
|
* E: Extended Inquiry Result
|
||||||
|
*/
|
||||||
|
uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr){
|
||||||
|
|
||||||
|
hci_cmd_buffer[0] = cmd->opcode & 0xff;
|
||||||
|
hci_cmd_buffer[1] = cmd->opcode >> 8;
|
||||||
|
int pos = 3;
|
||||||
|
|
||||||
|
const char *format = cmd->format;
|
||||||
|
uint16_t word;
|
||||||
|
uint32_t longword;
|
||||||
|
uint8_t * ptr;
|
||||||
|
while (*format) {
|
||||||
|
switch(*format) {
|
||||||
|
case '1': // 8 bit value
|
||||||
|
case '2': // 16 bit value
|
||||||
|
case 'H': // hci_handle
|
||||||
|
word = va_arg(argptr, int); // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
|
||||||
|
hci_cmd_buffer[pos++] = word & 0xff;
|
||||||
|
if (*format == '2') {
|
||||||
|
hci_cmd_buffer[pos++] = word >> 8;
|
||||||
|
} else if (*format == 'H') {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
longword = va_arg(argptr, uint32_t);
|
||||||
|
// longword = va_arg(argptr, int);
|
||||||
|
hci_cmd_buffer[pos++] = longword;
|
||||||
|
hci_cmd_buffer[pos++] = longword >> 8;
|
||||||
|
hci_cmd_buffer[pos++] = longword >> 16;
|
||||||
|
if (*format == '4'){
|
||||||
|
hci_cmd_buffer[pos++] = longword >> 24;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'B': // bt-addr
|
||||||
|
ptr = va_arg(argptr, uint8_t *);
|
||||||
|
hci_cmd_buffer[pos++] = ptr[5];
|
||||||
|
hci_cmd_buffer[pos++] = ptr[4];
|
||||||
|
hci_cmd_buffer[pos++] = ptr[3];
|
||||||
|
hci_cmd_buffer[pos++] = ptr[2];
|
||||||
|
hci_cmd_buffer[pos++] = ptr[1];
|
||||||
|
hci_cmd_buffer[pos++] = ptr[0];
|
||||||
|
break;
|
||||||
|
case 'P': // c string passed as pascal string with leading 1-byte len
|
||||||
|
ptr = va_arg(argptr, uint8_t *);
|
||||||
|
memcpy(&hci_cmd_buffer[pos], ptr, 16);
|
||||||
|
pos += 16;
|
||||||
|
break;
|
||||||
|
case 'N': // UTF-8 string, null terminated
|
||||||
|
ptr = va_arg(argptr, uint8_t *);
|
||||||
|
memcpy(&hci_cmd_buffer[pos], ptr, 248);
|
||||||
|
pos += 248;
|
||||||
|
break;
|
||||||
|
case 'E': // Extended Inquiry Information 240 octets
|
||||||
|
ptr = va_arg(argptr, uint8_t *);
|
||||||
|
memcpy(&hci_cmd_buffer[pos], ptr, 240);
|
||||||
|
pos += 240;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
format++;
|
||||||
|
};
|
||||||
|
hci_cmd_buffer[2] = pos - 3;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* construct HCI Command based on template
|
||||||
|
*
|
||||||
|
* mainly calls hci_create_cmd_internal
|
||||||
|
*/
|
||||||
|
uint16_t hci_create_cmd(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, ...){
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, cmd);
|
||||||
|
uint16_t len = hci_create_cmd_internal(hci_cmd_buffer, cmd, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link Control Commands
|
||||||
|
*/
|
||||||
|
hci_cmd_t hci_inquiry = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x01), "311"
|
||||||
|
// LAP, Inquiry length, Num_responses
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_inquiry_cancel = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x02), ""
|
||||||
|
// no params
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_create_connection = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x05), "B21121"
|
||||||
|
// BD_ADDR, Packet_Type, Page_Scan_Repetition_Mode, Reserved, Clock_Offset, Allow_Role_Switch
|
||||||
|
};
|
||||||
|
|
||||||
|
hci_cmd_t hci_accept_connection_request = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x09), "B1"
|
||||||
|
// BD_ADDR, Role: become master, stay slave
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_link_key_request_negative_reply = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x0c), "B"
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_pin_code_request_reply = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x0d), "B1P"
|
||||||
|
// BD_ADDR, pin length, PIN: c-string
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_remote_name_request = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x19), "B112"
|
||||||
|
// BD_ADDR, Page_Scan_Repetition_Mode, Reserved, Clock_Offset
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_remote_name_request_cancel = {
|
||||||
|
OPCODE(OGF_LINK_CONTROL, 0x1A), "B"
|
||||||
|
// BD_ADDR
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller & Baseband Commands
|
||||||
|
*/
|
||||||
|
hci_cmd_t hci_set_event_mask = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x01), "44"
|
||||||
|
// event_mask lower 4 octets, higher 4 bytes
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_reset = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x03), ""
|
||||||
|
// no params
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_delete_stored_link_key = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x12), "B1"
|
||||||
|
// BD_ADDR, Delete_All_Flag
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_write_local_name = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x13), "N"
|
||||||
|
// Local name (UTF-8, Null Terminated, max 248 octets)
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_write_page_timeout = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x18), "2"
|
||||||
|
// Page_Timeout * 0.625 ms
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_write_scan_enable = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x1A), "1"
|
||||||
|
// Scan_enable: no, inq, page, inq+page
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_write_authentication_enable = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x20), "1"
|
||||||
|
// Authentication_Enable
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_write_class_of_device = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x24), "3"
|
||||||
|
// Class of Device
|
||||||
|
};
|
||||||
|
hci_cmd_t hci_host_buffer_size = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x33), "2122"
|
||||||
|
// Host_ACL_Data_Packet_Length:, Host_Synchronous_Data_Packet_Length:, Host_Total_Num_ACL_Data_Packets:, Host_Total_Num_Synchronous_Data_Packets:
|
||||||
|
};
|
||||||
|
|
||||||
|
hci_cmd_t hci_write_inquiry_mode = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x45), "1"
|
||||||
|
// Inquiry mode: 0x00 = standard, 0x01 = with RSSI, 0x02 = extended
|
||||||
|
};
|
||||||
|
|
||||||
|
hci_cmd_t hci_write_extended_inquiry_response = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x52), "1E"
|
||||||
|
// FEC_Required, Exstended Inquiry Response
|
||||||
|
};
|
||||||
|
|
||||||
|
hci_cmd_t hci_write_simple_pairing_mode = {
|
||||||
|
OPCODE(OGF_CONTROLLER_BASEBAND, 0x56), "1"
|
||||||
|
// mode: 0 = off, 1 = on
|
||||||
|
};
|
||||||
|
|
||||||
|
hci_cmd_t hci_read_bd_addr = {
|
||||||
|
OPCODE(OGF_INFORMATIONAL_PARAMETERS, 0x09), ""
|
||||||
|
// no params
|
||||||
|
};
|
||||||
|
|
||||||
|
hci_cmd_t hci_get_btstack_state = {
|
||||||
|
OPCODE(OGF_BTSTACK, HCI_BTSTACK_GET_STATE), ""
|
||||||
|
// no params ->
|
||||||
|
};
|
||||||
|
|
67
src/hci_cmds.h
Normal file
67
src/hci_cmds.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* hci_cmds.h
|
||||||
|
*
|
||||||
|
* Created by Matthias Ringwald on 7/23/09.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// calculate combined ogf/ocf value
|
||||||
|
#define OPCODE(ogf, ocf) (ocf | ogf << 10)
|
||||||
|
|
||||||
|
// get HCI CMD OGF
|
||||||
|
#define READ_CMD_OGF(buffer) (buffer[1] >> 2)
|
||||||
|
#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])
|
||||||
|
|
||||||
|
// OGFs
|
||||||
|
#define OGF_LINK_CONTROL 0x01
|
||||||
|
#define OGF_CONTROLLER_BASEBAND 0x03
|
||||||
|
#define OGF_INFORMATIONAL_PARAMETERS 0x04
|
||||||
|
#define OGF_BTSTACK 0x3d
|
||||||
|
#define OGF_VENDOR 0x3f
|
||||||
|
|
||||||
|
// cmds for BTstack
|
||||||
|
#define HCI_BTSTACK_GET_STATE 0x01
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* compact HCI Command packet description
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint16_t opcode;
|
||||||
|
const char *format;
|
||||||
|
} hci_cmd_t;
|
||||||
|
|
||||||
|
// create and send hci command packets based on a template and a list of parameters
|
||||||
|
uint16_t hci_create_cmd(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, ...);
|
||||||
|
uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr);
|
||||||
|
|
||||||
|
// HCI Commands - see hci_cmds.c for info on parameters
|
||||||
|
extern hci_cmd_t hci_inquiry;
|
||||||
|
extern hci_cmd_t hci_inquiry_cancel;
|
||||||
|
extern hci_cmd_t hci_link_key_request_negative_reply;
|
||||||
|
extern hci_cmd_t hci_pin_code_request_reply;
|
||||||
|
extern hci_cmd_t hci_set_event_mask;
|
||||||
|
extern hci_cmd_t hci_reset;
|
||||||
|
extern hci_cmd_t hci_create_connection;
|
||||||
|
extern hci_cmd_t hci_host_buffer_size;
|
||||||
|
extern hci_cmd_t hci_write_authentication_enable;
|
||||||
|
extern hci_cmd_t hci_write_local_name;
|
||||||
|
extern hci_cmd_t hci_write_page_timeout;
|
||||||
|
extern hci_cmd_t hci_write_class_of_device;
|
||||||
|
extern hci_cmd_t hci_remote_name_request;
|
||||||
|
extern hci_cmd_t hci_remote_name_request_cancel;
|
||||||
|
extern hci_cmd_t hci_read_bd_addr;
|
||||||
|
extern hci_cmd_t hci_delete_stored_link_key;
|
||||||
|
extern hci_cmd_t hci_write_scan_enable;
|
||||||
|
extern hci_cmd_t hci_accept_connection_request;
|
||||||
|
extern hci_cmd_t hci_write_inquiry_mode;
|
||||||
|
extern hci_cmd_t hci_write_extended_inquiry_response;
|
||||||
|
extern hci_cmd_t hci_write_simple_pairing_mode;
|
||||||
|
|
||||||
|
// BTSTACK client/server commands - see hci.c for info on parameters
|
||||||
|
extern hci_cmd_t hci_get_btstack_state;
|
Loading…
x
Reference in New Issue
Block a user