mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-20 18:40:31 +00:00
Merge branch 'master' into ble-api-cleanup
This commit is contained in:
commit
1e35c04d3c
@ -125,9 +125,9 @@ static uint16_t ehcill_defer_rx_size = 0;
|
||||
static uint8_t ehcill_command_to_send;
|
||||
|
||||
// H4: packet reader state machine
|
||||
static H4_STATE h4_state;
|
||||
static int read_pos;
|
||||
static int bytes_to_read;
|
||||
static volatile H4_STATE h4_state;
|
||||
static int read_pos;
|
||||
static int bytes_to_read;
|
||||
|
||||
// bigger than largest packet
|
||||
static uint8_t hci_packet_prefixed[HCI_INCOMING_PRE_BUFFER_SIZE + HCI_PACKET_BUFFER_SIZE];
|
||||
@ -136,8 +136,8 @@ static uint8_t * hci_packet = &hci_packet_prefixed[HCI_INCOMING_PRE_BUFFER_SIZE]
|
||||
static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;
|
||||
|
||||
// H4: tx state
|
||||
static TX_STATE tx_state;
|
||||
static int tx_send_packet_sent;
|
||||
static volatile TX_STATE tx_state; // updated from block_sent callback
|
||||
static volatile int tx_send_packet_sent; // updated from block_sent callback
|
||||
static uint8_t * tx_data;
|
||||
static uint16_t tx_len;
|
||||
static uint8_t tx_packet_type;
|
||||
@ -225,11 +225,10 @@ static int h4_close(void *transport_config){
|
||||
return 0;
|
||||
}
|
||||
|
||||
// potentially called from ISR context
|
||||
static void h4_block_received(void){
|
||||
|
||||
// gpio_set(GPIOB, GPIO_DEBUG_0);
|
||||
|
||||
read_pos += bytes_to_read;
|
||||
read_pos += bytes_to_read;
|
||||
|
||||
// act
|
||||
switch (h4_state) {
|
||||
@ -300,11 +299,10 @@ static void h4_block_received(void){
|
||||
|
||||
static int h4_can_send_packet_now(uint8_t packet_type){
|
||||
return tx_state == TX_IDLE;
|
||||
|
||||
}
|
||||
|
||||
static void ehcill_sleep_ack_timer_handler(timer_source_t * timer){
|
||||
tx_state = TX_W4_EHCILL_SENT;
|
||||
// gpio_clear(GPIOB, GPIO_DEBUG_1);
|
||||
hal_uart_dma_send_block(&ehcill_command_to_send, 1);
|
||||
}
|
||||
|
||||
@ -316,6 +314,7 @@ static void ehcill_sleep_ack_timer_setup(void){
|
||||
embedded_trigger();
|
||||
}
|
||||
|
||||
// potentially called from ISR context
|
||||
static void h4_block_sent(void){
|
||||
switch (tx_state){
|
||||
case TX_W4_HEADER_SENT:
|
||||
@ -324,22 +323,22 @@ static void h4_block_sent(void){
|
||||
hal_uart_dma_send_block(tx_data, tx_len);
|
||||
break;
|
||||
case TX_W4_PACKET_SENT:
|
||||
// non-ehcill packet sent, confirm
|
||||
tx_send_packet_sent = 1;
|
||||
|
||||
// send pending ehcill command if neccessary
|
||||
switch (ehcill_command_to_send){
|
||||
case EHCILL_GO_TO_SLEEP_ACK:
|
||||
ehcill_sleep_ack_timer_setup();
|
||||
tx_send_packet_sent = 1;
|
||||
break;
|
||||
case EHCILL_WAKE_UP_IND:
|
||||
tx_state = TX_W4_EHCILL_SENT;
|
||||
// gpio_clear(GPIOB, GPIO_DEBUG_1);
|
||||
hal_uart_dma_send_block(&ehcill_command_to_send, 1);
|
||||
tx_send_packet_sent = 1;
|
||||
break;
|
||||
default:
|
||||
// trigger run loop
|
||||
tx_state = TX_DONE;
|
||||
tx_send_packet_sent = 1;
|
||||
embedded_trigger();
|
||||
break;
|
||||
}
|
||||
@ -369,6 +368,12 @@ static int h4_process(struct data_source *ds) {
|
||||
|
||||
// notify about packet sent
|
||||
if (tx_send_packet_sent){
|
||||
// race condition: if tx_state was set after our check, can_send_now will fail, causing a hang
|
||||
// workaround: assert that tx_state is TX_IDLE if it was just set to done by ISR
|
||||
if (tx_state == TX_DONE){
|
||||
tx_state = TX_IDLE;
|
||||
}
|
||||
|
||||
tx_send_packet_sent = 0;
|
||||
uint8_t event[] = { DAEMON_EVENT_HCI_PACKET_SENT, 0 };
|
||||
packet_handler(HCI_EVENT_PACKET, &event[0], sizeof(event));
|
||||
|
@ -130,6 +130,7 @@ const char * hfp_ag_feature(int index){
|
||||
}
|
||||
|
||||
int send_str_over_rfcomm(uint16_t cid, char * command){
|
||||
log_info("HFP_TX %s", command);
|
||||
if (!rfcomm_can_send_packet_now(cid)) return 1;
|
||||
int err = rfcomm_send_internal(cid, (uint8_t*) command, strlen(command));
|
||||
if (err){
|
||||
|
@ -1523,6 +1523,12 @@ static hfp_generic_status_indicator_t *get_hf_indicator_by_number(int number){
|
||||
static void hfp_handle_rfcomm_data(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
|
||||
if (!context) return;
|
||||
|
||||
char last_char = packet[size-1];
|
||||
packet[size-1] = 0;
|
||||
log_info("HFP_RX %s", packet);
|
||||
packet[size-1] = last_char;
|
||||
|
||||
int pos;
|
||||
for (pos = 0; pos < size ; pos++){
|
||||
hfp_parse(context, packet[pos], 0);
|
||||
@ -1765,6 +1771,11 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
|
||||
hfp_run();
|
||||
}
|
||||
|
||||
static void hfp_ag_set_ag_indicators(hfp_ag_indicator_t * ag_indicators, int ag_indicators_nr){
|
||||
hfp_ag_indicators_nr = ag_indicators_nr;
|
||||
memcpy(hfp_ag_indicators, ag_indicators, ag_indicators_nr * sizeof(hfp_ag_indicator_t));
|
||||
}
|
||||
|
||||
void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features,
|
||||
uint8_t * codecs, int codecs_nr,
|
||||
hfp_ag_indicator_t * ag_indicators, int ag_indicators_nr,
|
||||
@ -1789,8 +1800,7 @@ void hfp_ag_init(uint16_t rfcomm_channel_nr, uint32_t supported_features,
|
||||
hfp_codecs[i] = codecs[i];
|
||||
}
|
||||
|
||||
hfp_ag_indicators_nr = ag_indicators_nr;
|
||||
memcpy(hfp_ag_indicators, ag_indicators, ag_indicators_nr * sizeof(hfp_ag_indicator_t));
|
||||
hfp_ag_set_ag_indicators(ag_indicators, ag_indicators_nr);
|
||||
|
||||
set_hfp_generic_status_indicators(hf_indicators, hf_indicators_nr);
|
||||
|
||||
|
@ -919,9 +919,12 @@ static void hfp_handle_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8
|
||||
hfp_connection_t * context = get_hfp_connection_context_for_rfcomm_cid(channel);
|
||||
if (!context) return;
|
||||
|
||||
packet[size] = 0;
|
||||
char last_char = packet[size-1];
|
||||
packet[size-1] = 0;
|
||||
log_info("HFP_RX %s", packet);
|
||||
packet[size-1] = last_char;
|
||||
|
||||
int pos, i, value;
|
||||
//printf("\nHF received: %s", packet+2);
|
||||
for (pos = 0; pos < size ; pos++){
|
||||
hfp_parse(context, packet[pos], 1);
|
||||
}
|
||||
@ -1034,8 +1037,6 @@ void hfp_hf_set_codecs(uint8_t * codecs, int codecs_nr){
|
||||
char buffer[30];
|
||||
int offset = join(buffer, sizeof(buffer), hfp_codecs, hfp_codecs_nr);
|
||||
buffer[offset] = 0;
|
||||
printf("set codecs %s\n", buffer);
|
||||
|
||||
linked_list_iterator_t it;
|
||||
linked_list_iterator_init(&it, hfp_get_connections());
|
||||
while (linked_list_iterator_has_next(&it)){
|
||||
|
@ -406,7 +406,7 @@ static void hsp_run(void){
|
||||
int gain = ag_microphone_gain;
|
||||
ag_microphone_gain = -1;
|
||||
char buffer[10];
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_MICROPHONE_GAIN, ag_microphone_gain);
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_MICROPHONE_GAIN, gain);
|
||||
err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, buffer);
|
||||
if (err) {
|
||||
ag_microphone_gain = gain;
|
||||
@ -418,7 +418,7 @@ static void hsp_run(void){
|
||||
int gain = ag_speaker_gain;
|
||||
ag_speaker_gain = -1;
|
||||
char buffer[10];
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_SPEAKER_GAIN, ag_speaker_gain);
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_SPEAKER_GAIN, gain);
|
||||
err = hsp_ag_send_str_over_rfcomm(rfcomm_cid, buffer);
|
||||
if (err) {
|
||||
ag_speaker_gain = gain;
|
||||
|
@ -352,7 +352,7 @@ static void hsp_run(void){
|
||||
int gain = hs_microphone_gain;
|
||||
hs_microphone_gain = -1;
|
||||
char buffer[20];
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain);
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, gain);
|
||||
err = hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
|
||||
if (err) {
|
||||
hs_microphone_gain = gain;
|
||||
@ -364,7 +364,7 @@ static void hsp_run(void){
|
||||
int gain = hs_speaker_gain;
|
||||
hs_speaker_gain = -1;
|
||||
char buffer[20];
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, hs_speaker_gain);
|
||||
sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, gain);
|
||||
err = hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
|
||||
if (err) {
|
||||
hs_speaker_gain = gain;
|
||||
|
@ -74,9 +74,6 @@
|
||||
|
||||
#include "l2cap.h"
|
||||
|
||||
// used for debugging
|
||||
// #define RFCOMM_LOG_CREDITS
|
||||
|
||||
// global rfcomm data
|
||||
static uint16_t rfcomm_client_cid_generator; // used for client channel IDs
|
||||
|
||||
@ -136,20 +133,6 @@ static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status
|
||||
(*app_packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, pos);
|
||||
}
|
||||
|
||||
// data: event(8), len(8), creidts incoming(8), new credits incoming(8), credits outgoing(8)
|
||||
static inline void rfcomm_emit_credit_status(rfcomm_channel_t * channel) {
|
||||
#ifdef RFCOMM_LOG_CREDITS
|
||||
log_info("RFCOMM_LOG_CREDITS incoming %u new_incoming %u outgoing %u", channel->credits_incoming, channel->new_credits_incoming, channel->credits_outgoing);
|
||||
uint8_t event[5];
|
||||
event[0] = 0x88;
|
||||
event[1] = sizeof(event) - 2;
|
||||
event[2] = channel->credits_incoming;
|
||||
event[3] = channel->new_credits_incoming;
|
||||
event[4] = channel->credits_outgoing;
|
||||
hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
#endif
|
||||
}
|
||||
|
||||
// data: event(8), len(8), rfcomm_cid(16)
|
||||
static void rfcomm_emit_channel_closed(rfcomm_channel_t * channel) {
|
||||
log_info("RFCOMM_EVENT_CHANNEL_CLOSED cid 0x%02x", channel->rfcomm_cid);
|
||||
@ -251,7 +234,6 @@ static void rfcomm_multiplexer_initialize(rfcomm_multiplexer_t *multiplexer){
|
||||
memset(multiplexer, 0, sizeof(rfcomm_multiplexer_t));
|
||||
|
||||
multiplexer->state = RFCOMM_MULTIPLEXER_CLOSED;
|
||||
multiplexer->l2cap_credits = 0;
|
||||
multiplexer->fcon = 1;
|
||||
multiplexer->send_dm_for_dlci = 0;
|
||||
multiplexer->max_frame_size = rfcomm_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
|
||||
@ -466,20 +448,8 @@ static int rfcomm_send_packet_for_multiplexer(rfcomm_multiplexer_t *multiplexer,
|
||||
}
|
||||
rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, crc_fields); // calc fcs
|
||||
|
||||
int credits_taken = 0;
|
||||
if (multiplexer->l2cap_credits){
|
||||
credits_taken++;
|
||||
multiplexer->l2cap_credits--;
|
||||
} else {
|
||||
log_info( "rfcomm_send_packet addr %02x, ctrl %02x size %u without l2cap credits", address, control, pos);
|
||||
}
|
||||
|
||||
int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
|
||||
|
||||
if (err) {
|
||||
// undo credit counting
|
||||
multiplexer->l2cap_credits += credits_taken;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -502,21 +472,9 @@ static int rfcomm_send_uih_prepared(rfcomm_multiplexer_t *multiplexer, uint8_t d
|
||||
|
||||
// UIH frames only calc FCS over address + control (5.1.1)
|
||||
rfcomm_out_buffer[pos++] = crc8_calc(rfcomm_out_buffer, 2); // calc fcs
|
||||
|
||||
int credits_taken = 0;
|
||||
if (multiplexer->l2cap_credits){
|
||||
credits_taken++;
|
||||
multiplexer->l2cap_credits--;
|
||||
} else {
|
||||
log_info( "rfcomm_send_uih_prepared addr %02x, ctrl %02x size %u without l2cap credits", address, control, pos);
|
||||
}
|
||||
|
||||
int err = l2cap_send_prepared(multiplexer->l2cap_cid, pos);
|
||||
|
||||
if (err) {
|
||||
// undo credit counting
|
||||
multiplexer->l2cap_credits += credits_taken;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -926,8 +884,6 @@ static int rfcomm_multiplexer_hci_event_handler(uint8_t *packet, uint16_t size){
|
||||
l2cap_cid = READ_BT_16(packet, 2);
|
||||
multiplexer = rfcomm_multiplexer_for_l2cap_cid(l2cap_cid);
|
||||
if (!multiplexer) break;
|
||||
multiplexer->l2cap_credits += packet[4];
|
||||
|
||||
// log_info("L2CAP_EVENT_CREDITS: %u (now %u)", packet[4], multiplexer->l2cap_credits);
|
||||
|
||||
// new credits, continue with signaling
|
||||
@ -1180,10 +1136,6 @@ static void rfcomm_hand_out_credits(void){
|
||||
// log_info("RFCOMM_EVENT_CREDITS: no outgoing credits");
|
||||
continue;
|
||||
}
|
||||
if (!channel->multiplexer->l2cap_credits){
|
||||
// log_info("RFCOMM_EVENT_CREDITS: no l2cap credits");
|
||||
continue;
|
||||
}
|
||||
// channel open, multiplexer has l2cap credits and we didn't hand out credit before -> go!
|
||||
// log_info("RFCOMM_EVENT_CREDITS: 1");
|
||||
channel->packets_granted += 1;
|
||||
@ -1194,8 +1146,6 @@ static void rfcomm_hand_out_credits(void){
|
||||
static void rfcomm_channel_send_credits(rfcomm_channel_t *channel, uint8_t credits){
|
||||
rfcomm_send_uih_credits(channel->multiplexer, channel->dlci, credits);
|
||||
channel->credits_incoming += credits;
|
||||
|
||||
rfcomm_emit_credit_status(channel);
|
||||
}
|
||||
|
||||
static void rfcomm_channel_opened(rfcomm_channel_t *rfChannel){
|
||||
@ -1261,9 +1211,6 @@ static void rfcomm_channel_packet_handler_uih(rfcomm_multiplexer_t *multiplexer,
|
||||
if (!channel->incoming_flow_control && channel->credits_incoming < 5){
|
||||
channel->new_credits_incoming =RFCOMM_CREDITS;
|
||||
}
|
||||
|
||||
rfcomm_emit_credit_status(channel);
|
||||
|
||||
// we received new RFCOMM credits, hand them out if possible
|
||||
rfcomm_hand_out_credits();
|
||||
}
|
||||
@ -1547,7 +1494,8 @@ static int rfcomm_channel_ready_for_open(rfcomm_channel_t *channel){
|
||||
// log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u ", channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP|RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS, channel->state_var, channel->credits_outgoing, channel->multiplexer->l2cap_credits);
|
||||
// if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_MSC_RSP) == 0) return 0;
|
||||
// if (channel->credits_outgoing == 0) return 0;
|
||||
log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u, l2cap credits %u ", channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP, channel->state_var, channel->credits_outgoing, channel->multiplexer->l2cap_credits);
|
||||
log_info("rfcomm_channel_ready_for_open state %u, flags needed %04x, current %04x, rf credits %u",
|
||||
channel->state, RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP, channel->state_var, channel->credits_outgoing);
|
||||
if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_RCVD_MSC_RSP) == 0) return 0;
|
||||
if ((channel->state_var & RFCOMM_CHANNEL_STATE_VAR_SENT_CREDITS) == 0) return 0;
|
||||
|
||||
@ -1976,7 +1924,6 @@ int rfcomm_can_send_packet_now(uint16_t rfcomm_cid){
|
||||
return 1;
|
||||
}
|
||||
if (!channel->credits_outgoing) return 0;
|
||||
if (!channel->packets_granted) return 0;
|
||||
if ((channel->multiplexer->fcon & 1) == 0) return 0;
|
||||
|
||||
return l2cap_can_send_packet_now(channel->multiplexer->l2cap_cid);
|
||||
@ -1992,11 +1939,6 @@ static int rfcomm_assert_send_valid(rfcomm_channel_t * channel , uint16_t len){
|
||||
log_info("rfcomm_send_internal cid 0x%02x, no rfcomm outgoing credits!", channel->rfcomm_cid);
|
||||
return RFCOMM_NO_OUTGOING_CREDITS;
|
||||
}
|
||||
|
||||
if (!channel->packets_granted){
|
||||
log_info("rfcomm_send_internal cid 0x%02x, no rfcomm credits granted!", channel->rfcomm_cid);
|
||||
return RFCOMM_NO_OUTGOING_CREDITS;
|
||||
}
|
||||
|
||||
if ((channel->multiplexer->fcon & 1) == 0){
|
||||
log_info("rfcomm_send_internal cid 0x%02x, aggregate flow off!", channel->rfcomm_cid);
|
||||
|
@ -204,7 +204,6 @@ typedef struct {
|
||||
RFCOMM_MULTIPLEXER_STATE state;
|
||||
|
||||
uint16_t l2cap_cid;
|
||||
uint8_t l2cap_credits;
|
||||
|
||||
uint8_t fcon; // only send if fcon & 1, send rsp if fcon & 0x80
|
||||
|
||||
|
13
src/l2cap.c
13
src/l2cap.c
@ -239,7 +239,6 @@ static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){
|
||||
int l2cap_can_send_packet_now(uint16_t local_cid){
|
||||
l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid);
|
||||
if (!channel) return 0;
|
||||
if (!channel->packets_granted) return 0;
|
||||
return hci_can_send_acl_packet_now(channel->handle);
|
||||
}
|
||||
|
||||
@ -383,17 +382,14 @@ int l2cap_send_prepared(uint16_t local_cid, uint16_t len){
|
||||
return -1; // TODO: define error
|
||||
}
|
||||
|
||||
if (channel->packets_granted == 0){
|
||||
log_error("l2cap_send_prepared cid 0x%02x, no credits!", local_cid);
|
||||
return -1; // TODO: define error
|
||||
}
|
||||
|
||||
if (!hci_can_send_prepared_acl_packet_now(channel->handle)){
|
||||
log_info("l2cap_send_prepared cid 0x%02x, cannot send", local_cid);
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
--channel->packets_granted;
|
||||
if (channel->packets_granted){
|
||||
--channel->packets_granted;
|
||||
}
|
||||
|
||||
log_debug("l2cap_send_prepared cid 0x%02x, handle %u, 1 credit used, credits left %u;",
|
||||
local_cid, channel->handle, channel->packets_granted);
|
||||
@ -943,6 +939,9 @@ static void l2cap_event_handler(uint8_t *packet, uint16_t size){
|
||||
break;
|
||||
|
||||
case DAEMON_EVENT_HCI_PACKET_SENT:
|
||||
l2cap_run(); // try sending signaling packets first
|
||||
l2cap_hand_out_credits();
|
||||
|
||||
linked_list_iterator_init(&it, &l2cap_channels);
|
||||
while (linked_list_iterator_has_next(&it)){
|
||||
l2cap_channel_t * channel = (l2cap_channel_t *) linked_list_iterator_next(&it);
|
||||
|
@ -5,6 +5,8 @@ BTSTACK_ROOT = ../..
|
||||
POSIX_ROOT= ${BTSTACK_ROOT}/platform/posix
|
||||
CPPUTEST_HOME = ${BTSTACK_ROOT}/test/cpputest
|
||||
|
||||
include ${BTSTACK_ROOT}/example/embedded/Makefile.inc
|
||||
|
||||
COMMON = \
|
||||
btstack_memory.c \
|
||||
linked_list.c \
|
||||
|
89
test/hfp/dump_test_sequence_from_pklg.py
Executable file
89
test/hfp/dump_test_sequence_from_pklg.py
Executable file
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python
|
||||
# BlueKitchen GmbH (c) 2014
|
||||
|
||||
# primitive dump for PacketLogger format
|
||||
|
||||
# APPLE PacketLogger
|
||||
# typedef struct {
|
||||
# uint32_t len;
|
||||
# uint32_t ts_sec;
|
||||
# uint32_t ts_usec;
|
||||
# uint8_t type; // 0xfc for note
|
||||
# }
|
||||
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import datetime
|
||||
|
||||
packet_types = [ "CMD =>", "EVT <=", "ACL =>", "ACL <="]
|
||||
|
||||
def read_net_32(f):
|
||||
a = f.read(1)
|
||||
b = f.read(1)
|
||||
c = f.read(1)
|
||||
d = f.read(1)
|
||||
return ord(a) << 24 | ord(b) << 16 | ord(c) << 8 | ord(d)
|
||||
|
||||
def as_hex(data):
|
||||
str_list = []
|
||||
for byte in data:
|
||||
str_list.append("{0:02x} ".format(ord(byte)))
|
||||
return ''.join(str_list)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print 'Dump PacketLogger file'
|
||||
print 'Copyright 2014, BlueKitchen GmbH'
|
||||
print ''
|
||||
print 'Usage: ', sys.argv[0], 'hci_dump.pklg test_name'
|
||||
exit(0)
|
||||
|
||||
infile = sys.argv[1]
|
||||
test_name = sys.argv[2]
|
||||
separator = ""
|
||||
spaces = " "
|
||||
print "const char * "+test_name+"[] = {"
|
||||
|
||||
|
||||
with open (infile, 'rb') as fin:
|
||||
try:
|
||||
while True:
|
||||
len = read_net_32(fin)
|
||||
ts_sec = read_net_32(fin)
|
||||
ts_usec = read_net_32(fin)
|
||||
type = ord(fin.read(1))
|
||||
packet_len = len - 9;
|
||||
packet = fin.read(packet_len)
|
||||
time = "[%s.%03u]" % (datetime.datetime.fromtimestamp(ts_sec).strftime("%Y-%m-%d %H:%M:%S"), ts_usec / 1000)
|
||||
if type == 0xfc:
|
||||
packet = packet.replace("\n","\\n")
|
||||
packet = packet.replace("\r","\\r")
|
||||
packet = packet.replace("\"","\\\"")
|
||||
|
||||
parts = re.match('HFP_RX(.*)',packet)
|
||||
if not parts:
|
||||
parts = re.match('HFP_TX(.*)',packet)
|
||||
|
||||
cmd = 0
|
||||
if parts:
|
||||
hfp_cmds = parts.groups()[0].split('\\r\\n')
|
||||
for cmd in hfp_cmds:
|
||||
cmd = cmd.strip()
|
||||
if cmd <> "":
|
||||
cmd = cmd.replace("\\r","")
|
||||
print separator+spaces+"\""+cmd+"\"",
|
||||
separator = ",\n"
|
||||
|
||||
else:
|
||||
parts = re.match('USER:\'(.*)\'.*',packet)
|
||||
if parts:
|
||||
cmd = 'USER:'+parts.groups()[0]
|
||||
print separator+spaces+"\""+cmd+"\"",
|
||||
separator = ",\n"
|
||||
|
||||
|
||||
except TypeError:
|
||||
print "\n};\n"
|
||||
exit(0)
|
||||
|
||||
print "\n};\n"
|
@ -84,8 +84,18 @@ static hfp_ag_indicator_t ag_indicators[] = {
|
||||
{7, "callheld", 0, 2, 0, 1, 1, 0}
|
||||
};
|
||||
|
||||
static int supported_features_with_codec_negotiation = 1007; // 0011 1110 1111
|
||||
static int supported_features_without_codec_negotiation = 495; // 0001 1110 1111
|
||||
hfp_ag_indicator_t ag_indicators_temp[] = {
|
||||
// index, name, min range, max range, status, mandatory, enabled, status changed
|
||||
{1, "service", 0, 1, 1, 0, 0, 0},
|
||||
{2, "call", 0, 1, 0, 1, 1, 0},
|
||||
{3, "callsetup", 0, 3, 0, 1, 1, 0},
|
||||
{4, "battchg", 0, 5, 3, 0, 0, 0},
|
||||
{5, "signal", 0, 5, 5, 0, 0, 0},
|
||||
{6, "roam", 0, 1, 0, 0, 0, 0},
|
||||
{7, "callheld", 0, 2, 0, 1, 1, 0}
|
||||
};
|
||||
|
||||
static int supported_features_with_codec_negotiation = 4079; // 0011 1110 1111
|
||||
|
||||
static int call_hold_services_nr = 5;
|
||||
static const char* call_hold_services[] = {"1", "1x", "2", "2x", "3"};
|
||||
@ -104,41 +114,251 @@ static uint8_t start_ringing = 0;
|
||||
static uint8_t stop_ringing = 0;
|
||||
static uint8_t call_termiated = 0;
|
||||
|
||||
int expected_rfcomm_command(const char * expected_cmd){
|
||||
char * ag_cmd = (char *)get_rfcomm_payload();
|
||||
int ag_len = get_rfcomm_payload_len();
|
||||
int expected_len = strlen(expected_cmd);
|
||||
for (int i = 0; i < ag_len; i++){
|
||||
if ( (ag_cmd+i)[0] == '\r' || (ag_cmd+i)[0] == '\n' ) {
|
||||
continue;
|
||||
}
|
||||
if (strncmp(ag_cmd + i, expected_cmd, expected_len) == 0) return 1;
|
||||
}
|
||||
return 0;
|
||||
static uint16_t handle = -1;
|
||||
static int memory_1_enabled = 1;
|
||||
static int last_number_exists = 1;
|
||||
|
||||
int has_more_hfp_ag_commands(){
|
||||
return has_more_hfp_commands(2,2);
|
||||
}
|
||||
|
||||
char * get_next_hfp_ag_command(){
|
||||
return get_next_hfp_command(2,2);
|
||||
}
|
||||
|
||||
void simulate_test_sequence(char ** test_steps, int nr_test_steps){
|
||||
int i = 0;
|
||||
for (i=0; i < nr_test_steps; i++){
|
||||
char * cmd = test_steps[i];
|
||||
printf("\n---> NEXT STEP %s\n", cmd);
|
||||
if (strncmp(cmd, "AT", 2) == 0){
|
||||
inject_rfcomm_command_to_ag((uint8_t*)cmd, strlen(cmd));
|
||||
} else if (strncmp(cmd, "NOP", 3) == 0){
|
||||
inject_rfcomm_command_to_ag((uint8_t*)"NOP",3);
|
||||
} else {
|
||||
int expected_cmd = expected_rfcomm_command(cmd);
|
||||
if (!expected_cmd){
|
||||
printf("\nError: Expected:'%s', but got:'%s'\n", cmd, (char *)get_rfcomm_payload());
|
||||
CHECK_EQUAL(expected_cmd,1);
|
||||
return;
|
||||
}
|
||||
printf("AG response verified %s\n\n", cmd);
|
||||
}
|
||||
static void user_command(char cmd){
|
||||
switch (cmd){
|
||||
case 'a':
|
||||
printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_ag_establish_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'A':
|
||||
printf("Release HFP service level connection.\n");
|
||||
hfp_ag_release_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'b':
|
||||
printf("Establish Audio connection %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_ag_establish_audio_connection(device_addr);
|
||||
break;
|
||||
case 'B':
|
||||
printf("Release Audio connection.\n");
|
||||
hfp_ag_release_audio_connection(device_addr);
|
||||
break;
|
||||
case 'c':
|
||||
printf("Simulate incoming call from 1234567\n");
|
||||
// current_call_exists_a = 1;
|
||||
// current_call_status_a = HFP_ENHANCED_CALL_STATUS_INCOMING;
|
||||
// current_call_dir = HFP_ENHANCED_CALL_DIR_INCOMING;
|
||||
hfp_ag_set_clip(129, "1234567");
|
||||
hfp_ag_incoming_call();
|
||||
break;
|
||||
case 'm':
|
||||
printf("Simulate incoming call from 7654321\n");
|
||||
// current_call_exists_b = 1;
|
||||
// current_call_status_b = HFP_ENHANCED_CALL_STATUS_INCOMING;
|
||||
// current_call_dir = HFP_ENHANCED_CALL_DIR_INCOMING;
|
||||
hfp_ag_set_clip(129, "7654321");
|
||||
hfp_ag_incoming_call();
|
||||
break;
|
||||
case 'C':
|
||||
printf("Simulate terminate call\n");
|
||||
hfp_ag_call_dropped();
|
||||
break;
|
||||
case 'd':
|
||||
printf("Report AG failure\n");
|
||||
hfp_ag_report_extended_audio_gateway_error_result_code(device_addr, HFP_CME_ERROR_AG_FAILURE);
|
||||
break;
|
||||
case 'e':
|
||||
printf("Answer call on AG\n");
|
||||
// if (current_call_status_a == HFP_ENHANCED_CALL_STATUS_INCOMING){
|
||||
// current_call_status_a = HFP_ENHANCED_CALL_STATUS_ACTIVE;
|
||||
// }
|
||||
// if (current_call_status_b == HFP_ENHANCED_CALL_STATUS_INCOMING){
|
||||
// current_call_status_b = HFP_ENHANCED_CALL_STATUS_ACTIVE;
|
||||
// }
|
||||
hfp_ag_answer_incoming_call();
|
||||
break;
|
||||
case 'E':
|
||||
printf("Reject call on AG\n");
|
||||
hfp_ag_terminate_call();
|
||||
break;
|
||||
case 'f':
|
||||
printf("Disable cellular network\n");
|
||||
hfp_ag_set_registration_status(0);
|
||||
break;
|
||||
case 'F':
|
||||
printf("Enable cellular network\n");
|
||||
hfp_ag_set_registration_status(1);
|
||||
break;
|
||||
case 'g':
|
||||
printf("Set signal strength to 0\n");
|
||||
hfp_ag_set_signal_strength(0);
|
||||
break;
|
||||
case 'G':
|
||||
printf("Set signal strength to 5\n");
|
||||
hfp_ag_set_signal_strength(5);
|
||||
break;
|
||||
case 'h':
|
||||
printf("Disable roaming\n");
|
||||
hfp_ag_set_roaming_status(0);
|
||||
break;
|
||||
case 'H':
|
||||
printf("Enable roaming\n");
|
||||
hfp_ag_set_roaming_status(1);
|
||||
break;
|
||||
case 'i':
|
||||
printf("Set battery level to 3\n");
|
||||
hfp_ag_set_battery_level(3);
|
||||
break;
|
||||
case 'I':
|
||||
printf("Set battery level to 5\n");
|
||||
hfp_ag_set_battery_level(5);
|
||||
break;
|
||||
case 'j':
|
||||
printf("Answering call on remote side\n");
|
||||
hfp_ag_outgoing_call_established();
|
||||
break;
|
||||
case 'r':
|
||||
printf("Disable in-band ring tone\n");
|
||||
hfp_ag_set_use_in_band_ring_tone(0);
|
||||
break;
|
||||
case 'k':
|
||||
printf("Memory 1 cleared\n");
|
||||
memory_1_enabled = 0;
|
||||
break;
|
||||
case 'K':
|
||||
printf("Memory 1 set\n");
|
||||
memory_1_enabled = 1;
|
||||
break;
|
||||
case 'l':
|
||||
printf("Last dialed number cleared\n");
|
||||
last_number_exists = 0;
|
||||
break;
|
||||
case 'L':
|
||||
printf("Last dialed number set\n");
|
||||
last_number_exists = 1;
|
||||
break;
|
||||
case 'n':
|
||||
printf("Disable Voice Recognition\n");
|
||||
hfp_ag_activate_voice_recognition(device_addr, 0);
|
||||
break;
|
||||
case 'N':
|
||||
printf("Enable Voice Recognition\n");
|
||||
hfp_ag_activate_voice_recognition(device_addr, 1);
|
||||
break;
|
||||
case 'o':
|
||||
printf("Set speaker gain to 0 (minimum)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 0);
|
||||
break;
|
||||
case 'O':
|
||||
printf("Set speaker gain to 9 (default)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 9);
|
||||
break;
|
||||
case 'p':
|
||||
printf("Set speaker gain to 12 (higher)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 12);
|
||||
break;
|
||||
case 'P':
|
||||
printf("Set speaker gain to 15 (maximum)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 15);
|
||||
break;
|
||||
case 'q':
|
||||
printf("Set microphone gain to 0\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 0);
|
||||
break;
|
||||
case 'Q':
|
||||
printf("Set microphone gain to 9\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 9);
|
||||
break;
|
||||
case 's':
|
||||
printf("Set microphone gain to 12\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 12);
|
||||
break;
|
||||
case 'S':
|
||||
printf("Set microphone gain to 15\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 15);
|
||||
break;
|
||||
case 'R':
|
||||
printf("Enable in-band ring tone\n");
|
||||
hfp_ag_set_use_in_band_ring_tone(1);
|
||||
break;
|
||||
case 't':
|
||||
printf("Terminate HCI connection.\n");
|
||||
gap_disconnect(handle);
|
||||
break;
|
||||
case 'u':
|
||||
printf("Join held call\n");
|
||||
// current_call_mpty = HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL;
|
||||
hfp_ag_join_held_call();
|
||||
break;
|
||||
case 'v':
|
||||
// start_scan();
|
||||
break;
|
||||
case 'w':
|
||||
printf("AG: Put incoming call on hold (Response and Hold)\n");
|
||||
hfp_ag_hold_incoming_call();
|
||||
break;
|
||||
case 'x':
|
||||
printf("AG: Accept held incoming call (Response and Hold)\n");
|
||||
hfp_ag_accept_held_incoming_call();
|
||||
break;
|
||||
case 'X':
|
||||
printf("AG: Reject held incoming call (Response and Hold)\n");
|
||||
hfp_ag_reject_held_incoming_call();
|
||||
break;
|
||||
default:
|
||||
printf("AG: undefined user command\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void simulate_test_sequence(hfp_test_item_t * test_item){
|
||||
char ** test_steps = test_item->test;
|
||||
printf("\nSimulate test sequence: \"%s\"\n", test_item->name);
|
||||
|
||||
int i = 0;
|
||||
static char * previous_cmd = NULL;
|
||||
|
||||
while (i < test_item->len){
|
||||
char * expected_cmd = test_steps[i];
|
||||
int expected_cmd_len = strlen(expected_cmd);
|
||||
|
||||
if (strncmp(expected_cmd, "USER:", 5) == 0){
|
||||
printf("\n---> USER: ");
|
||||
user_command(expected_cmd[5]);
|
||||
i++;
|
||||
} else if (strncmp(expected_cmd, "AT", 2) == 0){
|
||||
// printf("\n---> NEXT STEP receive from HF: '%s'\n", expected_cmd);
|
||||
inject_hfp_command_to_ag((uint8_t*)expected_cmd, expected_cmd_len);
|
||||
i++;
|
||||
|
||||
} else {
|
||||
printf("\n---> NEXT STEP expect from AG: %s\n", expected_cmd);
|
||||
|
||||
while (has_more_hfp_ag_commands()){
|
||||
char * ag_cmd = get_next_hfp_ag_command();
|
||||
|
||||
int equal_cmds = strncmp(ag_cmd, expected_cmd, expected_cmd_len) == 0;
|
||||
if (!equal_cmds){
|
||||
printf("\nError: Expected:'%s', but got:'%s'\n", expected_cmd, ag_cmd);
|
||||
CHECK_EQUAL(equal_cmds,1);
|
||||
return;
|
||||
}
|
||||
printf("Verified: '%s'\n", expected_cmd);
|
||||
previous_cmd = ag_cmd;
|
||||
|
||||
i++;
|
||||
if (i < test_item->len){
|
||||
expected_cmd = test_steps[i];
|
||||
expected_cmd_len = strlen(expected_cmd);
|
||||
}
|
||||
}
|
||||
// printf("\n---> NEXT STEP trigger once more AG\n");
|
||||
inject_hfp_command_to_ag((uint8_t*)"NOP",3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void packet_handler(uint8_t * event, uint16_t event_size){
|
||||
if (event[0] != HCI_EVENT_HFP_META) return;
|
||||
if (event[3] && event[2] != HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR){
|
||||
@ -181,8 +401,24 @@ void packet_handler(uint8_t * event, uint16_t event_size){
|
||||
case HFP_SUBEVENT_CALL_TERMINATED:
|
||||
call_termiated = 1;
|
||||
break;
|
||||
case HFP_CMD_CALL_ANSWERED:
|
||||
//printf("HF answers call, accept call by GSM\n");
|
||||
break;
|
||||
case HFP_SUBEVENT_REDIAL_LAST_NUMBER:
|
||||
printf("\n** Redial last number\n");
|
||||
if (last_number_exists){
|
||||
hfp_ag_outgoing_call_accepted();
|
||||
printf("Last number exists: accept call\n");
|
||||
// TODO: calling ringing right away leads to callstatus=2 being skipped. don't call for now
|
||||
// hfp_ag_outgoing_call_ringing();
|
||||
} else {
|
||||
printf("Last number missing: reject call\n");
|
||||
hfp_ag_outgoing_call_rejected();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("event not handled %u\n", event[2]);
|
||||
printf("hfp_ag_client_test: event not handled %u\n", event[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -212,121 +448,48 @@ TEST_GROUP(HFPClient){
|
||||
codecs_connection_established = 0;
|
||||
audio_connection_established = 0;
|
||||
}
|
||||
|
||||
void setup_hfp_service_level_connection(char ** test_steps, int nr_test_steps){
|
||||
service_level_connection_established = 0;
|
||||
hfp_ag_establish_service_level_connection(device_addr);
|
||||
simulate_test_sequence((char **) test_steps, nr_test_steps);
|
||||
}
|
||||
|
||||
void setup_hfp_codecs_connection(char ** test_steps, int nr_test_steps){
|
||||
codecs_connection_established = 0;
|
||||
simulate_test_sequence((char **) test_steps, nr_test_steps);
|
||||
}
|
||||
};
|
||||
|
||||
// TEST(HFPClient, HFAnswerIncomingCallWithInBandRingToneHFTermiantesCall){
|
||||
// setup_hfp_service_level_connection(default_slc_setup(), default_slc_setup_size());
|
||||
// CHECK_EQUAL(service_level_connection_established, 1);
|
||||
|
||||
// hfp_ag_set_use_in_band_ring_tone(1);
|
||||
// hfp_ag_incoming_call();
|
||||
// simulate_test_sequence(default_ic_setup(), default_ic_setup_size());
|
||||
// CHECK_EQUAL(audio_connection_established, 1);
|
||||
|
||||
// simulate_test_sequence(alert_ic_setup(), alert_ic_setup_size());
|
||||
// CHECK_EQUAL(stop_ringing, 1);
|
||||
|
||||
// simulate_test_sequence(terminate_ic_hf_setup(), terminate_ic_hf_setup_size());
|
||||
// CHECK_EQUAL(call_termiated,1);
|
||||
// TEST(HFPClient, PTSRHHTests){
|
||||
// for (int i = 0; i < hfp_pts_ag_rhh_tests_size(); i++){
|
||||
// simulate_test_sequence(&hfp_pts_ag_rhh_tests()[i]);
|
||||
// teardown();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// TEST(HFPClient, HFAnswerIncomingCallWithInBandRingToneAGTerminatesCall){
|
||||
// setup_hfp_service_level_connection(default_slc_setup(), default_slc_setup_size());
|
||||
// CHECK_EQUAL(service_level_connection_established, 1);
|
||||
|
||||
// hfp_ag_set_use_in_band_ring_tone(1);
|
||||
// hfp_ag_incoming_call();
|
||||
// simulate_test_sequence(default_ic_setup(), default_ic_setup_size());
|
||||
// CHECK_EQUAL(audio_connection_established, 1);
|
||||
|
||||
// simulate_test_sequence(alert_ic_setup(), alert_ic_setup_size());
|
||||
// CHECK_EQUAL(stop_ringing, 1);
|
||||
|
||||
// // AG terminates call
|
||||
// hfp_ag_terminate_call();
|
||||
// simulate_test_sequence(terminate_ic_ag_setup(), terminate_ic_ag_setup_size());
|
||||
// CHECK_EQUAL(call_termiated,1);
|
||||
// TEST(HFPClient, PTSECCTests){
|
||||
// for (int i = 0; i < hfp_pts_ag_ecc_tests_size(); i++){
|
||||
// simulate_test_sequence(&hfp_pts_ag_ecc_tests()[i]);
|
||||
// teardown();
|
||||
// }
|
||||
// }
|
||||
|
||||
// TEST(HFPClient, PTSECSTests){
|
||||
// for (int i = 0; i < hfp_pts_ag_ecs_tests_size(); i++){
|
||||
// simulate_test_sequence(&hfp_pts_ag_ecs_tests()[i]);
|
||||
// teardown();
|
||||
// }
|
||||
// }
|
||||
|
||||
TEST(HFPClient, HFAudioConnectionEstablishedWithCodecNegotiation){
|
||||
setup_hfp_service_level_connection(default_slc_setup(), default_slc_setup_size());
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
|
||||
setup_hfp_codecs_connection(default_cc_setup(), default_cc_setup_size());
|
||||
CHECK_EQUAL(codecs_connection_established, 1);
|
||||
|
||||
hfp_ag_establish_audio_connection(device_addr);
|
||||
CHECK_EQUAL(audio_connection_established, 1);
|
||||
|
||||
hfp_ag_release_audio_connection(device_addr);
|
||||
CHECK_EQUAL(audio_connection_established, 0);
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFAudioConnectionEstablishedWithoutCodecNegotiation){
|
||||
hfp_ag_init(rfcomm_channel_nr, supported_features_without_codec_negotiation,
|
||||
codecs, sizeof(codecs),
|
||||
ag_indicators, ag_indicators_nr,
|
||||
hf_indicators, hf_indicators_nr,
|
||||
call_hold_services, call_hold_services_nr);
|
||||
|
||||
setup_hfp_service_level_connection(hfp_slc_tests()[1].test, hfp_slc_tests()[1].len);
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
|
||||
setup_hfp_codecs_connection(default_cc_setup(), default_cc_setup_size());
|
||||
CHECK_EQUAL(codecs_connection_established, 1);
|
||||
|
||||
hfp_ag_establish_audio_connection(device_addr);
|
||||
CHECK_EQUAL(audio_connection_established, 1);
|
||||
|
||||
hfp_ag_release_audio_connection(device_addr);
|
||||
CHECK_EQUAL(audio_connection_established, 0);
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFCodecsConnectionEstablished){
|
||||
for (int i = 0; i < cc_tests_size(); i++){
|
||||
setup_hfp_service_level_connection(default_slc_setup(), default_slc_setup_size());
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
|
||||
setup_hfp_codecs_connection(hfp_cc_tests()[i].test, hfp_cc_tests()[i].len);
|
||||
CHECK_EQUAL(codecs_connection_established, 1);
|
||||
TEST(HFPClient, PTSTWCTests){
|
||||
for (int i = 0; i < hfp_pts_ag_twc_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_ag_twc_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFServiceLevelConnectionCommands){
|
||||
setup_hfp_service_level_connection(default_slc_setup(), default_slc_setup_size());
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
for (int i = 0; i < slc_cmds_tests_size(); i++){
|
||||
simulate_test_sequence(hfp_slc_cmds_tests()[i].test, hfp_slc_cmds_tests()[i].len);
|
||||
TEST(HFPClient, PTSATATests){
|
||||
for (int i = 0; i < hfp_pts_ag_ata_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_ag_ata_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFServiceLevelConnectionEstablishedWithoutCodecNegotiation){
|
||||
hfp_ag_init(rfcomm_channel_nr, supported_features_without_codec_negotiation,
|
||||
codecs, sizeof(codecs),
|
||||
ag_indicators, ag_indicators_nr,
|
||||
hf_indicators, hf_indicators_nr,
|
||||
call_hold_services, call_hold_services_nr);
|
||||
setup_hfp_service_level_connection(hfp_slc_tests()[1].test, hfp_slc_tests()[1].len);
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFServiceLevelConnectionEstablishedWithCodecNegotiation){
|
||||
setup_hfp_service_level_connection(hfp_slc_tests()[0].test, hfp_slc_tests()[0].len);
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
TEST(HFPClient, PTSSLCTests){
|
||||
for (int i = 0; i < hfp_pts_ag_slc_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_ag_slc_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[]){
|
||||
|
@ -71,7 +71,6 @@ const uint8_t rfcomm_channel_nr = 1;
|
||||
static bd_addr_t device_addr = {0xD8,0xBb,0x2C,0xDf,0xF1,0x08};
|
||||
|
||||
static uint8_t codecs[2] = {1,2};
|
||||
static uint8_t default_codecs[2] = {1};
|
||||
static uint16_t indicators[1] = {0x01};
|
||||
|
||||
static uint8_t service_level_connection_established = 0;
|
||||
@ -81,72 +80,321 @@ static uint8_t start_ringing = 0;
|
||||
static uint8_t stop_ringing = 0;
|
||||
static uint8_t call_termiated = 0;
|
||||
|
||||
static int supported_features_with_codec_negotiation = 438; // 0001 1011 0110
|
||||
static int supported_features_without_codec_negotiation = 310; // 0001 0011 0110
|
||||
static int supported_features_with_codec_negotiation = 438;
|
||||
|
||||
int expected_rfcomm_command(const char * cmd){
|
||||
char * ag_cmd = (char *)get_rfcomm_payload();
|
||||
int offset = 2;
|
||||
int cmd_size = strlen(cmd);
|
||||
static uint16_t handle = -1;
|
||||
|
||||
int cmd_found = strncmp(ag_cmd+offset, cmd, cmd_size) == 0;
|
||||
while (!cmd_found && get_rfcomm_payload_len() - cmd_size >= offset){
|
||||
offset++;
|
||||
cmd_found = strncmp(ag_cmd+offset, cmd, cmd_size) == 0;
|
||||
}
|
||||
if (!cmd_found) return 0;
|
||||
|
||||
// AG cmds that are not followed by OK
|
||||
if (strncmp(ag_cmd+offset, "+BCS", 4) == 0){
|
||||
return cmd_found;
|
||||
}
|
||||
|
||||
offset += strlen(cmd)+4;
|
||||
// printf("cmd found, offset %d, cmd %s\n", offset, ag_cmd+offset);
|
||||
int ok_found = strncmp(ag_cmd+offset, "OK", 2) == 0;
|
||||
while (!ok_found && get_rfcomm_payload_len() - 2 >= offset){
|
||||
offset++;
|
||||
// printf("cmd found, offset %d, cmd %s\n", offset, ag_cmd+offset);
|
||||
ok_found = strncmp(ag_cmd+offset, "OK", 2) == 0;
|
||||
}
|
||||
// printf("cmd found, ok found %d\n", ok_found);
|
||||
return cmd_found && ok_found;
|
||||
char * get_next_hfp_hf_command(){
|
||||
return get_next_hfp_command(0,2);
|
||||
}
|
||||
|
||||
void simulate_test_sequence(char ** test_steps, int nr_test_steps){
|
||||
int has_more_hfp_hf_commands(){
|
||||
return has_more_hfp_commands(0,2);
|
||||
}
|
||||
|
||||
static void user_command(char cmd){
|
||||
switch (cmd){
|
||||
case '#':
|
||||
case '-':
|
||||
case '+':
|
||||
case '*':
|
||||
printf("DTMF Code: %c\n", cmd);
|
||||
hfp_hf_send_dtmf_code(device_addr, cmd);
|
||||
break;
|
||||
case 'a':
|
||||
printf("Establish Service level connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_establish_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'A':
|
||||
printf("Release Service level connection.\n");
|
||||
hfp_hf_release_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'b':
|
||||
printf("Establish Audio connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_establish_audio_connection(device_addr);
|
||||
break;
|
||||
case 'B':
|
||||
printf("Release Audio service level connection.\n");
|
||||
hfp_hf_release_audio_connection(device_addr);
|
||||
break;
|
||||
case 'C':
|
||||
printf("Enable registration status update for all AG indicators.\n");
|
||||
hfp_hf_enable_status_update_for_all_ag_indicators(device_addr);
|
||||
case 'c':
|
||||
printf("Disable registration status update for all AG indicators.\n");
|
||||
hfp_hf_disable_status_update_for_all_ag_indicators(device_addr);
|
||||
break;
|
||||
case 'D':
|
||||
printf("Set HFP AG registration status update for individual indicators (0111111).\n");
|
||||
hfp_hf_set_status_update_for_individual_ag_indicators(device_addr, 63);
|
||||
break;
|
||||
case 'd':
|
||||
printf("Query network operator.\n");
|
||||
hfp_hf_query_operator_selection(device_addr);
|
||||
break;
|
||||
case 'E':
|
||||
printf("Enable reporting of the extended AG error result code.\n");
|
||||
hfp_hf_enable_report_extended_audio_gateway_error_result_code(device_addr);
|
||||
break;
|
||||
case 'e':
|
||||
printf("Disable reporting of the extended AG error result code.\n");
|
||||
hfp_hf_disable_report_extended_audio_gateway_error_result_code(device_addr);
|
||||
break;
|
||||
case 'f':
|
||||
printf("Answer incoming call.\n");
|
||||
hfp_hf_answer_incoming_call(device_addr);
|
||||
break;
|
||||
case 'F':
|
||||
printf("Hangup call.\n");
|
||||
hfp_hf_terminate_call(device_addr);
|
||||
break;
|
||||
case 'G':
|
||||
printf("Reject call.\n");
|
||||
hfp_hf_reject_call(device_addr);
|
||||
break;
|
||||
case 'g':
|
||||
printf("Query operator.\n");
|
||||
hfp_hf_query_operator_selection(device_addr);
|
||||
break;
|
||||
case 't':
|
||||
printf("Terminate HCI connection.\n");
|
||||
gap_disconnect(handle);
|
||||
break;
|
||||
case 'i':
|
||||
printf("Dial 1234567\n");
|
||||
hfp_hf_dial_number(device_addr, (char *)"1234567");
|
||||
break;
|
||||
case 'I':
|
||||
printf("Dial 7654321\n");
|
||||
hfp_hf_dial_number(device_addr, (char *)"7654321");
|
||||
break;
|
||||
case 'j':
|
||||
printf("Dial #1\n");
|
||||
hfp_hf_dial_memory(device_addr, (char *)"1");
|
||||
break;
|
||||
case 'J':
|
||||
printf("Dial #99\n");
|
||||
hfp_hf_dial_memory(device_addr, (char *)"99");
|
||||
break;
|
||||
case 'k':
|
||||
printf("Deactivate call waiting notification\n");
|
||||
hfp_hf_deactivate_call_waiting_notification(device_addr);
|
||||
break;
|
||||
case 'K':
|
||||
printf("Activate call waiting notification\n");
|
||||
hfp_hf_activate_call_waiting_notification(device_addr);
|
||||
break;
|
||||
case 'l':
|
||||
printf("Deactivate calling line notification\n");
|
||||
hfp_hf_deactivate_calling_line_notification(device_addr);
|
||||
break;
|
||||
case 'L':
|
||||
printf("Activate calling line notification\n");
|
||||
hfp_hf_activate_calling_line_notification(device_addr);
|
||||
break;
|
||||
case 'm':
|
||||
printf("Deactivate echo canceling and noise reduction\n");
|
||||
hfp_hf_deactivate_echo_canceling_and_noise_reduction(device_addr);
|
||||
break;
|
||||
case 'M':
|
||||
printf("Activate echo canceling and noise reduction\n");
|
||||
hfp_hf_activate_echo_canceling_and_noise_reduction(device_addr);
|
||||
break;
|
||||
case 'n':
|
||||
printf("Deactivate voice recognition\n");
|
||||
hfp_hf_deactivate_voice_recognition_notification(device_addr);
|
||||
break;
|
||||
case 'N':
|
||||
printf("Activate voice recognition\n");
|
||||
hfp_hf_activate_voice_recognition_notification(device_addr);
|
||||
break;
|
||||
case 'o':
|
||||
printf("Set speaker gain to 0 (minimum)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 0);
|
||||
break;
|
||||
case 'O':
|
||||
printf("Set speaker gain to 9 (default)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 9);
|
||||
break;
|
||||
case 'p':
|
||||
printf("Set speaker gain to 12 (higher)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 12);
|
||||
break;
|
||||
case 'P':
|
||||
printf("Set speaker gain to 15 (maximum)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 15);
|
||||
break;
|
||||
case 'q':
|
||||
printf("Set microphone gain to 0\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 0);
|
||||
break;
|
||||
case 'Q':
|
||||
printf("Set microphone gain to 9\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 9);
|
||||
break;
|
||||
case 's':
|
||||
printf("Set microphone gain to 12\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 12);
|
||||
break;
|
||||
case 'S':
|
||||
printf("Set microphone gain to 15\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 15);
|
||||
break;
|
||||
case 'u':
|
||||
printf("Send 'user busy' (Three-Way Call 0)\n");
|
||||
hfp_hf_user_busy(device_addr);
|
||||
break;
|
||||
case 'U':
|
||||
printf("End active call and accept waiting/held call (Three-Way Call 1)\n");
|
||||
hfp_hf_end_active_and_accept_other(device_addr);
|
||||
break;
|
||||
case 'v':
|
||||
printf("Swap active call and hold/waiting call (Three-Way Call 2)\n");
|
||||
hfp_hf_swap_calls(device_addr);
|
||||
break;
|
||||
case 'V':
|
||||
printf("Join hold call (Three-Way Call 3)\n");
|
||||
hfp_hf_join_held_call(device_addr);
|
||||
break;
|
||||
case 'w':
|
||||
printf("Connect calls (Three-Way Call 4)\n");
|
||||
hfp_hf_connect_calls(device_addr);
|
||||
break;
|
||||
case 'W':
|
||||
printf("Redial\n");
|
||||
hfp_hf_redial_last_number(device_addr);
|
||||
break;
|
||||
case 'x':
|
||||
printf("Request phone number for voice tag\n");
|
||||
hfp_hf_request_phone_number_for_voice_tag(device_addr);
|
||||
break;
|
||||
case 'X':
|
||||
printf("Query current call status\n");
|
||||
hfp_hf_query_current_call_status(device_addr);
|
||||
break;
|
||||
case 'y':
|
||||
printf("Release call with index 2\n");
|
||||
hfp_hf_release_call_with_index(device_addr, 2);
|
||||
break;
|
||||
case 'Y':
|
||||
printf("Private consulation with call 2\n");
|
||||
hfp_hf_private_consultation_with_call(device_addr, 2);
|
||||
break;
|
||||
case '[':
|
||||
printf("Query Response and Hold status (RHH ?)\n");
|
||||
hfp_hf_rrh_query_status(device_addr);
|
||||
break;
|
||||
case ']':
|
||||
printf("Place call in a response and held state (RHH 0)\n");
|
||||
hfp_hf_rrh_hold_call(device_addr);
|
||||
break;
|
||||
case '{':
|
||||
printf("Accept held call (RHH 1)\n");
|
||||
hfp_hf_rrh_accept_held_call(device_addr);
|
||||
break;
|
||||
case '}':
|
||||
printf("Reject held call (RHH 2)\n");
|
||||
hfp_hf_rrh_reject_held_call(device_addr);
|
||||
break;
|
||||
case '?':
|
||||
printf("Query Subscriber Number\n");
|
||||
hfp_hf_query_subscriber_number(device_addr);
|
||||
break;
|
||||
case '!':
|
||||
printf("Update HF indicator with assigned number 1 (HFI)\n");
|
||||
hfp_hf_set_hf_indicator(device_addr, 1, 1);
|
||||
break;
|
||||
default:
|
||||
printf("HF: undefined user command\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void simulate_test_sequence(hfp_test_item_t * test_item){
|
||||
char ** test_steps = test_item->test;
|
||||
printf("\nSimulate test sequence: \"%s\"\n", test_item->name);
|
||||
|
||||
int i = 0;
|
||||
for (i=0; i < nr_test_steps; i++){
|
||||
char * cmd = test_steps[i];
|
||||
printf("\n---> NEXT STEP %s\n", cmd);
|
||||
if (strncmp(cmd, "AT", 2) == 0){
|
||||
while ( i < test_item->len){
|
||||
char * expected_cmd = test_steps[i];
|
||||
int expected_cmd_len = strlen(expected_cmd);
|
||||
|
||||
if (strncmp(expected_cmd, "USER:", 5) == 0){
|
||||
user_command(expected_cmd[5]);
|
||||
while (has_more_hfp_hf_commands()){
|
||||
// empty rfcomm payload buffer
|
||||
get_next_hfp_hf_command();
|
||||
}
|
||||
i++;
|
||||
|
||||
} else if (strncmp(expected_cmd, "AT+BAC=", 7) == 0){
|
||||
int parsed_codecs[2];
|
||||
uint8_t new_codecs[2];
|
||||
if (strncmp(cmd, "AT+BAC=", 7) == 0){
|
||||
printf("Send BAC\n");
|
||||
sscanf(&cmd[7],"%d,%d", &parsed_codecs[0], &parsed_codecs[1]);
|
||||
new_codecs[0] = parsed_codecs[0];
|
||||
new_codecs[1] = parsed_codecs[1];
|
||||
hfp_hf_set_codecs((uint8_t*)new_codecs, 2);
|
||||
} else {
|
||||
printf("Verify\n");
|
||||
int expected_cmd = expected_rfcomm_command(cmd);
|
||||
if (expected_cmd){
|
||||
printf("\nError: Expected:'%s', but got:'%s'", cmd, (char *)get_rfcomm_payload());
|
||||
return;
|
||||
}
|
||||
sscanf(&expected_cmd[7],"%d,%d", &parsed_codecs[0], &parsed_codecs[1]);
|
||||
new_codecs[0] = parsed_codecs[0];
|
||||
new_codecs[1] = parsed_codecs[1];
|
||||
hfp_hf_set_codecs((uint8_t*)new_codecs, 2);
|
||||
while (has_more_hfp_hf_commands()){
|
||||
// empty rfcomm payload buffer
|
||||
get_next_hfp_hf_command();
|
||||
}
|
||||
i++;
|
||||
} else if (strncmp(expected_cmd, "AT+BRSF=", 8) == 0 ){
|
||||
int supported_features = 0;
|
||||
sscanf(&expected_cmd[8],"%d", &supported_features);
|
||||
printf("Call hfp_hf_init with SF %d\n", supported_features);
|
||||
hfp_hf_init(rfcomm_channel_nr, supported_features, indicators, sizeof(indicators)/sizeof(uint16_t), 1);
|
||||
user_command('a');
|
||||
while (has_more_hfp_hf_commands()){
|
||||
// empty rfcomm payload buffer
|
||||
get_next_hfp_hf_command();
|
||||
}
|
||||
i++;
|
||||
} else if (strncmp(expected_cmd, "AT+BCC", 6) == 0){
|
||||
user_command('b');
|
||||
while (has_more_hfp_hf_commands()){
|
||||
// empty rfcomm payload buffer
|
||||
get_next_hfp_hf_command();
|
||||
}
|
||||
i++;
|
||||
} else if (strncmp(expected_cmd, "AT", 2) == 0){
|
||||
printf("\n---> NEXT STEP expect from HF: %s\n", expected_cmd);
|
||||
while (has_more_hfp_hf_commands()){
|
||||
char * ag_cmd = get_next_hfp_hf_command();
|
||||
//printf("HF response verify %s == %s[%d]\n", expected_cmd, ag_cmd, expected_cmd_len);
|
||||
|
||||
int equal_cmds = strncmp(ag_cmd, expected_cmd, expected_cmd_len) == 0;
|
||||
if (!equal_cmds){
|
||||
printf("\nError: Expected:'%s', but got:'%s'\n", expected_cmd, ag_cmd);
|
||||
CHECK_EQUAL(equal_cmds,1);
|
||||
return;
|
||||
}
|
||||
printf("Verified: '%s'\n", expected_cmd);
|
||||
i++;
|
||||
if (i < test_item->len){
|
||||
expected_cmd = test_steps[i];
|
||||
expected_cmd_len = strlen(expected_cmd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inject_rfcomm_command_to_hf((uint8_t*)cmd, strlen(cmd));
|
||||
//printf("\n---> NEXT STEP receive from AG: '%s'\n", expected_cmd);
|
||||
inject_hfp_command_to_hf((uint8_t*)expected_cmd, strlen(expected_cmd));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void packet_handler(uint8_t * event, uint16_t event_size){
|
||||
if (event[0] != HCI_EVENT_HFP_META) return;
|
||||
if (event[3] && event[2] != HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR){
|
||||
if (event[3]
|
||||
&& event[2] != HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR
|
||||
&& event[2] != HFP_SUBEVENT_NUMBER_FOR_VOICE_TAG
|
||||
&& event[2] != HFP_SUBEVENT_SPEAKER_VOLUME
|
||||
&& event[2] != HFP_SUBEVENT_MICROPHONE_VOLUME){
|
||||
printf("ERROR, status: %u\n", event[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event[2]) {
|
||||
case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
|
||||
printf("\n** SLC established **\n\n");
|
||||
@ -183,6 +431,31 @@ void packet_handler(uint8_t * event, uint16_t event_size){
|
||||
case HFP_SUBEVENT_CALL_TERMINATED:
|
||||
call_termiated = 1;
|
||||
break;
|
||||
case HFP_SUBEVENT_COMPLETE:
|
||||
printf("HFP AG HFP_SUBEVENT_COMPLETE.\n");
|
||||
break;
|
||||
case HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED:
|
||||
printf("AG_INDICATOR_STATUS_CHANGED, AG indicator '%s' (index: %d) to: %d\n", (const char*) &event[6], event[4], event[5]);
|
||||
break;
|
||||
case HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED:
|
||||
printf("NETWORK_OPERATOR_CHANGED, operator mode: %d, format: %d, name: %s\n", event[4], event[5], (char *) &event[6]);
|
||||
break;
|
||||
case HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR:
|
||||
if (event[4])
|
||||
printf("EXTENDED_AUDIO_GATEWAY_ERROR_REPORT, status : %d\n", event[3]);
|
||||
break;
|
||||
case HFP_SUBEVENT_RING:
|
||||
printf("** Ring **\n");
|
||||
break;
|
||||
case HFP_SUBEVENT_NUMBER_FOR_VOICE_TAG:
|
||||
printf("Phone number for voice tag: %s\n", (const char *) &event[3]);
|
||||
break;
|
||||
case HFP_SUBEVENT_SPEAKER_VOLUME:
|
||||
printf("Speaker volume: %u\n", event[3]);
|
||||
break;
|
||||
case HFP_SUBEVENT_MICROPHONE_VOLUME:
|
||||
printf("Microphone volume: %u\n", event[3]);
|
||||
break;
|
||||
default:
|
||||
printf("event not handled %u\n", event[2]);
|
||||
break;
|
||||
@ -190,7 +463,6 @@ void packet_handler(uint8_t * event, uint16_t event_size){
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_GROUP(HFPClient){
|
||||
|
||||
void setup(void){
|
||||
@ -213,61 +485,49 @@ TEST_GROUP(HFPClient){
|
||||
codecs_connection_established = 0;
|
||||
audio_connection_established = 0;
|
||||
}
|
||||
|
||||
void setup_hfp_service_level_connection(char ** test_steps, int nr_test_steps){
|
||||
service_level_connection_established = 0;
|
||||
hfp_hf_establish_service_level_connection(device_addr);
|
||||
simulate_test_sequence((char **) test_steps, nr_test_steps);
|
||||
}
|
||||
|
||||
void setup_hfp_codecs_connection(char ** test_steps, int nr_test_steps){
|
||||
codecs_connection_established = 0;
|
||||
simulate_test_sequence((char **) test_steps, nr_test_steps);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST(HFPClient, HFAudioConnectionEstablishedWithoutCodecNegotiation){
|
||||
hfp_hf_init(rfcomm_channel_nr, supported_features_without_codec_negotiation, indicators, sizeof(indicators)/sizeof(uint16_t), 1);
|
||||
hfp_hf_set_codecs(default_codecs, 1);
|
||||
|
||||
setup_hfp_service_level_connection(hfp_slc_tests()[1].test, hfp_slc_tests()[1].len);
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
|
||||
setup_hfp_codecs_connection(default_cc_setup(), default_cc_setup_size());
|
||||
CHECK_EQUAL(codecs_connection_established, 1);
|
||||
|
||||
hfp_hf_establish_audio_connection(device_addr);
|
||||
hfp_hf_release_audio_connection(device_addr);
|
||||
CHECK_EQUAL(audio_connection_established, 0);
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFCodecsConnectionEstablished){
|
||||
for (int i = 0; i < cc_tests_size(); i++){
|
||||
setup_hfp_service_level_connection(default_slc_setup(), default_slc_setup_size());
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
|
||||
setup_hfp_codecs_connection(hfp_cc_tests()[i].test, hfp_cc_tests()[i].len);
|
||||
TEST(HFPClient, PTSRHHTests){
|
||||
for (int i = 0; i < hfp_pts_hf_rhh_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_hf_rhh_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFServiceLevelConnectionCommands){
|
||||
setup_hfp_service_level_connection(default_slc_setup(), default_slc_setup_size());
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
for (int i = 0; i < slc_cmds_tests_size(); i++){
|
||||
simulate_test_sequence(hfp_slc_cmds_tests()[i].test, hfp_slc_cmds_tests()[i].len);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, HFServiceLevelConnectionEstablished){
|
||||
for (int i = 0; i < slc_tests_size(); i++){
|
||||
setup_hfp_service_level_connection(hfp_slc_tests()[i].test, hfp_slc_tests()[i].len);
|
||||
CHECK_EQUAL(service_level_connection_established, 1);
|
||||
TEST(HFPClient, PTSECCTests){
|
||||
for (int i = 0; i < hfp_pts_hf_ecc_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_hf_ecc_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, PTSECSTests){
|
||||
for (int i = 0; i < hfp_pts_hf_ecs_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_hf_ecs_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, PTSTWCTests){
|
||||
for (int i = 0; i < hfp_pts_hf_twc_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_hf_twc_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, PTSATATests){
|
||||
for (int i = 0; i < hfp_pts_hf_ata_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_hf_ata_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HFPClient, PTSSLCTests){
|
||||
for (int i = 0; i < hfp_pts_hf_slc_tests_size(); i++){
|
||||
simulate_test_sequence(&hfp_pts_hf_slc_tests()[i]);
|
||||
teardown();
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, const char * argv[]){
|
||||
hfp_hf_register_packet_handler(packet_handler);
|
||||
|
134
test/hfp/mock.c
134
test/hfp/mock.c
@ -61,7 +61,11 @@ static uint16_t rfcomm_cid = 1;
|
||||
static bd_addr_t dev_addr;
|
||||
static uint16_t sco_handle = 10;
|
||||
static uint8_t rfcomm_payload[200];
|
||||
static uint16_t rfcomm_payload_len;
|
||||
static uint16_t rfcomm_payload_len = 0;
|
||||
|
||||
static uint8_t outgoing_rfcomm_payload[200];
|
||||
static uint16_t outgoing_rfcomm_payload_len = 0;
|
||||
|
||||
void * active_connection;
|
||||
hfp_connection_t * hfp_context;
|
||||
|
||||
@ -76,34 +80,34 @@ uint16_t get_rfcomm_payload_len(){
|
||||
return rfcomm_payload_len;
|
||||
}
|
||||
|
||||
static void prepare_rfcomm_buffer(uint8_t * data, int len){
|
||||
if (len <= 0) return;
|
||||
memset(&rfcomm_payload, 0, 200);
|
||||
int pos = 0;
|
||||
static int hfp_command_start_index = 0;
|
||||
|
||||
if (strncmp((char*)data, "AT", 2) == 0){
|
||||
strncpy((char*)&rfcomm_payload[pos], (char*)data, len);
|
||||
pos += len;
|
||||
} else {
|
||||
rfcomm_payload[pos++] = '\r';
|
||||
rfcomm_payload[pos++] = '\n';
|
||||
strncpy((char*)&rfcomm_payload[pos], (char*)data, len);
|
||||
pos += len;
|
||||
|
||||
if (memcmp((char*)data, "+BAC", 4) != 0 &&
|
||||
memcmp((char*)data, "+BCS", 4) != 0){
|
||||
rfcomm_payload[pos++] = '\r';
|
||||
rfcomm_payload[pos++] = '\n';
|
||||
rfcomm_payload[pos++] = 'O';
|
||||
rfcomm_payload[pos++] = 'K';
|
||||
}
|
||||
|
||||
|
||||
int has_more_hfp_commands(int start_command_offset, int end_command_offset){
|
||||
int has_cmd = get_rfcomm_payload_len() - hfp_command_start_index >= 2 + start_command_offset + end_command_offset;
|
||||
//printf("has more: payload len %d, start %d, has more %d\n", get_rfcomm_payload_len(), hfp_command_start_index, has_cmd);
|
||||
return has_cmd;
|
||||
}
|
||||
|
||||
char * get_next_hfp_command(int start_command_offset, int end_command_offset){
|
||||
//printf("get next: payload len %d, start %d\n", get_rfcomm_payload_len(), hfp_command_start_index);
|
||||
char * data = (char *)(&get_rfcomm_payload()[hfp_command_start_index + start_command_offset]);
|
||||
int data_len = get_rfcomm_payload_len() - hfp_command_start_index - start_command_offset;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < data_len; i++){
|
||||
if ( *(data+i) == '\r' || *(data+i) == '\n' ) {
|
||||
data[i]=0;
|
||||
// update state
|
||||
//printf("!!! command %s\n", data);
|
||||
hfp_command_start_index = hfp_command_start_index + i + start_command_offset + end_command_offset;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
rfcomm_payload[pos++] = '\r';
|
||||
rfcomm_payload[pos++] = '\n';
|
||||
rfcomm_payload[pos] = 0;
|
||||
rfcomm_payload_len = pos;
|
||||
}
|
||||
printf("should not got here\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void print_without_newlines(uint8_t *data, uint16_t len){
|
||||
int found_newline = 0;
|
||||
@ -129,16 +133,26 @@ extern "C" void l2cap_register_packet_handler(void (*handler)(uint8_t packet_typ
|
||||
|
||||
|
||||
int rfcomm_send_internal(uint16_t rfcomm_cid, uint8_t *data, uint16_t len){
|
||||
if (strncmp((char*)data, "AT", 2) == 0){
|
||||
printf("Verify HF state machine response: ");
|
||||
print_without_newlines(data,len);
|
||||
} else {
|
||||
printf("Verify AG state machine response: ");
|
||||
print_without_newlines(data,len);
|
||||
}
|
||||
strncpy((char*)&rfcomm_payload[0], (char*)data, len);
|
||||
rfcomm_payload_len = len;
|
||||
return 0;
|
||||
int start_command_offset = 2;
|
||||
int end_command_offset = 2;
|
||||
|
||||
if (strncmp((char*)data, "AT", 2) == 0){
|
||||
start_command_offset = 0;
|
||||
}
|
||||
|
||||
if (has_more_hfp_commands(start_command_offset, end_command_offset)){
|
||||
//printf("Buffer response: ");
|
||||
strncpy((char*)&rfcomm_payload[rfcomm_payload_len], (char*)data, len);
|
||||
rfcomm_payload_len += len;
|
||||
} else {
|
||||
hfp_command_start_index = 0;
|
||||
//printf("Copy response: ");
|
||||
strncpy((char*)&rfcomm_payload[0], (char*)data, len);
|
||||
rfcomm_payload_len = len;
|
||||
}
|
||||
|
||||
//print_without_newlines(rfcomm_payload,rfcomm_payload_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hci_event_sco_complete(){
|
||||
@ -163,7 +177,7 @@ static void hci_event_sco_complete(){
|
||||
}
|
||||
|
||||
int hci_send_cmd(const hci_cmd_t *cmd, ...){
|
||||
printf("hci_send_cmd opcode 0x%02x\n", cmd->opcode);
|
||||
//printf("hci_send_cmd opcode 0x%02x\n", cmd->opcode);
|
||||
if (cmd->opcode == 0x428){
|
||||
hci_event_sco_complete();
|
||||
}
|
||||
@ -292,28 +306,40 @@ int hci_remote_eSCO_supported(hci_con_handle_t handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
void inject_rfcomm_command_to_hf(uint8_t * data, int len){
|
||||
if (memcmp((char*)data, "AT", 2) == 0) return;
|
||||
|
||||
prepare_rfcomm_buffer(data, len);
|
||||
if (data[0] == '+' || (data[0] == 'O' && data[1] == 'K')){
|
||||
printf("Send cmd to HF state machine: %s\n", data);
|
||||
static void add_new_lines_to_hfp_command(uint8_t * data, int len){
|
||||
if (len <= 0) return;
|
||||
memset(&outgoing_rfcomm_payload, 0, 200);
|
||||
int pos = 0;
|
||||
|
||||
if (strncmp((char*)data, "AT", 2) == 0){
|
||||
strncpy((char*)&outgoing_rfcomm_payload[pos], (char*)data, len);
|
||||
pos += len;
|
||||
} else {
|
||||
printf("Trigger HF state machine - %s", data);
|
||||
outgoing_rfcomm_payload[pos++] = '\r';
|
||||
outgoing_rfcomm_payload[pos++] = '\n';
|
||||
strncpy((char*)&outgoing_rfcomm_payload[pos], (char*)data, len);
|
||||
pos += len;
|
||||
}
|
||||
(*registered_rfcomm_packet_handler)(RFCOMM_DATA_PACKET, rfcomm_cid, (uint8_t *) &rfcomm_payload[0], rfcomm_payload_len);
|
||||
outgoing_rfcomm_payload[pos++] = '\r';
|
||||
outgoing_rfcomm_payload[pos++] = '\n';
|
||||
outgoing_rfcomm_payload[pos] = 0;
|
||||
outgoing_rfcomm_payload_len = pos;
|
||||
}
|
||||
|
||||
void inject_hfp_command_to_hf(uint8_t * data, int len){
|
||||
if (memcmp((char*)data, "AT", 2) == 0) return;
|
||||
add_new_lines_to_hfp_command(data, len);
|
||||
// printf("inject_hfp_command_to_hf to HF: ");
|
||||
// print_without_newlines(outgoing_rfcomm_payload,outgoing_rfcomm_payload_len);
|
||||
(*registered_rfcomm_packet_handler)(active_connection, RFCOMM_DATA_PACKET, rfcomm_cid, (uint8_t *) &outgoing_rfcomm_payload[0], outgoing_rfcomm_payload_len);
|
||||
|
||||
}
|
||||
|
||||
void inject_rfcomm_command_to_ag(uint8_t * data, int len){
|
||||
void inject_hfp_command_to_ag(uint8_t * data, int len){
|
||||
if (data[0] == '+') return;
|
||||
|
||||
prepare_rfcomm_buffer(data, len);
|
||||
if (memcmp((char*)data, "AT", 2) == 0){
|
||||
printf("Send cmd to AG state machine: %s\n", data);
|
||||
} else {
|
||||
printf("Trigger AG state machine - %s", data);
|
||||
}
|
||||
(*registered_rfcomm_packet_handler)( RFCOMM_DATA_PACKET, rfcomm_cid, (uint8_t *) &rfcomm_payload[0], rfcomm_payload_len);
|
||||
add_new_lines_to_hfp_command(data, len);
|
||||
(*registered_rfcomm_packet_handler)(active_connection, RFCOMM_DATA_PACKET, rfcomm_cid, (uint8_t *) &outgoing_rfcomm_payload[0], outgoing_rfcomm_payload_len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -50,5 +50,8 @@
|
||||
uint8_t * get_rfcomm_payload();
|
||||
uint16_t get_rfcomm_payload_len();
|
||||
|
||||
void inject_rfcomm_command_to_ag(uint8_t * data, int len);
|
||||
void inject_rfcomm_command_to_hf(uint8_t * data, int len);
|
||||
void inject_hfp_command_to_ag(uint8_t * data, int len);
|
||||
void inject_hfp_command_to_hf(uint8_t * data, int len);
|
||||
|
||||
int has_more_hfp_commands(int start_command_offset, int end_command_offset);
|
||||
char * get_next_hfp_command(int start_command_offset, int end_command_offset);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -47,39 +47,49 @@
|
||||
#include <string.h>
|
||||
|
||||
typedef struct hfp_test_item{
|
||||
char * name;
|
||||
char ** test;
|
||||
int len;
|
||||
} hfp_test_item_t;
|
||||
|
||||
|
||||
/* Service Level Connection (slc) test sequences */
|
||||
hfp_test_item_t * hfp_slc_tests();
|
||||
int slc_tests_size();
|
||||
char ** default_slc_setup();
|
||||
int default_slc_setup_size();
|
||||
|
||||
/* Service Level Connection (slc) common commands */
|
||||
hfp_test_item_t * hfp_slc_cmds_tests();
|
||||
int slc_cmds_tests_size();
|
||||
char ** default_slc_cmds_setup();
|
||||
int default_slc_cmds_setup_size();
|
||||
|
||||
/* Codecs Connection (cc) test sequences */
|
||||
int hfp_cc_tests_size();
|
||||
hfp_test_item_t * hfp_cc_tests();
|
||||
int cc_tests_size();
|
||||
char ** default_cc_setup();
|
||||
int default_cc_setup_size();
|
||||
hfp_test_item_t * default_hfp_cc_test();
|
||||
|
||||
/* Incoming call (ic) test sequences */
|
||||
char ** default_ic_setup();
|
||||
int default_ic_setup_size();
|
||||
/* PTS test sequences - SLC Group */
|
||||
int hfp_pts_ag_slc_tests_size();
|
||||
hfp_test_item_t * hfp_pts_ag_slc_tests();
|
||||
int hfp_pts_hf_slc_tests_size();
|
||||
hfp_test_item_t * hfp_pts_hf_slc_tests();
|
||||
|
||||
char ** alert_ic_setup();
|
||||
int alert_ic_setup_size();
|
||||
/* PTS test sequences - ATA Group */
|
||||
int hfp_pts_ag_ata_tests_size();
|
||||
hfp_test_item_t * hfp_pts_ag_ata_tests();
|
||||
int hfp_pts_hf_ata_tests_size();
|
||||
hfp_test_item_t * hfp_pts_hf_ata_tests();
|
||||
|
||||
char ** terminate_ic_ag_setup();
|
||||
int terminate_ic_ag_setup_size();
|
||||
/* PTS test sequences - TWC Group */
|
||||
int hfp_pts_ag_twc_tests_size();
|
||||
hfp_test_item_t * hfp_pts_ag_twc_tests();
|
||||
int hfp_pts_hf_twc_tests_size();
|
||||
hfp_test_item_t * hfp_pts_hf_twc_tests();
|
||||
|
||||
char ** terminate_ic_hf_setup();
|
||||
int terminate_ic_hf_setup_size();
|
||||
/* PTS test sequences - ECS Group */
|
||||
int hfp_pts_ag_ecs_tests_size();
|
||||
hfp_test_item_t * hfp_pts_ag_ecs_tests();
|
||||
int hfp_pts_hf_ecs_tests_size();
|
||||
hfp_test_item_t * hfp_pts_hf_ecs_tests();
|
||||
|
||||
/* PTS test sequences - ECC Group */
|
||||
int hfp_pts_ag_ecc_tests_size();
|
||||
hfp_test_item_t * hfp_pts_ag_ecc_tests();
|
||||
int hfp_pts_hf_ecc_tests_size();
|
||||
hfp_test_item_t * hfp_pts_hf_ecc_tests();
|
||||
|
||||
/* PTS test sequences - RHH Group */
|
||||
int hfp_pts_ag_rhh_tests_size();
|
||||
hfp_test_item_t * hfp_pts_ag_rhh_tests();
|
||||
int hfp_pts_hf_rhh_tests_size();
|
||||
hfp_test_item_t * hfp_pts_hf_rhh_tests();
|
||||
|
||||
|
@ -72,7 +72,8 @@ const uint8_t rfcomm_channel_nr = 1;
|
||||
const char hfp_ag_service_name[] = "BTstack HFP AG Test";
|
||||
|
||||
static bd_addr_t device_addr;
|
||||
static bd_addr_t pts_addr = {0x00,0x1b,0xDC,0x07,0x32,0xEF};
|
||||
static bd_addr_t pts_addr = {0x00,0x15,0x83,0x5F,0x9D,0x46};
|
||||
//static bd_addr_t pts_addr = {0x00,0x1b,0xDC,0x07,0x32,0xEF};
|
||||
static bd_addr_t speaker_addr = {0x00, 0x21, 0x3C, 0xAC, 0xF7, 0x38};
|
||||
static uint8_t codecs[1] = {HFP_CODEC_CVSD};
|
||||
static uint16_t handle = -1;
|
||||
@ -353,31 +354,38 @@ static int stdin_process(struct data_source *ds){
|
||||
switch (cmd){
|
||||
case 'a':
|
||||
memcpy(device_addr, pts_addr, 6);
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Establish HFP service level connection to PTS module %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_ag_establish_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'A':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Release HFP service level connection.\n");
|
||||
hfp_ag_release_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'z':
|
||||
memcpy(device_addr, speaker_addr, 6);
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Establish HFP service level connection to %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_ag_establish_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'Z':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Release HFP service level connection to %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_ag_release_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'b':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Establish Audio connection %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_ag_establish_audio_connection(device_addr);
|
||||
break;
|
||||
case 'B':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Release Audio connection.\n");
|
||||
hfp_ag_release_audio_connection(device_addr);
|
||||
break;
|
||||
case 'c':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Simulate incoming call from 1234567\n");
|
||||
current_call_exists_a = 1;
|
||||
current_call_status_a = HFP_ENHANCED_CALL_STATUS_INCOMING;
|
||||
@ -386,6 +394,7 @@ static int stdin_process(struct data_source *ds){
|
||||
hfp_ag_incoming_call();
|
||||
break;
|
||||
case 'm':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Simulate incoming call from 7654321\n");
|
||||
current_call_exists_b = 1;
|
||||
current_call_status_b = HFP_ENHANCED_CALL_STATUS_INCOMING;
|
||||
@ -394,14 +403,17 @@ static int stdin_process(struct data_source *ds){
|
||||
hfp_ag_incoming_call();
|
||||
break;
|
||||
case 'C':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Simulate terminate call\n");
|
||||
hfp_ag_call_dropped();
|
||||
break;
|
||||
case 'd':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Report AG failure\n");
|
||||
hfp_ag_report_extended_audio_gateway_error_result_code(device_addr, HFP_CME_ERROR_AG_FAILURE);
|
||||
break;
|
||||
case 'e':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Answer call on AG\n");
|
||||
if (current_call_status_a == HFP_ENHANCED_CALL_STATUS_INCOMING){
|
||||
current_call_status_a = HFP_ENHANCED_CALL_STATUS_ACTIVE;
|
||||
@ -412,114 +424,142 @@ static int stdin_process(struct data_source *ds){
|
||||
hfp_ag_answer_incoming_call();
|
||||
break;
|
||||
case 'E':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Reject call on AG\n");
|
||||
hfp_ag_terminate_call();
|
||||
break;
|
||||
case 'f':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Disable cellular network\n");
|
||||
hfp_ag_set_registration_status(0);
|
||||
break;
|
||||
case 'F':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Enable cellular network\n");
|
||||
hfp_ag_set_registration_status(1);
|
||||
break;
|
||||
case 'g':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set signal strength to 0\n");
|
||||
hfp_ag_set_signal_strength(0);
|
||||
break;
|
||||
case 'G':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set signal strength to 5\n");
|
||||
hfp_ag_set_signal_strength(5);
|
||||
break;
|
||||
case 'h':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Disable roaming\n");
|
||||
hfp_ag_set_roaming_status(0);
|
||||
break;
|
||||
case 'H':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Enable roaming\n");
|
||||
hfp_ag_set_roaming_status(1);
|
||||
break;
|
||||
case 'i':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set battery level to 3\n");
|
||||
hfp_ag_set_battery_level(3);
|
||||
break;
|
||||
case 'I':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set battery level to 5\n");
|
||||
hfp_ag_set_battery_level(5);
|
||||
break;
|
||||
case 'j':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Answering call on remote side\n");
|
||||
hfp_ag_outgoing_call_established();
|
||||
break;
|
||||
case 'r':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Disable in-band ring tone\n");
|
||||
hfp_ag_set_use_in_band_ring_tone(0);
|
||||
break;
|
||||
case 'k':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Memory 1 cleared\n");
|
||||
memory_1_enabled = 0;
|
||||
break;
|
||||
case 'K':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Memory 1 set\n");
|
||||
memory_1_enabled = 1;
|
||||
break;
|
||||
case 'l':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Last dialed number cleared\n");
|
||||
last_number_exists = 0;
|
||||
break;
|
||||
case 'L':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Last dialed number set\n");
|
||||
last_number_exists = 1;
|
||||
break;
|
||||
case 'n':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Disable Voice Recognition\n");
|
||||
hfp_ag_activate_voice_recognition(device_addr, 0);
|
||||
break;
|
||||
case 'N':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Enable Voice Recognition\n");
|
||||
hfp_ag_activate_voice_recognition(device_addr, 1);
|
||||
break;
|
||||
case 'o':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 0 (minimum)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 0);
|
||||
break;
|
||||
case 'O':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 9 (default)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 9);
|
||||
break;
|
||||
case 'p':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 12 (higher)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 12);
|
||||
break;
|
||||
case 'P':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 15 (maximum)\n");
|
||||
hfp_ag_set_speaker_gain(device_addr, 15);
|
||||
break;
|
||||
case 'q':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 0\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 0);
|
||||
break;
|
||||
case 'Q':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 9\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 9);
|
||||
break;
|
||||
case 's':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 12\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 12);
|
||||
break;
|
||||
case 'S':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 15\n");
|
||||
hfp_ag_set_microphone_gain(device_addr, 15);
|
||||
break;
|
||||
case 'R':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Enable in-band ring tone\n");
|
||||
hfp_ag_set_use_in_band_ring_tone(1);
|
||||
break;
|
||||
case 't':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Terminate HCI connection.\n");
|
||||
gap_disconnect(handle);
|
||||
break;
|
||||
case 'u':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Join held call\n");
|
||||
current_call_mpty = HFP_ENHANCED_CALL_MPTY_CONFERENCE_CALL;
|
||||
hfp_ag_join_held_call();
|
||||
@ -528,14 +568,17 @@ static int stdin_process(struct data_source *ds){
|
||||
start_scan();
|
||||
break;
|
||||
case 'w':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("AG: Put incoming call on hold (Response and Hold)\n");
|
||||
hfp_ag_hold_incoming_call();
|
||||
break;
|
||||
case 'x':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("AG: Accept held incoming call (Response and Hold)\n");
|
||||
hfp_ag_accept_held_incoming_call();
|
||||
break;
|
||||
case 'X':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("AG: Reject held incoming call (Response and Hold)\n");
|
||||
hfp_ag_reject_held_incoming_call();
|
||||
break;
|
||||
|
@ -73,7 +73,8 @@ const uint32_t hfp_service_buffer[150/4]; // implicit alignment to 4-byte memo
|
||||
const uint8_t rfcomm_channel_nr = 1;
|
||||
const char hfp_hf_service_name[] = "BTstack HFP HF Test";
|
||||
|
||||
static bd_addr_t pts_addr = {0x00,0x1b,0xDC,0x07,0x32,0xEF};
|
||||
static bd_addr_t pts_addr = {0x00,0x15,0x83,0x5F,0x9D,0x46};
|
||||
//static bd_addr_t pts_addr = {0x00,0x1b,0xDC,0x07,0x32,0xEF};
|
||||
static bd_addr_t phone_addr = {0xD8,0xBb,0x2C,0xDf,0xF1,0x08};
|
||||
|
||||
static bd_addr_t device_addr;
|
||||
@ -186,213 +187,266 @@ static int stdin_process(struct data_source *ds){
|
||||
case '-':
|
||||
case '+':
|
||||
case '*':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("DTMF Code: %c\n", cmd);
|
||||
hfp_hf_send_dtmf_code(device_addr, cmd);
|
||||
break;
|
||||
case 'a':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Establish Service level connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_establish_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'A':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Release Service level connection.\n");
|
||||
hfp_hf_release_service_level_connection(device_addr);
|
||||
break;
|
||||
case 'b':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Establish Audio connection to device with Bluetooth address %s...\n", bd_addr_to_str(device_addr));
|
||||
hfp_hf_establish_audio_connection(device_addr);
|
||||
break;
|
||||
case 'B':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Release Audio service level connection.\n");
|
||||
hfp_hf_release_audio_connection(device_addr);
|
||||
break;
|
||||
case 'C':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Enable registration status update for all AG indicators.\n");
|
||||
hfp_hf_enable_status_update_for_all_ag_indicators(device_addr);
|
||||
case 'c':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Disable registration status update for all AG indicators.\n");
|
||||
hfp_hf_disable_status_update_for_all_ag_indicators(device_addr);
|
||||
break;
|
||||
case 'D':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set HFP AG registration status update for individual indicators (0111111).\n");
|
||||
hfp_hf_set_status_update_for_individual_ag_indicators(device_addr, 63);
|
||||
break;
|
||||
case 'd':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Query network operator.\n");
|
||||
hfp_hf_query_operator_selection(device_addr);
|
||||
break;
|
||||
case 'E':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Enable reporting of the extended AG error result code.\n");
|
||||
hfp_hf_enable_report_extended_audio_gateway_error_result_code(device_addr);
|
||||
break;
|
||||
case 'e':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Disable reporting of the extended AG error result code.\n");
|
||||
hfp_hf_disable_report_extended_audio_gateway_error_result_code(device_addr);
|
||||
break;
|
||||
case 'f':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Answer incoming call.\n");
|
||||
hfp_hf_answer_incoming_call(device_addr);
|
||||
break;
|
||||
case 'F':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Hangup call.\n");
|
||||
hfp_hf_terminate_call(device_addr);
|
||||
break;
|
||||
case 'G':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Reject call.\n");
|
||||
hfp_hf_reject_call(device_addr);
|
||||
break;
|
||||
case 'g':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Query operator.\n");
|
||||
hfp_hf_query_operator_selection(device_addr);
|
||||
break;
|
||||
case 't':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Terminate HCI connection.\n");
|
||||
gap_disconnect(handle);
|
||||
break;
|
||||
case 'i':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Dial 1234567\n");
|
||||
hfp_hf_dial_number(device_addr, "1234567");
|
||||
break;
|
||||
case 'I':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Dial 7654321\n");
|
||||
hfp_hf_dial_number(device_addr, "7654321");
|
||||
break;
|
||||
case 'j':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Dial #1\n");
|
||||
hfp_hf_dial_memory(device_addr,"1");
|
||||
break;
|
||||
case 'J':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Dial #99\n");
|
||||
hfp_hf_dial_memory(device_addr,"99");
|
||||
break;
|
||||
case 'k':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Deactivate call waiting notification\n");
|
||||
hfp_hf_deactivate_call_waiting_notification(device_addr);
|
||||
break;
|
||||
case 'K':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Activate call waiting notification\n");
|
||||
hfp_hf_activate_call_waiting_notification(device_addr);
|
||||
break;
|
||||
case 'l':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Deactivate calling line notification\n");
|
||||
hfp_hf_deactivate_calling_line_notification(device_addr);
|
||||
break;
|
||||
case 'L':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Activate calling line notification\n");
|
||||
hfp_hf_activate_calling_line_notification(device_addr);
|
||||
break;
|
||||
case 'm':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Deactivate echo canceling and noise reduction\n");
|
||||
hfp_hf_deactivate_echo_canceling_and_noise_reduction(device_addr);
|
||||
break;
|
||||
case 'M':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Activate echo canceling and noise reduction\n");
|
||||
hfp_hf_activate_echo_canceling_and_noise_reduction(device_addr);
|
||||
break;
|
||||
case 'n':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Deactivate voice recognition\n");
|
||||
hfp_hf_deactivate_voice_recognition_notification(device_addr);
|
||||
break;
|
||||
case 'N':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Activate voice recognition\n");
|
||||
hfp_hf_activate_voice_recognition_notification(device_addr);
|
||||
break;
|
||||
case 'o':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 0 (minimum)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 0);
|
||||
break;
|
||||
case 'O':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 9 (default)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 9);
|
||||
break;
|
||||
case 'p':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 12 (higher)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 12);
|
||||
break;
|
||||
case 'P':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set speaker gain to 15 (maximum)\n");
|
||||
hfp_hf_set_speaker_gain(device_addr, 15);
|
||||
break;
|
||||
case 'q':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 0\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 0);
|
||||
break;
|
||||
case 'Q':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 9\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 9);
|
||||
break;
|
||||
case 's':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 12\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 12);
|
||||
break;
|
||||
case 'S':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Set microphone gain to 15\n");
|
||||
hfp_hf_set_microphone_gain(device_addr, 15);
|
||||
break;
|
||||
case 'u':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Send 'user busy' (Three-Way Call 0)\n");
|
||||
hfp_hf_user_busy(device_addr);
|
||||
break;
|
||||
case 'U':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("End active call and accept waiting/held call (Three-Way Call 1)\n");
|
||||
hfp_hf_end_active_and_accept_other(device_addr);
|
||||
break;
|
||||
case 'v':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Swap active call and hold/waiting call (Three-Way Call 2)\n");
|
||||
hfp_hf_swap_calls(device_addr);
|
||||
break;
|
||||
case 'V':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Join hold call (Three-Way Call 3)\n");
|
||||
hfp_hf_join_held_call(device_addr);
|
||||
break;
|
||||
case 'w':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Connect calls (Three-Way Call 4)\n");
|
||||
hfp_hf_connect_calls(device_addr);
|
||||
break;
|
||||
case 'W':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Redial\n");
|
||||
hfp_hf_redial_last_number(device_addr);
|
||||
break;
|
||||
case 'x':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Request phone number for voice tag\n");
|
||||
hfp_hf_request_phone_number_for_voice_tag(device_addr);
|
||||
break;
|
||||
case 'X':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Query current call status\n");
|
||||
hfp_hf_query_current_call_status(device_addr);
|
||||
break;
|
||||
case 'y':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Release call with index 2\n");
|
||||
hfp_hf_release_call_with_index(device_addr, 2);
|
||||
break;
|
||||
case 'Y':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Private consulation with call 2\n");
|
||||
hfp_hf_private_consultation_with_call(device_addr, 2);
|
||||
break;
|
||||
case 'z':
|
||||
memcpy(device_addr, phone_addr, 6);
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Use iPhone %s as Audiogateway.\n", bd_addr_to_str(device_addr));
|
||||
break;
|
||||
case '[':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Query Response and Hold status (RHH ?)\n");
|
||||
hfp_hf_rrh_query_status(device_addr);
|
||||
break;
|
||||
case ']':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Place call in a response and held state (RHH 0)\n");
|
||||
hfp_hf_rrh_hold_call(device_addr);
|
||||
break;
|
||||
case '{':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Accept held call (RHH 1)\n");
|
||||
hfp_hf_rrh_accept_held_call(device_addr);
|
||||
break;
|
||||
case '}':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Reject held call (RHH 2)\n");
|
||||
hfp_hf_rrh_reject_held_call(device_addr);
|
||||
break;
|
||||
case '?':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Query Subscriber Number\n");
|
||||
hfp_hf_query_subscriber_number(device_addr);
|
||||
break;
|
||||
case '!':
|
||||
log_info("USER:\'%c\'", cmd);
|
||||
printf("Update HF indicator with assigned number 1 (HFI)\n");
|
||||
hfp_hf_set_hf_indicator(device_addr, 1, 1);
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user