docu & api change HSP HS

This commit is contained in:
Milanka Ringwald 2016-03-17 11:49:30 +01:00
parent ee5d6bf559
commit 4e919b3947
6 changed files with 291 additions and 124 deletions

View File

@ -57,6 +57,7 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <btstack/hci_cmds.h>
#include <btstack/run_loop.h>
@ -64,20 +65,35 @@
#include "sdp.h"
#include "hsp_hs.h"
#include "stdin_support.h"
#include "hci.h"
#include "l2cap.h"
#include "rfcomm.h"
#include "debug.h"
#define SCO_REPORT_PERIOD 255
static uint32_t hsp_service_buffer[150/4]; // implicit alignment to 4-byte memory address
static const uint8_t rfcomm_channel_nr = 1;
static const char hsp_hs_service_name[] = "Headset Test";
static uint16_t sco_handle = 0;
static char hs_cmd_buffer[100];
// static bd_addr_t current_addr = {0x04,0x0C,0xCE,0xE4,0x85,0xD3};
static bd_addr_t current_addr = {0x00,0x1b,0xDC,0x07,0x32,0xEF};
static int phase = 0;
// input signal: pre-computed sine wave, 160 Hz
static const uint8_t sine[] = {
0, 15, 31, 46, 61, 74, 86, 97, 107, 114,
120, 124, 126, 126, 124, 120, 114, 107, 97, 86,
74, 61, 46, 31, 15, 0, 241, 225, 210, 195,
182, 170, 159, 149, 142, 136, 132, 130, 130, 132,
136, 142, 149, 159, 170, 182, 195, 210, 225, 241,
};
/* @section Audio Transfer Setup
*
* @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz.
@ -85,8 +101,8 @@ static int phase = 0;
*
* Tested working setups:
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud
* - Ubuntu 14 64-bit, CSR dongle
* - OS X 10.11, CSR dongle
* - Ubuntu 14 64-bit, CSR USB dongle
* - OS X 10.11, CSR USB dongle
*
* Broken setups:
* - OS X 10.11, CC2564B connected via FDTI USB-2-UART adapter, 921600 baud
@ -101,15 +117,86 @@ static int phase = 0;
*
*/
// input signal: pre-computed sine wave, 160 Hz
static const uint8_t sine[] = {
0, 15, 31, 46, 61, 74, 86, 97, 107, 114,
120, 124, 126, 126, 124, 120, 114, 107, 97, 86,
74, 61, 46, 31, 15, 0, 241, 225, 210, 195,
182, 170, 159, 149, 142, 136, 132, 130, 130, 132,
136, 142, 149, 159, 170, 182, 195, 210, 225, 241,
};
static void show_usage(void){
uint8_t iut_address_type;
bd_addr_t iut_address;
hci_le_advertisement_address(&iut_address_type, iut_address);
printf("\n--- Bluetooth HSP Headset Test Console %s ---\n", bd_addr_to_str(iut_address));
printf("---\n");
printf("c - Connect to %s\n", bd_addr_to_str(current_addr));
printf("C - Disconnect\n");
printf("a - establish audio connection\n");
printf("A - release audio connection\n");
printf("b - press user button\n");
printf("z - set microphone gain 0\n");
printf("m - set microphone gain 8\n");
printf("M - set microphone gain 15\n");
printf("o - set speaker gain 0\n");
printf("s - set speaker gain 8\n");
printf("S - set speaker gain 15\n");
printf("---\n");
printf("Ctrl-c - exit\n");
printf("---\n");
}
static int stdin_process(struct data_source *ds){
char buffer;
read(ds->fd, &buffer, 1);
switch (buffer){
case 'c':
printf("Connect to %s\n", bd_addr_to_str(current_addr));
hsp_hs_connect(current_addr);
break;
case 'C':
printf("Disconnect.\n");
hsp_hs_disconnect();
break;
case 'a':
printf("Establish audio connection\n");
hsp_hs_establish_audio_connection();
break;
case 'A':
printf("Release audio connection\n");
hsp_hs_release_audio_connection();
break;
case 'z':
printf("Setting microphone gain 0\n");
hsp_hs_set_microphone_gain(0);
break;
case 'm':
printf("Setting microphone gain 8\n");
hsp_hs_set_microphone_gain(8);
break;
case 'M':
printf("Setting microphone gain 15\n");
hsp_hs_set_microphone_gain(15);
break;
case 'o':
printf("Setting speaker gain 0\n");
hsp_hs_set_speaker_gain(0);
break;
case 's':
printf("Setting speaker gain 8\n");
hsp_hs_set_speaker_gain(8);
break;
case 'S':
printf("Setting speaker gain 15\n");
hsp_hs_set_speaker_gain(15);
break;
case 'b':
printf("Press user button\n");
hsp_hs_send_button_press();
break;
default:
show_usage();
break;
}
return 0;
}
static void try_send_sco(void){
if (!sco_handle) return;
@ -137,27 +224,28 @@ static void try_send_sco(void){
hci_send_sco_packet_buffer(sco_packet_length);
static int count = 0;
count++;
if ((count & 15) == 0) printf("Sent %u\n", count);
if ((count & SCO_REPORT_PERIOD) == 0) printf("Sent %u\n", count);
}
static void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){
static int count = 0;
count++;
if ((count & 15)) return;
if ((count & SCO_REPORT_PERIOD)) return;
printf("SCO packets %u\n", count);
// hexdumpf(packet, size);
hexdumpf(packet, size);
}
static void packet_handler(uint8_t * event, uint16_t event_size){
// printf("Packet handler event 0x%02x\n", event[0]);
//printf("Packet handler event 0x%02x / BTSTACK_EVENT_STATE 0x%02x\n", event[0], BTSTACK_EVENT_STATE);
try_send_sco();
switch (event[0]) {
case BTSTACK_EVENT_STATE:
if (event[2] != HCI_STATE_WORKING) break;
printf("Working!\n");
printf("HCI_STATE_WORKING\n");
show_usage();
break;
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
// printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n");
@ -169,6 +257,20 @@ static void packet_handler(uint8_t * event, uint16_t event_size){
break;
case HCI_EVENT_HSP_META:
switch (event[2]) {
case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE:
if (event[3] == 0){
printf("RFCOMM connection established.\n");
} else {
printf("RFCOMM connection establishement failed.\n");
}
break;
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
if (event[3] == 0){
printf("RFCOMM disconnected.\n");
} else {
printf("RFCOMM disconnection failed.\n");
}
break;
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
if (event[3] == 0){
sco_handle = READ_BT_16(event, 4);
@ -222,13 +324,17 @@ static void packet_handler(uint8_t * event, uint16_t event_size){
* - The HCI SCO packet handler receives audio data.
* - The HSP HS packet handler is used to trigger sending of audio data and commands to the AG. It also receives the AG's answers.
*
* The stdin_process callback allows for sending commands to the AG.
* At the end the Bluetooth stack is started.
*/
/* LISTING_START(MainConfiguration): Setup packet handlers and audio data channel for HSP Headset */
int btstack_main(int argc, const char * argv[]);
int btstack_main(int argc, const char * argv[]){
l2cap_init();
rfcomm_init();
sdp_init();
memset((uint8_t *)hsp_service_buffer, 0, sizeof(hsp_service_buffer));
hsp_hs_create_sdp_record((uint8_t *)hsp_service_buffer, rfcomm_channel_nr, hsp_hs_service_name, 0);
sdp_register_service_internal(NULL, (uint8_t *)hsp_service_buffer);
@ -238,10 +344,14 @@ int btstack_main(int argc, const char * argv[]){
hsp_hs_init(rfcomm_channel_nr);
hsp_hs_register_packet_handler(packet_handler);
btstack_stdin_setup(stdin_process);
gap_set_local_name("BTstack HSP HS");
hci_discoverable_control(1);
hci_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO);
// turn on!
hci_set_class_of_device(0x240404);
hci_power_control(HCI_POWER_ON);
return 0;

View File

@ -623,34 +623,51 @@ extern "C" {
* @param subevent_code
* @param status 0 == OK
*/
#define HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE 0x01
#define HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE 0x01
// data: event(8), len(8), subevent(8), status(8)
/**
* @format 11
* @param subevent_code
* @param status 0 == OK
*/
#define HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE 0x02
// data: event(8), len(8), subevent(8), status(8)
/**
* @format 11
* @param subevent_code
* @param status 0 == OK
*/
#define HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE 0x03
/**
* @format 11
* @param subevent_code
* @param status 0 == OK
*/
#define HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE 0x02
#define HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE 0x04
/**
* @format 1
* @param subevent_code
*/
#define HSP_SUBEVENT_RING 0x03
#define HSP_SUBEVENT_RING 0x05
/**
* @format 11
* @param subevent_code
* @param gain Valid range: [0,15]
*/
#define HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED 0x04
#define HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED 0x06
/**
* @format 11
* @param subevent_code
* @param gain Valid range: [0,15]
*/
#define HSP_SUBEVENT_SPEAKER_GAIN_CHANGED 0x05
#define HSP_SUBEVENT_SPEAKER_GAIN_CHANGED 0x07
/**
* @format 1JV
@ -658,7 +675,7 @@ extern "C" {
* @param value_length
* @param value
*/
#define HSP_SUBEVENT_HS_COMMAND 0x06
#define HSP_SUBEVENT_HS_COMMAND 0x08
/**
* @format 1JV
@ -666,7 +683,7 @@ extern "C" {
* @param value_length
* @param value
*/
#define HSP_SUBEVENT_AG_INDICATION 0x07
#define HSP_SUBEVENT_AG_INDICATION 0x09
#define HCI_EVENT_HFP_META 0xE9

View File

@ -100,7 +100,7 @@ static int hfp_ag_get_ag_indicators_nr(hfp_connection_t * hfp_connection){
return hfp_connection->ag_indicators_nr;
}
hfp_ag_indicator_t * hfp_ag_get_ag_indicators(hfp_connection_t * hfp_connection){
static hfp_ag_indicator_t * hfp_ag_get_ag_indicators(hfp_connection_t * hfp_connection){
// TODO: save only value, and value changed in the hfp_connection?
if (hfp_connection->ag_indicators_nr != hfp_ag_indicators_nr){
hfp_connection->ag_indicators_nr = hfp_ag_indicators_nr;

View File

@ -87,22 +87,33 @@ static int hs_microphone_gain = -1;
static int hs_speaker_gain = -1;
static uint8_t hs_send_button_press = 0;
static uint8_t wait_ok = 0;
static uint8_t hs_support_custom_indications = 0;
static uint8_t hs_outgoing_connection = 0;
static uint8_t hsp_disconnect_rfcomm = 0;
static uint8_t hsp_establish_audio_connection = 0;
static uint8_t hsp_release_audio_connection = 0;
typedef enum {
HSP_IDLE,
HSP_SDP_QUERY_RFCOMM_CHANNEL,
HSP_W4_SDP_QUERY_COMPLETE,
HSP_W4_RFCOMM_CONNECTED,
HSP_W4_USER_ACTION,
HSP_RFCOMM_CONNECTION_ESTABLISHED,
HSP_W2_CONNECT_SCO,
HSP_W4_SCO_CONNECTED,
HSP_ACTIVE,
HSP_AUDIO_CONNECTION_ESTABLISHED,
HSP_W2_DISCONNECT_SCO,
HSP_W4_SCO_DISCONNECTED,
HSP_W4_SCO_DISCONNECTED,
HSP_W2_DISCONNECT_RFCOMM,
HSP_W4_RFCOMM_DISCONNECTED,
HSP_W4_RFCOMM_DISCONNECTED_AND_RESTART,
HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
} hsp_state_t;
@ -156,7 +167,6 @@ static void emit_event_audio_connected(uint8_t status, uint16_t handle){
// AG +VGM=13 [0..15] ; HS AT+VGM=6 | AG OK
static int hsp_hs_send_str_over_rfcomm(uint16_t cid, const char * command){
if (!rfcomm_can_send_packet_now(rfcomm_cid)) return 1;
int err = rfcomm_send_internal(cid, (uint8_t*) command, strlen(command));
if (err){
log_info("rfcomm_send_internal -> error 0X%02x", err);
@ -248,24 +258,18 @@ void hsp_hs_create_sdp_record(uint8_t * service, int rfcomm_channel_nr, const ch
static void hsp_hs_reset_state(void){
hsp_state = HSP_IDLE;
rfcomm_cid = 0;
rfcomm_handle = 0;
sco_handle = 0;
hs_microphone_gain = -1;
hs_speaker_gain = -1;
hs_send_button_press = 0;
wait_ok = 0;
hs_support_custom_indications = 0;
}
void hsp_hs_init(uint8_t rfcomm_channel_nr){
// init L2CAP
l2cap_init();
l2cap_register_packet_handler(packet_handler);
rfcomm_init();
rfcomm_register_packet_handler(packet_handler);
rfcomm_register_service_internal(NULL, rfcomm_channel_nr, 0xffff); // reserved channel, mtu limited by l2cap
@ -277,27 +281,59 @@ void hsp_hs_init(uint8_t rfcomm_channel_nr){
void hsp_hs_connect(bd_addr_t bd_addr){
if (hsp_state != HSP_IDLE) return;
hs_outgoing_connection = 1;
hsp_state = HSP_SDP_QUERY_RFCOMM_CHANNEL;
memcpy(remote, bd_addr, 6);
hsp_run();
}
void hsp_hs_disconnect(bd_addr_t bd_addr){
void hsp_hs_disconnect(void){
hsp_hs_release_audio_connection();
if (hsp_state < HSP_W4_RFCOMM_CONNECTED){
hsp_state = HSP_IDLE;
return;
}
if (hsp_state == HSP_W4_RFCOMM_CONNECTED){
hsp_state = HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN;
return;
}
if (hsp_state < HSP_W4_SCO_CONNECTED){
hsp_state = HSP_W2_DISCONNECT_RFCOMM;
return;
}
if (hsp_state < HSP_W4_SCO_DISCONNECTED){
hsp_state = HSP_W2_DISCONNECT_SCO;
return;
}
hsp_disconnect_rfcomm = 1;
hsp_run();
}
void hsp_hs_establish_audio_connection(void){
switch (hsp_state){
case HSP_ACTIVE:
hsp_state = HSP_W4_USER_ACTION;
hs_send_button_press = 1;
case HSP_RFCOMM_CONNECTION_ESTABLISHED:
hsp_establish_audio_connection = 1;
hsp_state = HSP_W4_SCO_CONNECTED;
break;
case HSP_W4_RFCOMM_CONNECTED:
hsp_state = HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN;
break;
default:
return;
break;
}
hsp_run();
}
void hsp_hs_release_audio_connection(void){
if (hsp_state >= HSP_W2_DISCONNECT_SCO) return;
if (hsp_state < HSP_AUDIO_CONNECTION_ESTABLISHED) return;
hsp_release_audio_connection = 1;
hsp_run();
}
void hsp_hs_set_microphone_gain(uint8_t gain){
if (gain < 0 || gain >15) {
@ -320,14 +356,34 @@ void hsp_hs_set_speaker_gain(uint8_t gain){
static void hsp_run(void){
int err;
if (!rfcomm_can_send_packet_now(rfcomm_cid)) return;
if (wait_ok) return;
if (hsp_release_audio_connection){
hsp_release_audio_connection = 0;
wait_ok = 1;
hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD);
return;
}
if (hsp_disconnect_rfcomm){
hsp_disconnect_rfcomm = 0;
hsp_establish_audio_connection = 0;
rfcomm_disconnect_internal(rfcomm_cid);
return;
}
if (hsp_establish_audio_connection){
hsp_establish_audio_connection = 0;
wait_ok = 1;
hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD);
return;
}
if (hs_send_button_press){
hs_send_button_press = 0;
err = hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD);
if (err) {
hs_send_button_press = 1;
}
wait_ok = 1;
hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD);
return;
}
@ -337,40 +393,27 @@ static void hsp_run(void){
sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_Headset_AG);
break;
case HSP_W2_CONNECT_SCO:
hsp_state = HSP_W4_SCO_CONNECTED;
break;
case HSP_W2_DISCONNECT_SCO:
hsp_state = HSP_W4_SCO_DISCONNECTED;
break;
case HSP_AUDIO_CONNECTION_ESTABLISHED:
case HSP_RFCOMM_CONNECTION_ESTABLISHED :
case HSP_ACTIVE:
if (hs_microphone_gain >= 0){
int gain = hs_microphone_gain;
hs_microphone_gain = -1;
if (hs_microphone_gain >= 0){
char buffer[20];
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;
}
sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain);
hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
hs_microphone_gain = -1;
break;
}
if (hs_speaker_gain >= 0){
int gain = hs_speaker_gain;
hs_speaker_gain = -1;
char buffer[20];
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;
}
sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, hs_speaker_gain);
hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
hs_speaker_gain = -1;
break;
}
break;
case HSP_W4_RFCOMM_DISCONNECTED:
rfcomm_disconnect_internal(rfcomm_cid);
break;
default:
break;
@ -379,7 +422,7 @@ static void hsp_run(void){
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
// printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
//printf("packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
if (packet_type == RFCOMM_DATA_PACKET){
// skip over leading newline
while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
@ -389,16 +432,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
if (strncmp((char *)packet, HSP_AG_RING, strlen(HSP_AG_RING)) == 0){
emit_ring_event();
} else if (strncmp((char *)packet, HSP_AG_OK, strlen(HSP_AG_OK)) == 0){
switch (hsp_state){
case HSP_W4_RFCOMM_CONNECTED:
hsp_state = HSP_W2_CONNECT_SCO;
break;
case HSP_W4_USER_ACTION:
hsp_state = HSP_W2_DISCONNECT_SCO;
break;
default:
break;
}
wait_ok = 0;
} else if (strncmp((char *)packet, HSP_MICROPHONE_GAIN, strlen(HSP_MICROPHONE_GAIN)) == 0){
uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_MICROPHONE_GAIN)]);
emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, gain);
@ -433,6 +467,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
switch (event) {
case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{
if (hsp_state < HSP_RFCOMM_CONNECTION_ESTABLISHED) return;
int index = 2;
uint8_t status = packet[index++];
sco_handle = READ_BT_16(packet, index);
@ -452,8 +487,10 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
if (status != 0){
log_error("(e)SCO Connection failed, status %u", status);
emit_event_audio_connected(status, sco_handle);
hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED ;
break;
}
switch (link_type){
case 0x00:
log_info("SCO Connection established.");
@ -473,16 +510,11 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
" rx_packet_length %u bytes, tx_packet_length %u bytes, air_mode 0x%2x (0x02 == CVSD)", sco_handle,
bd_addr_to_str(address), transmission_interval, retransmission_interval, rx_packet_length, tx_packet_length, air_mode);
if (hsp_state == HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN){
hsp_state = HSP_W2_DISCONNECT_SCO;
break;
}
// forward event to app
hsp_hs_callback(packet, size);
hsp_state = HSP_ACTIVE;
emit_event_audio_connected(0, sco_handle);
hsp_state = HSP_AUDIO_CONNECTION_ESTABLISHED;
emit_event_audio_connected(status, sco_handle);
break;
}
@ -493,43 +525,29 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
bt_flip_addr(event_addr, &packet[2]);
rfcomm_cid = READ_BT_16(packet, 9);
log_info("RFCOMM channel %u requested for %s", packet[8], bd_addr_to_str(event_addr));
rfcomm_accept_connection_internal(rfcomm_cid);
hsp_state = HSP_W4_RFCOMM_CONNECTED;
rfcomm_accept_connection_internal(rfcomm_cid);
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
// printf("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
// data: event(8), len(8), status (8), address (48), handle(16), server channel(8), rfcomm_cid(16), max frame size(16)
if (hsp_state != HSP_W4_RFCOMM_CONNECTED) return;
if (packet[2]) {
log_info("RFCOMM channel open failed, status %u", packet[2]);
hsp_state = HSP_IDLE;
hsp_hs_reset_state();
emit_event(HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE, packet[2]);
hs_outgoing_connection = 0;
} else {
// data: event(8) , len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
rfcomm_handle = READ_BT_16(packet, 9);
rfcomm_cid = READ_BT_16(packet, 12);
mtu = READ_BT_16(packet, 14);
log_info("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u", rfcomm_cid, mtu);
if (hs_outgoing_connection){
hs_outgoing_connection = 0;
hs_send_button_press = 1;
}
switch (hsp_state){
case HSP_W4_RFCOMM_CONNECTED:
hsp_state = HSP_W2_CONNECT_SCO;
break;
case HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN:
hsp_state = HSP_W2_DISCONNECT_RFCOMM;
break;
default:
break;
}
log_info("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u, handle %02x", rfcomm_cid, mtu, rfcomm_handle);
hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED;
}
emit_event(HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE, packet[2]);
break;
case BTSTACK_EVENT_STATE:
case DAEMON_EVENT_HCI_PACKET_SENT:
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
case RFCOMM_EVENT_CREDITS:
@ -540,13 +558,21 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
handle = READ_BT_16(packet,3);
if (handle == sco_handle){
sco_handle = 0;
hsp_state = HSP_W2_DISCONNECT_RFCOMM;
hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED ;
hsp_hs_reset_state();
emit_event(HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE,0);
break;
}
if (handle == rfcomm_handle) {
rfcomm_handle = 0;
hsp_state = HSP_IDLE;
hsp_hs_callback(packet, size);
hsp_hs_reset_state();
}
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
hsp_hs_reset_state();
emit_event(HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE,0);
hsp_hs_callback(packet, size);
break;
default:
break;
@ -569,18 +595,18 @@ static void handle_query_rfcomm_event(sdp_query_event_t * event, void * context)
if (channel_nr > 0){
hsp_state = HSP_W4_RFCOMM_CONNECTED;
log_info("RFCOMM create channel.log_info");
log_info("HSP: SDP_QUERY_COMPLETE. RFCOMM create channel, addr %s, rfcomm channel nr %d", bd_addr_to_str(remote), channel_nr);
rfcomm_create_channel_internal(NULL, remote, channel_nr);
break;
}
hsp_hs_reset_state();
log_info("Service not found, status %u.", ce->status);
exit(0);
log_info("Service not fou nd, status %u.", ce->status);
break;
}
}
void hsp_hs_send_button_press(void){
if (hsp_state < HSP_RFCOMM_CONNECTION_ESTABLISHED || hsp_state >= HSP_W4_RFCOMM_DISCONNECTED) return;
hs_send_button_press = 1;
hsp_run();
}

View File

@ -110,7 +110,27 @@ void hsp_hs_connect(bd_addr_t bd_addr);
* Releases the RFCOMM channel.
* @param bd_addr
*/
void hsp_hs_disconnect(bd_addr_t bd_addr);
void hsp_hs_disconnect(void);
/**
* @brief Send button press action. Toggle establish/release of audio connection.
*/
void hsp_hs_send_button_press(void);
/**
* @brief Triger establishing audio connection.
*
* @param bd_addr
*/
void hsp_hs_establish_audio_connection(void);
/**
* @brief Trigger releasing audio connection.
*
* @param bd_addr
*/
void hsp_hs_release_audio_connection(void);
/**
* @brief Set microphone gain.
@ -130,11 +150,7 @@ void hsp_hs_set_microphone_gain(uint8_t gain);
*/
void hsp_hs_set_speaker_gain(uint8_t gain);
/**
* @brief Send button press action.
* @param gain Valid range: [0,15]
*/
void hsp_hs_send_button_press(void);
/**
* @brief Enable custom indications.

View File

@ -175,7 +175,7 @@ static int stdin_process(struct data_source *ds){
break;
case 'd':
printf("Releasing audio connection.\n");
hsp_hs_disconnect(current_addr);
hsp_hs_disconnect();
break;
case 'z':
printf("Setting microphone gain 0\n");
@ -245,8 +245,6 @@ static void packet_handler(uint8_t * event, uint16_t event_size){
case BTSTACK_EVENT_STATE:
if (event[2] != HCI_STATE_WORKING) break;
show_usage();
// request loopback mode
hci_send_cmd(&hci_write_synchronous_flow_control_enable, 1);
break;
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
// printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n");