mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-24 15:02:43 +00:00
docu & api change HSP HS
This commit is contained in:
parent
ee5d6bf559
commit
4e919b3947
@ -57,6 +57,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <btstack/hci_cmds.h>
|
#include <btstack/hci_cmds.h>
|
||||||
#include <btstack/run_loop.h>
|
#include <btstack/run_loop.h>
|
||||||
@ -64,20 +65,35 @@
|
|||||||
|
|
||||||
#include "sdp.h"
|
#include "sdp.h"
|
||||||
#include "hsp_hs.h"
|
#include "hsp_hs.h"
|
||||||
|
#include "stdin_support.h"
|
||||||
|
|
||||||
#include "hci.h"
|
#include "hci.h"
|
||||||
#include "l2cap.h"
|
#include "l2cap.h"
|
||||||
|
#include "rfcomm.h"
|
||||||
#include "debug.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 uint32_t hsp_service_buffer[150/4]; // implicit alignment to 4-byte memory address
|
||||||
static const uint8_t rfcomm_channel_nr = 1;
|
static const uint8_t rfcomm_channel_nr = 1;
|
||||||
static const char hsp_hs_service_name[] = "Headset Test";
|
static const char hsp_hs_service_name[] = "Headset Test";
|
||||||
static uint16_t sco_handle = 0;
|
static uint16_t sco_handle = 0;
|
||||||
|
|
||||||
static char hs_cmd_buffer[100];
|
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;
|
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
|
/* @section Audio Transfer Setup
|
||||||
*
|
*
|
||||||
* @text A pre-computed sine wave (160Hz) is used as the input audio signal. 160 Hz.
|
* @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:
|
* Tested working setups:
|
||||||
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud
|
* - Ubuntu 14 64-bit, CC2564B connected via FTDI USB-2-UART adapter, 921600 baud
|
||||||
* - Ubuntu 14 64-bit, CSR dongle
|
* - Ubuntu 14 64-bit, CSR USB dongle
|
||||||
* - OS X 10.11, CSR dongle
|
* - OS X 10.11, CSR USB dongle
|
||||||
*
|
*
|
||||||
* Broken setups:
|
* Broken setups:
|
||||||
* - OS X 10.11, CC2564B connected via FDTI USB-2-UART adapter, 921600 baud
|
* - 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 void show_usage(void){
|
||||||
static const uint8_t sine[] = {
|
uint8_t iut_address_type;
|
||||||
0, 15, 31, 46, 61, 74, 86, 97, 107, 114,
|
bd_addr_t iut_address;
|
||||||
120, 124, 126, 126, 124, 120, 114, 107, 97, 86,
|
hci_le_advertisement_address(&iut_address_type, iut_address);
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
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){
|
static void try_send_sco(void){
|
||||||
if (!sco_handle) return;
|
if (!sco_handle) return;
|
||||||
@ -137,27 +224,28 @@ static void try_send_sco(void){
|
|||||||
hci_send_sco_packet_buffer(sco_packet_length);
|
hci_send_sco_packet_buffer(sco_packet_length);
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
count++;
|
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 void sco_packet_handler(uint8_t packet_type, uint8_t * packet, uint16_t size){
|
||||||
static int count = 0;
|
static int count = 0;
|
||||||
count++;
|
count++;
|
||||||
if ((count & 15)) return;
|
if ((count & SCO_REPORT_PERIOD)) return;
|
||||||
printf("SCO packets %u\n", count);
|
printf("SCO packets %u\n", count);
|
||||||
// hexdumpf(packet, size);
|
hexdumpf(packet, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void packet_handler(uint8_t * event, uint16_t event_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();
|
try_send_sco();
|
||||||
|
|
||||||
switch (event[0]) {
|
switch (event[0]) {
|
||||||
case BTSTACK_EVENT_STATE:
|
case BTSTACK_EVENT_STATE:
|
||||||
if (event[2] != HCI_STATE_WORKING) break;
|
if (event[2] != HCI_STATE_WORKING) break;
|
||||||
printf("Working!\n");
|
printf("HCI_STATE_WORKING\n");
|
||||||
|
show_usage();
|
||||||
break;
|
break;
|
||||||
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
||||||
// printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n");
|
// printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n");
|
||||||
@ -169,6 +257,20 @@ static void packet_handler(uint8_t * event, uint16_t event_size){
|
|||||||
break;
|
break;
|
||||||
case HCI_EVENT_HSP_META:
|
case HCI_EVENT_HSP_META:
|
||||||
switch (event[2]) {
|
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:
|
case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
|
||||||
if (event[3] == 0){
|
if (event[3] == 0){
|
||||||
sco_handle = READ_BT_16(event, 4);
|
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 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 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.
|
* At the end the Bluetooth stack is started.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* LISTING_START(MainConfiguration): Setup packet handlers and audio data channel for HSP Headset */
|
/* 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[]);
|
||||||
int btstack_main(int argc, const char * argv[]){
|
int btstack_main(int argc, const char * argv[]){
|
||||||
|
l2cap_init();
|
||||||
|
rfcomm_init();
|
||||||
sdp_init();
|
sdp_init();
|
||||||
|
|
||||||
memset((uint8_t *)hsp_service_buffer, 0, sizeof(hsp_service_buffer));
|
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);
|
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);
|
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_init(rfcomm_channel_nr);
|
||||||
hsp_hs_register_packet_handler(packet_handler);
|
hsp_hs_register_packet_handler(packet_handler);
|
||||||
|
|
||||||
|
btstack_stdin_setup(stdin_process);
|
||||||
|
|
||||||
gap_set_local_name("BTstack HSP HS");
|
gap_set_local_name("BTstack HSP HS");
|
||||||
hci_discoverable_control(1);
|
hci_discoverable_control(1);
|
||||||
hci_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO);
|
hci_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO);
|
||||||
// turn on!
|
// turn on!
|
||||||
|
hci_set_class_of_device(0x240404);
|
||||||
|
|
||||||
hci_power_control(HCI_POWER_ON);
|
hci_power_control(HCI_POWER_ON);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -623,34 +623,51 @@ extern "C" {
|
|||||||
* @param subevent_code
|
* @param subevent_code
|
||||||
* @param status 0 == OK
|
* @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
|
* @format 11
|
||||||
* @param subevent_code
|
* @param subevent_code
|
||||||
* @param status 0 == OK
|
* @param status 0 == OK
|
||||||
*/
|
*/
|
||||||
#define HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE 0x02
|
#define HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE 0x04
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @format 1
|
* @format 1
|
||||||
* @param subevent_code
|
* @param subevent_code
|
||||||
*/
|
*/
|
||||||
#define HSP_SUBEVENT_RING 0x03
|
#define HSP_SUBEVENT_RING 0x05
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @format 11
|
* @format 11
|
||||||
* @param subevent_code
|
* @param subevent_code
|
||||||
* @param gain Valid range: [0,15]
|
* @param gain Valid range: [0,15]
|
||||||
*/
|
*/
|
||||||
#define HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED 0x04
|
#define HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED 0x06
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @format 11
|
* @format 11
|
||||||
* @param subevent_code
|
* @param subevent_code
|
||||||
* @param gain Valid range: [0,15]
|
* @param gain Valid range: [0,15]
|
||||||
*/
|
*/
|
||||||
#define HSP_SUBEVENT_SPEAKER_GAIN_CHANGED 0x05
|
#define HSP_SUBEVENT_SPEAKER_GAIN_CHANGED 0x07
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @format 1JV
|
* @format 1JV
|
||||||
@ -658,7 +675,7 @@ extern "C" {
|
|||||||
* @param value_length
|
* @param value_length
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
#define HSP_SUBEVENT_HS_COMMAND 0x06
|
#define HSP_SUBEVENT_HS_COMMAND 0x08
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @format 1JV
|
* @format 1JV
|
||||||
@ -666,7 +683,7 @@ extern "C" {
|
|||||||
* @param value_length
|
* @param value_length
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
#define HSP_SUBEVENT_AG_INDICATION 0x07
|
#define HSP_SUBEVENT_AG_INDICATION 0x09
|
||||||
|
|
||||||
|
|
||||||
#define HCI_EVENT_HFP_META 0xE9
|
#define HCI_EVENT_HFP_META 0xE9
|
||||||
|
@ -100,7 +100,7 @@ static int hfp_ag_get_ag_indicators_nr(hfp_connection_t * hfp_connection){
|
|||||||
return hfp_connection->ag_indicators_nr;
|
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?
|
// TODO: save only value, and value changed in the hfp_connection?
|
||||||
if (hfp_connection->ag_indicators_nr != hfp_ag_indicators_nr){
|
if (hfp_connection->ag_indicators_nr != hfp_ag_indicators_nr){
|
||||||
hfp_connection->ag_indicators_nr = hfp_ag_indicators_nr;
|
hfp_connection->ag_indicators_nr = hfp_ag_indicators_nr;
|
||||||
|
210
src/hsp_hs.c
210
src/hsp_hs.c
@ -87,22 +87,33 @@ static int hs_microphone_gain = -1;
|
|||||||
static int hs_speaker_gain = -1;
|
static int hs_speaker_gain = -1;
|
||||||
|
|
||||||
static uint8_t hs_send_button_press = 0;
|
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_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 {
|
typedef enum {
|
||||||
HSP_IDLE,
|
HSP_IDLE,
|
||||||
HSP_SDP_QUERY_RFCOMM_CHANNEL,
|
HSP_SDP_QUERY_RFCOMM_CHANNEL,
|
||||||
HSP_W4_SDP_QUERY_COMPLETE,
|
HSP_W4_SDP_QUERY_COMPLETE,
|
||||||
HSP_W4_RFCOMM_CONNECTED,
|
HSP_W4_RFCOMM_CONNECTED,
|
||||||
HSP_W4_USER_ACTION,
|
|
||||||
|
HSP_RFCOMM_CONNECTION_ESTABLISHED,
|
||||||
|
|
||||||
HSP_W2_CONNECT_SCO,
|
HSP_W2_CONNECT_SCO,
|
||||||
HSP_W4_SCO_CONNECTED,
|
HSP_W4_SCO_CONNECTED,
|
||||||
HSP_ACTIVE,
|
|
||||||
|
HSP_AUDIO_CONNECTION_ESTABLISHED,
|
||||||
|
|
||||||
HSP_W2_DISCONNECT_SCO,
|
HSP_W2_DISCONNECT_SCO,
|
||||||
HSP_W4_SCO_DISCONNECTED,
|
HSP_W4_SCO_DISCONNECTED,
|
||||||
|
|
||||||
HSP_W2_DISCONNECT_RFCOMM,
|
HSP_W2_DISCONNECT_RFCOMM,
|
||||||
HSP_W4_RFCOMM_DISCONNECTED,
|
HSP_W4_RFCOMM_DISCONNECTED,
|
||||||
|
HSP_W4_RFCOMM_DISCONNECTED_AND_RESTART,
|
||||||
HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
|
HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN
|
||||||
} hsp_state_t;
|
} 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
|
// 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){
|
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));
|
int err = rfcomm_send_internal(cid, (uint8_t*) command, strlen(command));
|
||||||
if (err){
|
if (err){
|
||||||
log_info("rfcomm_send_internal -> error 0X%02x", 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){
|
static void hsp_hs_reset_state(void){
|
||||||
hsp_state = HSP_IDLE;
|
hsp_state = HSP_IDLE;
|
||||||
|
|
||||||
rfcomm_cid = 0;
|
|
||||||
rfcomm_handle = 0;
|
|
||||||
sco_handle = 0;
|
|
||||||
|
|
||||||
hs_microphone_gain = -1;
|
hs_microphone_gain = -1;
|
||||||
hs_speaker_gain = -1;
|
hs_speaker_gain = -1;
|
||||||
|
|
||||||
hs_send_button_press = 0;
|
hs_send_button_press = 0;
|
||||||
|
wait_ok = 0;
|
||||||
hs_support_custom_indications = 0;
|
hs_support_custom_indications = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hsp_hs_init(uint8_t rfcomm_channel_nr){
|
void hsp_hs_init(uint8_t rfcomm_channel_nr){
|
||||||
// init L2CAP
|
// init L2CAP
|
||||||
l2cap_init();
|
|
||||||
l2cap_register_packet_handler(packet_handler);
|
l2cap_register_packet_handler(packet_handler);
|
||||||
|
|
||||||
rfcomm_init();
|
|
||||||
rfcomm_register_packet_handler(packet_handler);
|
rfcomm_register_packet_handler(packet_handler);
|
||||||
rfcomm_register_service_internal(NULL, rfcomm_channel_nr, 0xffff); // reserved channel, mtu limited by l2cap
|
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){
|
void hsp_hs_connect(bd_addr_t bd_addr){
|
||||||
if (hsp_state != HSP_IDLE) return;
|
if (hsp_state != HSP_IDLE) return;
|
||||||
hs_outgoing_connection = 1;
|
|
||||||
hsp_state = HSP_SDP_QUERY_RFCOMM_CHANNEL;
|
hsp_state = HSP_SDP_QUERY_RFCOMM_CHANNEL;
|
||||||
memcpy(remote, bd_addr, 6);
|
memcpy(remote, bd_addr, 6);
|
||||||
hsp_run();
|
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){
|
switch (hsp_state){
|
||||||
case HSP_ACTIVE:
|
case HSP_RFCOMM_CONNECTION_ESTABLISHED:
|
||||||
hsp_state = HSP_W4_USER_ACTION;
|
hsp_establish_audio_connection = 1;
|
||||||
hs_send_button_press = 1;
|
hsp_state = HSP_W4_SCO_CONNECTED;
|
||||||
break;
|
break;
|
||||||
case HSP_W4_RFCOMM_CONNECTED:
|
case HSP_W4_RFCOMM_CONNECTED:
|
||||||
hsp_state = HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN;
|
hsp_state = HSP_W4_CONNECTION_ESTABLISHED_TO_SHUTDOWN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
hsp_run();
|
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){
|
void hsp_hs_set_microphone_gain(uint8_t gain){
|
||||||
if (gain < 0 || gain >15) {
|
if (gain < 0 || gain >15) {
|
||||||
@ -320,14 +356,34 @@ void hsp_hs_set_speaker_gain(uint8_t gain){
|
|||||||
|
|
||||||
|
|
||||||
static void hsp_run(void){
|
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){
|
if (hs_send_button_press){
|
||||||
hs_send_button_press = 0;
|
hs_send_button_press = 0;
|
||||||
err = hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD);
|
wait_ok = 1;
|
||||||
if (err) {
|
hsp_hs_send_str_over_rfcomm(rfcomm_cid, HSP_HS_AT_CKPD);
|
||||||
hs_send_button_press = 1;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,40 +393,27 @@ static void hsp_run(void){
|
|||||||
sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_Headset_AG);
|
sdp_query_rfcomm_channel_and_name_for_uuid(remote, SDP_Headset_AG);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HSP_W2_CONNECT_SCO:
|
case HSP_AUDIO_CONNECTION_ESTABLISHED:
|
||||||
hsp_state = HSP_W4_SCO_CONNECTED;
|
case HSP_RFCOMM_CONNECTION_ESTABLISHED :
|
||||||
break;
|
|
||||||
|
|
||||||
case HSP_W2_DISCONNECT_SCO:
|
|
||||||
hsp_state = HSP_W4_SCO_DISCONNECTED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HSP_ACTIVE:
|
if (hs_microphone_gain >= 0){
|
||||||
|
|
||||||
if (hs_microphone_gain >= 0){
|
|
||||||
int gain = hs_microphone_gain;
|
|
||||||
hs_microphone_gain = -1;
|
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, gain);
|
sprintf(buffer, "%s=%d\r\n", HSP_HS_MICROPHONE_GAIN, hs_microphone_gain);
|
||||||
err = hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
|
hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
|
||||||
if (err) {
|
hs_microphone_gain = -1;
|
||||||
hs_microphone_gain = gain;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hs_speaker_gain >= 0){
|
if (hs_speaker_gain >= 0){
|
||||||
int gain = hs_speaker_gain;
|
|
||||||
hs_speaker_gain = -1;
|
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, gain);
|
sprintf(buffer, "%s=%d\r\n", HSP_HS_SPEAKER_GAIN, hs_speaker_gain);
|
||||||
err = hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
|
hsp_hs_send_str_over_rfcomm(rfcomm_cid, buffer);
|
||||||
if (err) {
|
hs_speaker_gain = -1;
|
||||||
hs_speaker_gain = gain;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case HSP_W4_RFCOMM_DISCONNECTED:
|
||||||
|
rfcomm_disconnect_internal(rfcomm_cid);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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){
|
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){
|
if (packet_type == RFCOMM_DATA_PACKET){
|
||||||
// skip over leading newline
|
// skip over leading newline
|
||||||
while (size > 0 && (packet[0] == '\n' || packet[0] == '\r')){
|
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){
|
if (strncmp((char *)packet, HSP_AG_RING, strlen(HSP_AG_RING)) == 0){
|
||||||
emit_ring_event();
|
emit_ring_event();
|
||||||
} else if (strncmp((char *)packet, HSP_AG_OK, strlen(HSP_AG_OK)) == 0){
|
} else if (strncmp((char *)packet, HSP_AG_OK, strlen(HSP_AG_OK)) == 0){
|
||||||
switch (hsp_state){
|
wait_ok = 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
} else if (strncmp((char *)packet, HSP_MICROPHONE_GAIN, strlen(HSP_MICROPHONE_GAIN)) == 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)]);
|
uint8_t gain = (uint8_t)atoi((char*)&packet[strlen(HSP_MICROPHONE_GAIN)]);
|
||||||
emit_event(HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED, 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) {
|
switch (event) {
|
||||||
case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{
|
case HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE:{
|
||||||
|
if (hsp_state < HSP_RFCOMM_CONNECTION_ESTABLISHED) return;
|
||||||
int index = 2;
|
int index = 2;
|
||||||
uint8_t status = packet[index++];
|
uint8_t status = packet[index++];
|
||||||
sco_handle = READ_BT_16(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){
|
if (status != 0){
|
||||||
log_error("(e)SCO Connection failed, status %u", status);
|
log_error("(e)SCO Connection failed, status %u", status);
|
||||||
emit_event_audio_connected(status, sco_handle);
|
emit_event_audio_connected(status, sco_handle);
|
||||||
|
hsp_state = HSP_RFCOMM_CONNECTION_ESTABLISHED ;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (link_type){
|
switch (link_type){
|
||||||
case 0x00:
|
case 0x00:
|
||||||
log_info("SCO Connection established.");
|
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,
|
" 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);
|
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
|
// forward event to app
|
||||||
hsp_hs_callback(packet, size);
|
hsp_hs_callback(packet, size);
|
||||||
|
|
||||||
hsp_state = HSP_ACTIVE;
|
hsp_state = HSP_AUDIO_CONNECTION_ESTABLISHED;
|
||||||
emit_event_audio_connected(0, sco_handle);
|
emit_event_audio_connected(status, sco_handle);
|
||||||
break;
|
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]);
|
bt_flip_addr(event_addr, &packet[2]);
|
||||||
rfcomm_cid = READ_BT_16(packet, 9);
|
rfcomm_cid = READ_BT_16(packet, 9);
|
||||||
log_info("RFCOMM channel %u requested for %s", packet[8], bd_addr_to_str(event_addr));
|
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;
|
hsp_state = HSP_W4_RFCOMM_CONNECTED;
|
||||||
|
rfcomm_accept_connection_internal(rfcomm_cid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
|
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
|
||||||
// printf("RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE packet_handler type %u, packet[0] %x\n", packet_type, packet[0]);
|
// 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)
|
// 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]) {
|
if (packet[2]) {
|
||||||
log_info("RFCOMM channel open failed, status %u", packet[2]);
|
log_info("RFCOMM channel open failed, status %u", packet[2]);
|
||||||
|
hsp_state = HSP_IDLE;
|
||||||
hsp_hs_reset_state();
|
hsp_hs_reset_state();
|
||||||
emit_event(HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE, packet[2]);
|
|
||||||
hs_outgoing_connection = 0;
|
|
||||||
} else {
|
} else {
|
||||||
// data: event(8) , len(8), status (8), address (48), handle (16), server channel(8), rfcomm_cid(16), max frame size(16)
|
// 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_handle = READ_BT_16(packet, 9);
|
||||||
rfcomm_cid = READ_BT_16(packet, 12);
|
rfcomm_cid = READ_BT_16(packet, 12);
|
||||||
mtu = READ_BT_16(packet, 14);
|
mtu = READ_BT_16(packet, 14);
|
||||||
log_info("RFCOMM channel open succeeded. New RFCOMM Channel ID %u, max frame size %u", rfcomm_cid, mtu);
|
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;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
emit_event(HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE, packet[2]);
|
||||||
break;
|
break;
|
||||||
|
case BTSTACK_EVENT_STATE:
|
||||||
case DAEMON_EVENT_HCI_PACKET_SENT:
|
case DAEMON_EVENT_HCI_PACKET_SENT:
|
||||||
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
||||||
case RFCOMM_EVENT_CREDITS:
|
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);
|
handle = READ_BT_16(packet,3);
|
||||||
if (handle == sco_handle){
|
if (handle == sco_handle){
|
||||||
sco_handle = 0;
|
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;
|
break;
|
||||||
|
}
|
||||||
|
if (handle == rfcomm_handle) {
|
||||||
|
rfcomm_handle = 0;
|
||||||
|
hsp_state = HSP_IDLE;
|
||||||
|
hsp_hs_callback(packet, size);
|
||||||
|
hsp_hs_reset_state();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RFCOMM_EVENT_CHANNEL_CLOSED:
|
case RFCOMM_EVENT_CHANNEL_CLOSED:
|
||||||
hsp_hs_reset_state();
|
hsp_hs_reset_state();
|
||||||
emit_event(HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE,0);
|
hsp_hs_callback(packet, size);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -569,18 +595,18 @@ static void handle_query_rfcomm_event(sdp_query_event_t * event, void * context)
|
|||||||
|
|
||||||
if (channel_nr > 0){
|
if (channel_nr > 0){
|
||||||
hsp_state = HSP_W4_RFCOMM_CONNECTED;
|
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);
|
rfcomm_create_channel_internal(NULL, remote, channel_nr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
hsp_hs_reset_state();
|
hsp_hs_reset_state();
|
||||||
log_info("Service not found, status %u.", ce->status);
|
log_info("Service not fou nd, status %u.", ce->status);
|
||||||
exit(0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hsp_hs_send_button_press(void){
|
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;
|
hs_send_button_press = 1;
|
||||||
hsp_run();
|
hsp_run();
|
||||||
}
|
}
|
||||||
|
28
src/hsp_hs.h
28
src/hsp_hs.h
@ -110,7 +110,27 @@ void hsp_hs_connect(bd_addr_t bd_addr);
|
|||||||
* Releases the RFCOMM channel.
|
* Releases the RFCOMM channel.
|
||||||
* @param bd_addr
|
* @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.
|
* @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);
|
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.
|
* @brief Enable custom indications.
|
||||||
|
@ -175,7 +175,7 @@ static int stdin_process(struct data_source *ds){
|
|||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
printf("Releasing audio connection.\n");
|
printf("Releasing audio connection.\n");
|
||||||
hsp_hs_disconnect(current_addr);
|
hsp_hs_disconnect();
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
printf("Setting microphone gain 0\n");
|
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:
|
case BTSTACK_EVENT_STATE:
|
||||||
if (event[2] != HCI_STATE_WORKING) break;
|
if (event[2] != HCI_STATE_WORKING) break;
|
||||||
show_usage();
|
show_usage();
|
||||||
// request loopback mode
|
|
||||||
hci_send_cmd(&hci_write_synchronous_flow_control_enable, 1);
|
|
||||||
break;
|
break;
|
||||||
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
||||||
// printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n");
|
// printf("HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user