util.h: move some to hci.h and btstack_link_key_db_fs

This commit is contained in:
Matthias Ringwald 2016-02-10 13:35:25 +01:00
parent 8974fcd6cf
commit caed94df78
6 changed files with 391 additions and 126 deletions

View File

@ -123,6 +123,10 @@ const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void);
// ATT_MTU - 1
#define ATT_MAX_ATTRIBUTE_SIZE 22
// HCI CMD OGF/OCF
#define READ_CMD_OGF(buffer) (buffer[1] >> 2)
#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])
typedef struct {
// linked list - assert: first field
btstack_linked_item_t item;

View File

@ -0,0 +1,183 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "btstack_link_key_db_fs.h"
#include "btstack_debug.h"
#include "btstack_util.h"
#define LINK_KEY_PATH "/tmp/"
#define LINK_KEY_PREFIX "btstack_link_key_"
#define LINK_KEY_SUFIX ".txt"
static char keypath[sizeof(LINK_KEY_PATH) + sizeof(LINK_KEY_PREFIX) + 17 + sizeof(LINK_KEY_SUFIX) + 1];
static char bd_addr_to_dash_str_buffer[6*3]; // 12-45-78-01-34-67\0
static char * bd_addr_to_dash_str(bd_addr_t addr){
char * p = bd_addr_to_dash_str_buffer;
int i;
for (i = 0; i < 6 ; i++) {
*p++ = char_for_nibble((addr[i] >> 4) & 0x0F);
*p++ = char_for_nibble((addr[i] >> 0) & 0x0F);
*p++ = '-';
}
*--p = 0;
return (char *) bd_addr_to_dash_str_buffer;
}
static void set_path(bd_addr_t bd_addr){
strcpy(keypath, LINK_KEY_PATH);
strcat(keypath, LINK_KEY_PREFIX);
strcat(keypath, bd_addr_to_dash_str(bd_addr));
strcat(keypath, LINK_KEY_SUFIX);
}
// Device info
static void db_open(void){
}
static void db_close(void){
}
static void put_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t link_key_type){
set_path(bd_addr);
char * link_key_str = link_key_to_str(link_key);
char * link_key_type_str = link_key_type_to_str(link_key_type);
FILE * wFile = fopen(keypath,"w+");
fwrite(link_key_str, strlen(link_key_str), 1, wFile);
fwrite(link_key_type_str, strlen(link_key_type_str), 1, wFile);
fclose(wFile);
}
static int get_link_key(bd_addr_t bd_addr, link_key_t link_key, link_key_type_t * link_key_type) {
set_path(bd_addr);
if (access(keypath, R_OK)) return 0;
char link_key_str[LINK_KEY_STR_LEN + 1];
char link_key_type_str[2];
FILE * rFile = fopen(keypath,"r+");
size_t objects_read = fread(link_key_str, LINK_KEY_STR_LEN, 1, rFile );
if (objects_read == 1){
link_key_str[LINK_KEY_STR_LEN] = 0;
log_info("Found link key %s\n", link_key_str);
objects_read = fread(link_key_type_str, 1, 1, rFile );
}
fclose(rFile);
if (objects_read != 1) return 0;
link_key_type_str[1] = 0;
log_info("Found link key type %s\n", link_key_type_str);
int scan_result = sscanf_link_key(link_key_str, link_key);
if (scan_result == 0 ) return 0;
int link_key_type_buffer;
scan_result = sscanf( (char *) link_key_type_str, "%d", &link_key_type_buffer);
if (scan_result == 0 ) return 0;
*link_key_type = (link_key_type_t) link_key_type_buffer;
return 1;
}
static void delete_link_key(bd_addr_t bd_addr){
set_path(bd_addr);
if (access(keypath, R_OK)) return;
if(remove(keypath) != 0){
log_error("File %s could not be deleted.\n", keypath);
}
}
const btstack_link_key_db_t btstack_link_key_db_fs = {
db_open,
db_close,
get_link_key,
put_link_key,
delete_link_key,
};
const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void){
return &btstack_link_key_db_fs;
}
static char link_key_to_str_buffer[LINK_KEY_STR_LEN+1]; // 11223344556677889900112233445566\0
char *link_key_to_str(link_key_t link_key){
char * p = link_key_to_str_buffer;
int i;
for (i = 0; i < LINK_KEY_LEN ; i++) {
*p++ = char_for_nibble((link_key[i] >> 4) & 0x0F);
*p++ = char_for_nibble((link_key[i] >> 0) & 0x0F);
}
*p = 0;
return (char *) link_key_to_str_buffer;
}
static char link_key_type_to_str_buffer[2];
char *link_key_type_to_str(link_key_type_t link_key){
snprintf(link_key_type_to_str_buffer, sizeof(link_key_type_to_str_buffer), "%d", link_key);
return (char *) link_key_type_to_str_buffer;
}
int sscanf_link_key(char * addr_string, link_key_t link_key){
unsigned int buffer[LINK_KEY_LEN];
// reset result buffer
memset(&buffer, 0, sizeof(buffer));
// parse
int result = sscanf( (char *) addr_string, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
&buffer[0], &buffer[1], &buffer[2], &buffer[3],
&buffer[4], &buffer[5], &buffer[6], &buffer[7],
&buffer[8], &buffer[9], &buffer[10], &buffer[11],
&buffer[12], &buffer[13], &buffer[14], &buffer[15] );
if (result != LINK_KEY_LEN) return 0;
// store
int i;
uint8_t *p = (uint8_t *) link_key;
for (i=0; i<LINK_KEY_LEN; i++ ) {
*p++ = (uint8_t) buffer[i];
}
return 1;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 4. Any redistribution, use, or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain.
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Please inquire about commercial licensing options at
* contact@bluekitchen-gmbh.com
*
*/
#ifndef __BTSTACK_LINK_KEY_DB_FS_H
#define __BTSTACK_LINK_KEY_DB_FS_H
#include "classic/btstack_link_key_db.h"
#if defined __cplusplus
extern "C" {
#endif
/*
* @brief Get basic link key db implementation that stores link keys in /tmp
*/
const btstack_link_key_db_t * btstack_link_key_db_fs_instance(void);
/**
* @brief Create human readable represenationt of link key
* @note uses fixed global buffer
* @return pointer to Bluetooth address string
*/
char * link_key_to_str(link_key_t link_key);
/**
* @brief return string for link key type
* @note uses fixed global buffer
* @param link_key_type
* @return link_key_type as string
*/
char *link_key_type_to_str(link_key_type_t link_key_type);
/**
* @brief Parse link key string
* @param addr_strings
* @param link_key buffer for result
* @return 1 on success
*/
int sscanf_link_key(char * addr_string, link_key_t link_key);
/* API_END */
#if defined __cplusplus
}
#endif
#endif // __BTSTACK_LINK_KEY_DB_FS_H

View File

@ -120,6 +120,37 @@ void printf_hexdump(const void *data, int size){
printf("\n");
}
void hexdumpf(const void *data, int size){
char buffer[6*16+1];
int i, j;
uint8_t low = 0x0F;
uint8_t high = 0xF0;
j = 0;
for (i=0; i<size;i++){
uint8_t byte = ((uint8_t *)data)[i];
buffer[j++] = '0';
buffer[j++] = 'x';
buffer[j++] = char_for_nibble((byte & high) >> 4);
buffer[j++] = char_for_nibble(byte & low);
buffer[j++] = ',';
buffer[j++] = ' ';
if (j >= 6*16 ){
buffer[j] = 0;
printf("%s\n", buffer);
j = 0;
}
}
if (j != 0){
buffer[j] = 0;
printf("%s\n", buffer);
}
}
// void log_info_hexdump(..){
//
// }
void hexdump(const void *data, int size){
#ifdef ENABLE_LOG_INFO
char buffer[6*16+1];
@ -149,33 +180,6 @@ void hexdump(const void *data, int size){
#endif
}
void hexdumpf(const void *data, int size){
char buffer[6*16+1];
int i, j;
uint8_t low = 0x0F;
uint8_t high = 0xF0;
j = 0;
for (i=0; i<size;i++){
uint8_t byte = ((uint8_t *)data)[i];
buffer[j++] = '0';
buffer[j++] = 'x';
buffer[j++] = char_for_nibble((byte & high) >> 4);
buffer[j++] = char_for_nibble(byte & low);
buffer[j++] = ',';
buffer[j++] = ' ';
if (j >= 6*16 ){
buffer[j] = 0;
printf("%s\n", buffer);
j = 0;
}
}
if (j != 0){
buffer[j] = 0;
printf("%s\n", buffer);
}
}
void log_key(const char * name, sm_key_t key){
log_info("%-6s ", name);
hexdump(key, 16);
@ -221,24 +225,6 @@ char * bd_addr_to_str(bd_addr_t addr){
return (char *) bd_addr_to_str_buffer;
}
static char link_key_to_str_buffer[LINK_KEY_STR_LEN+1]; // 11223344556677889900112233445566\0
char *link_key_to_str(link_key_t link_key){
char * p = link_key_to_str_buffer;
int i;
for (i = 0; i < LINK_KEY_LEN ; i++) {
*p++ = char_for_nibble((link_key[i] >> 4) & 0x0F);
*p++ = char_for_nibble((link_key[i] >> 0) & 0x0F);
}
*p = 0;
return (char *) link_key_to_str_buffer;
}
static char link_key_type_to_str_buffer[2];
char *link_key_type_to_str(link_key_type_t link_key){
snprintf(link_key_type_to_str_buffer, sizeof(link_key_type_to_str_buffer), "%d", link_key);
return (char *) link_key_type_to_str_buffer;
}
void print_bd_addr( bd_addr_t addr){
log_info("%s", bd_addr_to_str(addr));
}
@ -262,42 +248,6 @@ int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr){
return 1;
}
int sscan_link_key(char * addr_string, link_key_t link_key){
unsigned int buffer[LINK_KEY_LEN];
// reset result buffer
memset(&buffer, 0, sizeof(buffer));
// parse
int result = sscanf( (char *) addr_string, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
&buffer[0], &buffer[1], &buffer[2], &buffer[3],
&buffer[4], &buffer[5], &buffer[6], &buffer[7],
&buffer[8], &buffer[9], &buffer[10], &buffer[11],
&buffer[12], &buffer[13], &buffer[14], &buffer[15] );
if (result != LINK_KEY_LEN) return 0;
// store
int i;
uint8_t *p = (uint8_t *) link_key;
for (i=0; i<LINK_KEY_LEN; i++ ) {
*p++ = (uint8_t) buffer[i];
}
return 1;
}
// treat standard pairing as Authenticated as it uses a PIN
int is_authenticated_link_key(link_key_type_t link_key_type){
switch (link_key_type){
case COMBINATION_KEY:
case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P192:
case AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256:
return 1;
default:
return 0;
}
}
/*
* CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.

View File

@ -65,38 +65,17 @@ extern "C" {
typedef uint8_t device_name_t[DEVICE_NAME_LEN+1];
// helper for BT little endian format
// helper for little endian format
#define little_endian_read_16( buffer, pos) ( ((uint16_t) buffer[pos]) | (((uint16_t)buffer[(pos)+1]) << 8))
#define little_endian_read_24( buffer, pos) ( ((uint32_t) buffer[pos]) | (((uint32_t)buffer[(pos)+1]) << 8) | (((uint32_t)buffer[(pos)+2]) << 16))
#define little_endian_read_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)
// helper for SDP big endian format
#define big_endian_read_16( buffer, pos) ( ((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos ]) << 8))
#define bit_endian_read_32( buffer, pos) ( ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos])) << 24)
// HCI CMD OGF/OCF
#define READ_CMD_OGF(buffer) (buffer[1] >> 2)
#define READ_CMD_OCF(buffer) ((buffer[1] & 0x03) << 8 | buffer[0])
// check if command complete event for given command
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && little_endian_read_16(event,3) == cmd.opcode)
#define COMMAND_STATUS_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_STATUS && little_endian_read_16(event,4) == cmd.opcode)
// Code+Len=2, Pkts+Opcode=3; total=5
#define OFFSET_OF_DATA_IN_COMMAND_COMPLETE 5
// ACL Packet
#define READ_ACL_CONNECTION_HANDLE( buffer ) ( little_endian_read_16(buffer,0) & 0x0fff)
#define READ_ACL_FLAGS( buffer ) ( buffer[1] >> 4 )
#define READ_ACL_LENGTH( buffer ) (little_endian_read_16(buffer, 2))
// L2CAP Packet
#define READ_L2CAP_LENGTH(buffer) ( little_endian_read_16(buffer, 4))
#define READ_L2CAP_CHANNEL_ID(buffer) ( little_endian_read_16(buffer, 6))
void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
void bt_flip_addr(bd_addr_t dest, bd_addr_t src);
// helper for big endian format
#define big_endian_read_16( buffer, pos) ( ((uint16_t) buffer[(pos)+1]) | (((uint16_t)buffer[ pos ]) << 8))
#define bit_endian_read_32( buffer, pos) ( ((uint32_t) buffer[(pos)+3]) | (((uint32_t)buffer[(pos)+2]) << 8) | (((uint32_t)buffer[(pos)+1]) << 16) | (((uint32_t) buffer[pos])) << 24)
void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value);
void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
@ -106,6 +85,9 @@ void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value);
#undef swap64
#endif
/**
* @brief Copy from source to destination and reverse byte order
*/
void swapX (const uint8_t *src, uint8_t * dst, int len);
void swap24 (const uint8_t *src, uint8_t * dst);
void swap48 (const uint8_t *src, uint8_t * dst);
@ -113,36 +95,85 @@ void swap56 (const uint8_t *src, uint8_t * dst);
void swap64 (const uint8_t *src, uint8_t * dst);
void swap128(const uint8_t *src, uint8_t * dst);
void bt_flip_addr(bd_addr_t dest, bd_addr_t src);
/**
* @brief 4-bit nibble
* @return ASCII character for 4-bit nibble
*/
char char_for_nibble(int nibble);
void printf_hexdump(const void *data, int size);
void hexdump(const void *data, int size);
void hexdumpf(const void *data, int size);
char * uuid128_to_str(uint8_t * uuid);
void printUUID128(uint8_t *uuid);
void log_key(const char * name, sm_key_t key);
/**
* @brief Compare two Bluetooth addresses
* @param a
* @param b
* @return true if equal
*/
#define BD_ADDR_CMP(a,b) memcmp(a,b, BD_ADDR_LEN)
/**
* @brief Copy Bluetooth address
* @param dest
* @param src
*/
#define BD_ADDR_COPY(dest,src) memcpy(dest,src,BD_ADDR_LEN)
/**
* CRC8 functions using ETSI TS 101 369 V6.3.0.
* Only needed by RFCOMM
*/
uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum);
uint8_t crc8_calc(uint8_t *data, uint16_t len);
// @deprecated please use more convenient bd_addr_to_str
void print_bd_addr( bd_addr_t addr);
/**
* @brief Use printf to write hexdump as single line of data
*/
void printf_hexdump(const void *data, int size);
// move to btstack_debug.h
// void log_info_hexdump(..) either log or hci_dump or off
void log_key(const char * name, sm_key_t key);
//
void hexdump(const void *data, int size);
void hexdumpf(const void *data, int size);
/**
* @brief Create human readable representation for UUID128
* @note uses fixed global buffer
* @return pointer to UUID128 string
*/
char * uuid128_to_str(uint8_t * uuid);
/**
* @brief Print UUID128
* @note uses fixed global buffer
*/
void printUUID128(uint8_t *uuid);
/**
* @brief Create human readable represenationt of Bluetooth address
* @note uses fixed global buffer
* @return pointer to Bluetooth address string
*/
char * bd_addr_to_str(bd_addr_t addr);
char * link_key_to_str(link_key_t link_key);
char *link_key_type_to_str(link_key_type_t link_key);
/**
* @brief Parse Bluetooth address
* @param address_string
* @param buffer for parsed address
* @return 1 if string was parsed successfully
*/
int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr);
void sdp_normalize_uuid(uint8_t *uuid, uint32_t shortUUID);
int sdp_has_blueooth_base_uuid(uint8_t * uuid128);
int sscan_bd_addr(uint8_t * addr_string, bd_addr_t addr);
int sscan_link_key(char * addr_string, link_key_t link_key);
uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum);
uint8_t crc8_calc(uint8_t *data, uint16_t len);
#define BD_ADDR_CMP(a,b) memcmp(a,b, BD_ADDR_LEN)
#define BD_ADDR_COPY(dest,src) memcpy(dest,src,BD_ADDR_LEN)
int is_authenticated_link_key(link_key_type_t link_key_type);
#if defined __cplusplus
}
#endif

View File

@ -102,6 +102,22 @@ extern "C" {
//
#define IS_COMMAND(packet, command) (little_endian_read_16(packet,0) == command.opcode)
// check if command complete event for given command
#define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && little_endian_read_16(event,3) == cmd.opcode)
#define COMMAND_STATUS_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_STATUS && little_endian_read_16(event,4) == cmd.opcode)
// Code+Len=2, Pkts+Opcode=3; total=5
#define OFFSET_OF_DATA_IN_COMMAND_COMPLETE 5
// ACL Packet
#define READ_ACL_CONNECTION_HANDLE( buffer ) ( little_endian_read_16(buffer,0) & 0x0fff)
#define READ_ACL_FLAGS( buffer ) ( buffer[1] >> 4 )
#define READ_ACL_LENGTH( buffer ) (little_endian_read_16(buffer, 2))
// Sneak peak into L2CAP Packet
#define READ_L2CAP_LENGTH(buffer) ( little_endian_read_16(buffer, 4))
#define READ_L2CAP_CHANNEL_ID(buffer) ( little_endian_read_16(buffer, 6))
/**
* LE connection parameter update state
*/