mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-29 15:14:31 +08:00
Implement last number dialed (AT+BLDN) support
This commit is contained in:
parent
a3634219a1
commit
1b971b060b
@ -62,6 +62,9 @@
|
|||||||
|
|
||||||
#define RING_INTERVAL 3000
|
#define RING_INTERVAL 3000
|
||||||
|
|
||||||
|
/* Number of indicator events that can be queued */
|
||||||
|
#define EV_BUF_SIZE 4
|
||||||
|
|
||||||
#define BUF_SIZE 1024
|
#define BUF_SIZE 1024
|
||||||
|
|
||||||
#define HEADSET_GAIN_SPEAKER 'S'
|
#define HEADSET_GAIN_SPEAKER 'S'
|
||||||
@ -74,12 +77,19 @@ static struct {
|
|||||||
int er_mode; /* Event reporting mode */
|
int er_mode; /* Event reporting mode */
|
||||||
int er_ind; /* Event reporting for indicators */
|
int er_ind; /* Event reporting for indicators */
|
||||||
int rh; /* Response and Hold state */
|
int rh; /* Response and Hold state */
|
||||||
|
gboolean ev_buf_active; /* Buffer indicator events */
|
||||||
|
struct {
|
||||||
|
int index; /* HFP indicator index */
|
||||||
|
int val; /* new indicator value */
|
||||||
|
} ev_buf[EV_BUF_SIZE]; /* Indicator event buffer */
|
||||||
} ag = {
|
} ag = {
|
||||||
.telephony_ready = FALSE,
|
.telephony_ready = FALSE,
|
||||||
.features = 0,
|
.features = 0,
|
||||||
.er_mode = 3,
|
.er_mode = 3,
|
||||||
.er_ind = 0,
|
.er_ind = 0,
|
||||||
.rh = -1,
|
.rh = -1,
|
||||||
|
.ev_buf_active = FALSE,
|
||||||
|
.ev_buf = { { 0, 0 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean sco_hci = TRUE;
|
static gboolean sco_hci = TRUE;
|
||||||
@ -204,6 +214,49 @@ static int headset_send(struct headset *hs, char *format, ...)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int buffer_event(int index)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < EV_BUF_SIZE; i++) {
|
||||||
|
if (ag.ev_buf[i].index == 0) {
|
||||||
|
ag.ev_buf[i].index = index + 1;
|
||||||
|
ag.ev_buf[i].val = ag.indicators[index].val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error("No space in event buffer");
|
||||||
|
return -ENOSPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int flush_events(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct headset *hs;
|
||||||
|
|
||||||
|
if (!active_telephony_device)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
hs = active_telephony_device->headset;
|
||||||
|
|
||||||
|
for (i = 0; i < EV_BUF_SIZE; i++) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (ag.ev_buf[i].index == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = headset_send(hs, "\r\n+CIEV:%d,%d\r\n",
|
||||||
|
ag.ev_buf[i].index, ag.ev_buf[i].val);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ag.ev_buf[i].index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int supported_features(struct audio_device *device, const char *buf)
|
static int supported_features(struct audio_device *device, const char *buf)
|
||||||
{
|
{
|
||||||
struct headset *hs = device->headset;
|
struct headset *hs = device->headset;
|
||||||
@ -622,6 +675,23 @@ static int response_and_hold(struct audio_device *device, const char *buf)
|
|||||||
return headset_send(hs, "\r\nOK\n\r", ag.rh);
|
return headset_send(hs, "\r\nOK\n\r", ag.rh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int last_dialed_number(struct audio_device *device, const char *buf)
|
||||||
|
{
|
||||||
|
struct headset *hs = device->headset;
|
||||||
|
|
||||||
|
ag.ev_buf_active = TRUE;
|
||||||
|
|
||||||
|
if (telephony_last_dialed_number() < 0) {
|
||||||
|
headset_send(hs, "\r\nERROR\r\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
flush_events();
|
||||||
|
ag.ev_buf_active = FALSE;
|
||||||
|
|
||||||
|
return headset_send(hs, "\r\nOK\n\r", ag.rh);
|
||||||
|
}
|
||||||
|
|
||||||
static int signal_gain_setting(struct audio_device *device, const char *buf)
|
static int signal_gain_setting(struct audio_device *device, const char *buf)
|
||||||
{
|
{
|
||||||
struct headset *hs = device->headset;
|
struct headset *hs = device->headset;
|
||||||
@ -678,6 +748,7 @@ static struct event event_callbacks[] = {
|
|||||||
{ "AT+CKPD", answer_call },
|
{ "AT+CKPD", answer_call },
|
||||||
{ "AT+CLIP", cli_notification },
|
{ "AT+CLIP", cli_notification },
|
||||||
{ "AT+BTRH", response_and_hold },
|
{ "AT+BTRH", response_and_hold },
|
||||||
|
{ "AT+BLDN", last_dialed_number },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2013,6 +2084,9 @@ int telephony_event_ind(int index)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ag.ev_buf_active)
|
||||||
|
return buffer_event(index);
|
||||||
|
|
||||||
return headset_send(hs, "\r\n+CIEV:%d,%d\r\n", index + 1,
|
return headset_send(hs, "\r\n+CIEV:%d,%d\r\n", index + 1,
|
||||||
ag.indicators[index].val);
|
ag.indicators[index].val);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ static gboolean events_enabled = FALSE;
|
|||||||
*/
|
*/
|
||||||
static int response_and_hold = -1;
|
static int response_and_hold = -1;
|
||||||
|
|
||||||
static struct indicator indicators[] =
|
static struct indicator dummy_indicators[] =
|
||||||
{
|
{
|
||||||
{ "battchg", "0-5", 5 },
|
{ "battchg", "0-5", 5 },
|
||||||
{ "signal", "0-5", 5 },
|
{ "signal", "0-5", 5 },
|
||||||
@ -71,11 +71,19 @@ int telephony_response_and_hold_req(int rh)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int telephony_last_dialed_number(void)
|
||||||
|
{
|
||||||
|
/* Notify outgoing call set-up successfully initiated */
|
||||||
|
telephony_update_indicator(dummy_indicators, "callsetup", 2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int telephony_init(void)
|
int telephony_init(void)
|
||||||
{
|
{
|
||||||
uint32_t features = 0;
|
uint32_t features = 0;
|
||||||
|
|
||||||
telephony_ready(features, indicators, response_and_hold);
|
telephony_ready(features, dummy_indicators, response_and_hold);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
#define AG_FEATURE_THREE_WAY_CALLING 0x0001
|
#define AG_FEATURE_THREE_WAY_CALLING 0x0001
|
||||||
#define AG_FEATURE_EC_ANDOR_NR 0x0002
|
#define AG_FEATURE_EC_ANDOR_NR 0x0002
|
||||||
@ -48,7 +50,32 @@ int telephony_response_and_hold_req(int rh);
|
|||||||
|
|
||||||
int telephony_response_and_hold_ind(int rh);
|
int telephony_response_and_hold_ind(int rh);
|
||||||
|
|
||||||
|
int telephony_last_dialed_number(void);
|
||||||
|
|
||||||
int telephony_ready(uint32_t features, struct indicator *indicators, int rh);
|
int telephony_ready(uint32_t features, struct indicator *indicators, int rh);
|
||||||
|
|
||||||
|
/* Helper function for quick indicator updates */
|
||||||
|
static inline int telephony_update_indicator(struct indicator *indicators,
|
||||||
|
const char *desc,
|
||||||
|
int new_val)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct indicator *ind = NULL;
|
||||||
|
|
||||||
|
for (i = 0; indicators[i].desc != NULL; i++) {
|
||||||
|
if (g_str_equal(indicators[i].desc, desc)) {
|
||||||
|
ind = &indicators[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ind)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
ind->val = new_val;
|
||||||
|
|
||||||
|
return telephony_event_ind(i);
|
||||||
|
}
|
||||||
|
|
||||||
int telephony_init(void);
|
int telephony_init(void);
|
||||||
void telephony_exit(void);
|
void telephony_exit(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user