diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/headset.c | 74 | ||||
-rw-r--r-- | audio/telephony-dummy.c | 12 | ||||
-rw-r--r-- | audio/telephony.h | 27 |
3 files changed, 111 insertions, 2 deletions
diff --git a/audio/headset.c b/audio/headset.c index 1ce4d99b..0785df91 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -62,6 +62,9 @@ #define RING_INTERVAL 3000 +/* Number of indicator events that can be queued */ +#define EV_BUF_SIZE 4 + #define BUF_SIZE 1024 #define HEADSET_GAIN_SPEAKER 'S' @@ -74,12 +77,19 @@ static struct { int er_mode; /* Event reporting mode */ int er_ind; /* Event reporting for indicators */ 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 = { .telephony_ready = FALSE, .features = 0, .er_mode = 3, .er_ind = 0, .rh = -1, + .ev_buf_active = FALSE, + .ev_buf = { { 0, 0 } }, }; static gboolean sco_hci = TRUE; @@ -204,6 +214,49 @@ static int headset_send(struct headset *hs, char *format, ...) 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) { 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); } +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) { struct headset *hs = device->headset; @@ -678,6 +748,7 @@ static struct event event_callbacks[] = { { "AT+CKPD", answer_call }, { "AT+CLIP", cli_notification }, { "AT+BTRH", response_and_hold }, + { "AT+BLDN", last_dialed_number }, { 0 } }; @@ -2013,6 +2084,9 @@ int telephony_event_ind(int index) return -EINVAL; } + if (ag.ev_buf_active) + return buffer_event(index); + return headset_send(hs, "\r\n+CIEV:%d,%d\r\n", index + 1, ag.indicators[index].val); } diff --git a/audio/telephony-dummy.c b/audio/telephony-dummy.c index 6c003066..46637b95 100644 --- a/audio/telephony-dummy.c +++ b/audio/telephony-dummy.c @@ -43,7 +43,7 @@ static gboolean events_enabled = FALSE; */ static int response_and_hold = -1; -static struct indicator indicators[] = +static struct indicator dummy_indicators[] = { { "battchg", "0-5", 5 }, { "signal", "0-5", 5 }, @@ -71,11 +71,19 @@ int telephony_response_and_hold_req(int rh) 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) { uint32_t features = 0; - telephony_ready(features, indicators, response_and_hold); + telephony_ready(features, dummy_indicators, response_and_hold); return 0; } diff --git a/audio/telephony.h b/audio/telephony.h index 4cc74ede..398f98df 100644 --- a/audio/telephony.h +++ b/audio/telephony.h @@ -23,6 +23,8 @@ */ #include <stdint.h> +#include <errno.h> +#include <glib.h> #define AG_FEATURE_THREE_WAY_CALLING 0x0001 #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_last_dialed_number(void); + 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); void telephony_exit(void); |