1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "voice_extn"
18/*#define LOG_NDEBUG 0*/
19#define LOG_NDDEBUG 0
20
21#include <errno.h>
22#include <math.h>
23#include <cutils/log.h>
24#include <cutils/str_parms.h>
25#include <sys/ioctl.h>
26#include <sound/voice_params.h>
27
28#include "audio_hw.h"
29#include "voice.h"
30#include "platform.h"
31#include "platform_api.h"
32#include "voice_extn.h"
33
34#define AUDIO_PARAMETER_KEY_VSID                "vsid"
35#define AUDIO_PARAMETER_KEY_CALL_STATE          "call_state"
36#define AUDIO_PARAMETER_KEY_AUDIO_MODE          "audio_mode"
37#define AUDIO_PARAMETER_KEY_ALL_CALL_STATES     "all_call_states"
38#define AUDIO_PARAMETER_KEY_DEVICE_MUTE         "device_mute"
39#define AUDIO_PARAMETER_KEY_DIRECTION           "direction"
40
41#define VOICE_EXTN_PARAMETER_VALUE_MAX_LEN 256
42
43#define VOICE2_VSID 0x10DC1000
44#define VOLTE_VSID  0x10C02000
45#define QCHAT_VSID  0x10803000
46#define VOWLAN_VSID 0x10002000
47#define ALL_VSID    0xFFFFFFFF
48
49/* Voice Session Indices */
50#define VOICE2_SESS_IDX    (VOICE_SESS_IDX + 1)
51#define VOLTE_SESS_IDX     (VOICE_SESS_IDX + 2)
52#define QCHAT_SESS_IDX     (VOICE_SESS_IDX + 3)
53#define VOWLAN_SESS_IDX    (VOICE_SESS_IDX + 4)
54
55/* Call States */
56#define CALL_HOLD           (BASE_CALL_STATE + 2)
57#define CALL_LOCAL_HOLD     (BASE_CALL_STATE + 3)
58
59struct pcm_config pcm_config_incall_music = {
60    .channels = 1,
61    .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
62    .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
63    .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
64    .format = PCM_FORMAT_S16_LE,
65    .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
66    .stop_threshold = INT_MAX,
67    .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
68};
69
70int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active);
71
72static bool is_valid_call_state(int call_state)
73{
74    if (call_state < CALL_INACTIVE || call_state > CALL_LOCAL_HOLD)
75        return false;
76    else
77        return true;
78}
79
80static bool is_valid_vsid(uint32_t vsid)
81{
82    if (vsid == VOICE_VSID ||
83        vsid == VOICE2_VSID ||
84        vsid == VOLTE_VSID ||
85        vsid == QCHAT_VSID ||
86        vsid == VOWLAN_VSID)
87        return true;
88    else
89        return false;
90}
91
92static audio_usecase_t voice_extn_get_usecase_for_session_idx(const int index)
93{
94    audio_usecase_t usecase_id = -1;
95
96    switch(index) {
97    case VOICE_SESS_IDX:
98        usecase_id = USECASE_VOICE_CALL;
99        break;
100
101    case VOICE2_SESS_IDX:
102        usecase_id = USECASE_VOICE2_CALL;
103        break;
104
105    case VOLTE_SESS_IDX:
106        usecase_id = USECASE_VOLTE_CALL;
107        break;
108
109    case QCHAT_SESS_IDX:
110        usecase_id = USECASE_QCHAT_CALL;
111        break;
112
113    case VOWLAN_SESS_IDX:
114        usecase_id = USECASE_VOWLAN_CALL;
115        break;
116
117    default:
118        ALOGE("%s: Invalid voice session index\n", __func__);
119    }
120
121    return usecase_id;
122}
123
124static uint32_t get_session_id_with_state(struct audio_device *adev,
125                                          int call_state)
126{
127    struct voice_session *session = NULL;
128    int i = 0;
129    uint32_t session_id = 0;
130
131    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
132        session = &adev->voice.session[i];
133        if(session->state.current == call_state){
134            session_id = session->vsid;
135            break;
136        }
137    }
138
139    return session_id;
140}
141
142static int update_calls(struct audio_device *adev)
143{
144    int i = 0;
145    audio_usecase_t usecase_id = 0;
146    enum voice_lch_mode lch_mode;
147    struct voice_session *session = NULL;
148    int fd = 0;
149    int ret = 0;
150
151    ALOGD("%s: enter:", __func__);
152
153    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
154        usecase_id = voice_extn_get_usecase_for_session_idx(i);
155        session = &adev->voice.session[i];
156        ALOGD("%s: cur_state=%d new_state=%d vsid=%x",
157              __func__, session->state.current, session->state.new, session->vsid);
158
159        switch(session->state.new)
160        {
161        case CALL_ACTIVE:
162            switch(session->state.current)
163            {
164            case CALL_INACTIVE:
165                ALOGD("%s: INACTIVE -> ACTIVE vsid:%x", __func__, session->vsid);
166                ret = voice_start_usecase(adev, usecase_id);
167                if(ret < 0) {
168                    ALOGE("%s: voice_start_usecase() failed for usecase: %d\n",
169                          __func__, usecase_id);
170                } else {
171                    session->state.current = session->state.new;
172                }
173                break;
174
175            case CALL_HOLD:
176                ALOGD("%s: HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
177                session->state.current = session->state.new;
178                break;
179
180            case CALL_LOCAL_HOLD:
181                ALOGD("%s: LOCAL_HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
182                lch_mode = VOICE_LCH_STOP;
183                if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
184                    ALOGE("LOCAL_HOLD -> ACTIVE failed");
185                } else {
186                    session->state.current = session->state.new;
187                }
188                break;
189
190            default:
191                ALOGV("%s: CALL_ACTIVE cannot be handled in state=%d vsid:%x",
192                      __func__, session->state.current, session->vsid);
193                break;
194            }
195            break;
196
197        case CALL_INACTIVE:
198            switch(session->state.current)
199            {
200            case CALL_ACTIVE:
201            case CALL_HOLD:
202            case CALL_LOCAL_HOLD:
203                ALOGD("%s: ACTIVE/HOLD/LOCAL_HOLD -> INACTIVE vsid:%x", __func__, session->vsid);
204                ret = voice_stop_usecase(adev, usecase_id);
205                if(ret < 0) {
206                    ALOGE("%s: voice_stop_usecase() failed for usecase: %d\n",
207                          __func__, usecase_id);
208                } else {
209                    session->state.current = session->state.new;
210                }
211                break;
212
213            default:
214                ALOGV("%s: CALL_INACTIVE cannot be handled in state=%d vsid:%x",
215                      __func__, session->state.current, session->vsid);
216                break;
217            }
218            break;
219
220        case CALL_HOLD:
221            switch(session->state.current)
222            {
223            case CALL_ACTIVE:
224                ALOGD("%s: CALL_ACTIVE -> HOLD vsid:%x", __func__, session->vsid);
225                session->state.current = session->state.new;
226                break;
227
228            case CALL_LOCAL_HOLD:
229                ALOGD("%s: CALL_LOCAL_HOLD -> HOLD vsid:%x", __func__, session->vsid);
230                lch_mode = VOICE_LCH_STOP;
231                if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
232                    ALOGE("LOCAL_HOLD -> HOLD failed");
233                } else {
234                    session->state.current = session->state.new;
235                }
236                break;
237
238            default:
239                ALOGV("%s: CALL_HOLD cannot be handled in state=%d vsid:%x",
240                      __func__, session->state.current, session->vsid);
241                break;
242            }
243            break;
244
245        case CALL_LOCAL_HOLD:
246            switch(session->state.current)
247            {
248            case CALL_ACTIVE:
249            case CALL_HOLD:
250                ALOGD("%s: ACTIVE/CALL_HOLD -> LOCAL_HOLD vsid:%x", __func__,
251                      session->vsid);
252                lch_mode = VOICE_LCH_START;
253                if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
254                    ALOGE("LOCAL_HOLD -> HOLD failed");
255                } else {
256                    session->state.current = session->state.new;
257                }
258                break;
259
260            default:
261                ALOGV("%s: CALL_LOCAL_HOLD cannot be handled in state=%d vsid:%x",
262                      __func__, session->state.current, session->vsid);
263                break;
264            }
265            break;
266
267        default:
268            break;
269        } //end out switch loop
270    } //end for loop
271
272    return ret;
273}
274
275static int update_call_states(struct audio_device *adev,
276                                    const uint32_t vsid, const int call_state)
277{
278    struct voice_session *session = NULL;
279    int i = 0;
280    bool is_call_active;
281
282    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
283        if (vsid == adev->voice.session[i].vsid) {
284            session = &adev->voice.session[i];
285            break;
286        }
287    }
288
289    if (session) {
290        session->state.new = call_state;
291        voice_extn_is_call_state_active(adev, &is_call_active);
292        ALOGD("%s is_call_active:%d in_call:%d, mode:%d\n",
293              __func__, is_call_active, adev->voice.in_call, adev->mode);
294        /* Dont start voice call before device routing for voice usescases has
295         * occured, otherwise voice calls will be started unintendedly on
296         * speaker.
297         */
298        if (is_call_active ||
299                (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL)) {
300            /* Device routing is not triggered for voice calls on the subsequent
301             * subs, Hence update the call states if voice call is already
302             * active on other sub.
303             */
304            update_calls(adev);
305        }
306    } else {
307        return -EINVAL;
308    }
309
310    return 0;
311
312}
313
314int voice_extn_get_active_session_id(struct audio_device *adev,
315                                     uint32_t *session_id)
316{
317    *session_id = get_session_id_with_state(adev, CALL_ACTIVE);
318    return 0;
319}
320
321int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active)
322{
323    struct voice_session *session = NULL;
324    int i = 0;
325    *is_call_active = false;
326
327    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
328        session = &adev->voice.session[i];
329        if(session->state.current != CALL_INACTIVE){
330            *is_call_active = true;
331            break;
332        }
333    }
334
335    return 0;
336}
337
338int voice_extn_is_in_call_rec_stream(struct stream_in *in, bool *in_call_rec)
339{
340    *in_call_rec = false;
341
342    if(in->source == AUDIO_SOURCE_VOICE_DOWNLINK ||
343       in->source == AUDIO_SOURCE_VOICE_UPLINK ||
344       in->source == AUDIO_SOURCE_VOICE_CALL) {
345       *in_call_rec = true;
346    }
347
348    return 0;
349}
350
351void voice_extn_init(struct audio_device *adev)
352{
353    adev->voice.session[VOICE_SESS_IDX].vsid =  VOICE_VSID;
354    adev->voice.session[VOICE2_SESS_IDX].vsid = VOICE2_VSID;
355    adev->voice.session[VOLTE_SESS_IDX].vsid =  VOLTE_VSID;
356    adev->voice.session[QCHAT_SESS_IDX].vsid =  QCHAT_VSID;
357    adev->voice.session[VOWLAN_SESS_IDX].vsid = VOWLAN_VSID;
358}
359
360int voice_extn_get_session_from_use_case(struct audio_device *adev,
361                                         const audio_usecase_t usecase_id,
362                                         struct voice_session **session)
363{
364
365    switch(usecase_id)
366    {
367    case USECASE_VOICE_CALL:
368        *session = &adev->voice.session[VOICE_SESS_IDX];
369        break;
370
371    case USECASE_VOICE2_CALL:
372        *session = &adev->voice.session[VOICE2_SESS_IDX];
373        break;
374
375    case USECASE_VOLTE_CALL:
376        *session = &adev->voice.session[VOLTE_SESS_IDX];
377        break;
378
379    case USECASE_QCHAT_CALL:
380        *session = &adev->voice.session[QCHAT_SESS_IDX];
381        break;
382
383    case USECASE_VOWLAN_CALL:
384        *session = &adev->voice.session[VOWLAN_SESS_IDX];
385        break;
386
387    default:
388        ALOGE("%s: Invalid usecase_id:%d\n", __func__, usecase_id);
389        *session = NULL;
390        return -EINVAL;
391    }
392
393    return 0;
394}
395
396int voice_extn_start_call(struct audio_device *adev)
397{
398    /* Start voice calls on sessions whose call state has been
399     * udpated.
400     */
401    ALOGV("%s: enter:", __func__);
402    return update_calls(adev);
403}
404
405int voice_extn_stop_call(struct audio_device *adev)
406{
407    int i;
408    int ret = 0;
409
410    ALOGV("%s: enter:", __func__);
411
412    /* If BT device is enabled and voice calls are ended, telephony will call
413     * set_mode(AUDIO_MODE_NORMAL) which will trigger audio policy manager to
414     * set routing with device BT A2DP profile. Hence end all voice calls when
415     * set_mode(AUDIO_MODE_NORMAL) before BT A2DP profile is selected.
416     */
417    if (adev->mode == AUDIO_MODE_NORMAL) {
418        ALOGD("%s: end all calls", __func__);
419        for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
420            adev->voice.session[i].state.new = CALL_INACTIVE;
421        }
422
423        ret = update_calls(adev);
424    }
425
426    return ret;
427}
428
429int voice_extn_set_parameters(struct audio_device *adev,
430                              struct str_parms *parms)
431{
432    char *str;
433    int value;
434    int ret = 0, err;
435    char *kv_pairs = str_parms_to_str(parms);
436    char str_value[256] = {0};
437
438    ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
439
440    err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_VSID, &value);
441    if (err >= 0) {
442        str_parms_del(parms, AUDIO_PARAMETER_KEY_VSID);
443        uint32_t vsid = value;
444        int call_state = -1;
445        err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
446        if (err >= 0) {
447            call_state = value;
448            str_parms_del(parms, AUDIO_PARAMETER_KEY_CALL_STATE);
449        } else {
450            ALOGE("%s: call_state key not found", __func__);
451            ret = -EINVAL;
452            goto done;
453        }
454
455        if (is_valid_vsid(vsid) && is_valid_call_state(call_state)) {
456            ret = update_call_states(adev, vsid, call_state);
457        } else {
458            ALOGE("%s: invalid vsid:%x or call_state:%d",
459                  __func__, vsid, call_state);
460            ret = -EINVAL;
461            goto done;
462        }
463    }
464
465    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE, str_value,
466                            sizeof(str_value));
467    if (err >= 0) {
468        str_parms_del(parms, AUDIO_PARAMETER_KEY_DEVICE_MUTE);
469        bool mute = false;
470
471        if (!strncmp("true", str_value, sizeof("true"))) {
472            mute = true;
473        }
474
475        err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_DIRECTION, str_value,
476                                sizeof(str_value));
477        if (err >= 0) {
478            str_parms_del(parms, AUDIO_PARAMETER_KEY_DIRECTION);
479        } else {
480            ALOGE("%s: direction key not found", __func__);
481            ret = -EINVAL;
482            goto done;
483        }
484
485        ret = platform_set_device_mute(adev->platform, mute, str_value);
486        if (ret != 0) {
487            ALOGE("%s: Failed to set mute err:%d", __func__, ret);
488            ret = -EINVAL;
489            goto done;
490        }
491    }
492
493done:
494    ALOGV("%s: exit with code(%d)", __func__, ret);
495    free(kv_pairs);
496    return ret;
497}
498
499static int get_all_call_states_str(const struct audio_device *adev,
500                            char *value)
501{
502    int ret = 0;
503    char *cur_ptr = value;
504    int i, len=0;
505
506    for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
507        snprintf(cur_ptr, VOICE_EXTN_PARAMETER_VALUE_MAX_LEN - len,
508                 "%d:%d,",adev->voice.session[i].vsid,
509                 adev->voice.session[i].state.current);
510        len = strlen(cur_ptr);
511        cur_ptr = cur_ptr + len;
512    }
513    ALOGV("%s:value=%s", __func__, value);
514    return ret;
515}
516
517void voice_extn_get_parameters(const struct audio_device *adev,
518                               struct str_parms *query,
519                               struct str_parms *reply)
520{
521    int ret;
522    char value[VOICE_EXTN_PARAMETER_VALUE_MAX_LEN] = {0};
523    char *str = str_parms_to_str(query);
524
525    ALOGV_IF(str != NULL, "%s: enter %s", __func__, str);
526    free(str);
527
528    ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_AUDIO_MODE, value,
529                            sizeof(value));
530    if (ret >= 0) {
531        str_parms_add_int(reply, AUDIO_PARAMETER_KEY_AUDIO_MODE, adev->mode);
532    }
533
534    ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_ALL_CALL_STATES,
535                            value, sizeof(value));
536    if (ret >= 0) {
537        ret = get_all_call_states_str(adev, value);
538        if (ret) {
539            ALOGE("%s: Error fetching call states, err:%d", __func__, ret);
540            return;
541        }
542        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_ALL_CALL_STATES, value);
543    }
544
545    str = str_parms_to_str(reply);
546    ALOGV_IF(str != NULL, "%s: exit: returns \"%s\"", __func__, str);
547    free(str);
548}
549
550#ifdef INCALL_MUSIC_ENABLED
551int voice_extn_check_and_set_incall_music_usecase(struct audio_device *adev,
552                                                  struct stream_out *out)
553{
554    uint32_t session_id = 0;
555
556    session_id = get_session_id_with_state(adev, CALL_LOCAL_HOLD);
557    if (session_id == VOICE_VSID) {
558        out->usecase = USECASE_INCALL_MUSIC_UPLINK;
559    } else if (session_id == VOICE2_VSID) {
560        out->usecase = USECASE_INCALL_MUSIC_UPLINK2;
561    } else {
562        ALOGE("%s: Invalid session id %x", __func__, session_id);
563        return -EINVAL;
564    }
565
566    out->config = pcm_config_incall_music;
567    out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
568    out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
569
570    return 0;
571}
572#endif
573
574