| /* |
| * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * Changes from Qualcomm Innovation Center are provided under the following license: |
| * |
| * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted (subject to the limitations in the |
| * disclaimer below) provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * |
| * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE |
| * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT |
| * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
| * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef STREAM_H_ |
| #define STREAM_H_ |
| |
| #include "PalDefs.h" |
| #include <algorithm> |
| #include <vector> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <math.h> |
| #include <memory> |
| #include <mutex> |
| #include <exception> |
| #include <semaphore.h> |
| #include <errno.h> |
| #ifdef LINUX_ENABLED |
| #include <condition_variable> |
| #endif |
| #include "PalCommon.h" |
| |
| typedef enum { |
| DATA_MODE_SHMEM = 0, |
| DATA_MODE_BLOCKING , |
| DATA_MODE_NONBLOCKING |
| } dataFlags; |
| |
| typedef enum { |
| STREAM_IDLE = 0, |
| STREAM_INIT, |
| STREAM_OPENED, |
| STREAM_STARTED, |
| STREAM_PAUSED, |
| STREAM_SUSPENDED, |
| STREAM_STOPPED |
| } stream_state_t; |
| |
| #define BUF_SIZE_PLAYBACK 1024 |
| #define BUF_SIZE_CAPTURE 960 |
| #define NO_OF_BUF 4 |
| #define MUTE_TAG 0 |
| #define UNMUTE_TAG 1 |
| #define PAUSE_TAG 2 |
| #define RESUME_TAG 3 |
| #define MFC_SR_8K 4 |
| #define MFC_SR_16K 5 |
| #define MFC_SR_32K 6 |
| #define MFC_SR_44K 7 |
| #define MFC_SR_48K 8 |
| #define MFC_SR_96K 9 |
| #define MFC_SR_192K 10 |
| #define MFC_SR_384K 11 |
| #define ECNS_ON_TAG 12 |
| #define ECNS_OFF_TAG 13 |
| #define EC_ON_TAG 14 |
| #define NS_ON_TAG 15 |
| #define CHS_1 16 |
| #define CHS_2 17 |
| #define CHS_3 18 |
| #define CHS_4 19 |
| #define CHS_5 20 |
| #define CHS_6 21 |
| #define CHS_7 22 |
| #define CHS_8 23 |
| #define BW_16 24 |
| #define BW_24 25 |
| #define BW_32 26 |
| #define TTY_MODE 27 |
| #define VOICE_SLOW_TALK_OFF 28 |
| #define VOICE_SLOW_TALK_ON 29 |
| #define VOICE_VOLUME_BOOST 30 |
| #define SPKR_PROT_ENABLE 31 |
| #define INCALL_RECORD_UPLINK 32 |
| #define INCALL_RECORD_DOWNLINK 33 |
| #define INCALL_RECORD_UPLINK_DOWNLINK_MONO 34 |
| #define INCALL_RECORD_UPLINK_DOWNLINK_STEREO 35 |
| #define SPKR_VI_ENABLE 36 |
| #define VOICE_HD_VOICE 37 |
| #define LPI_LOGGING_ON 38 |
| #define LPI_LOGGING_OFF 39 |
| #define DEVICE_MUTE 40 |
| #define DEVICE_UNMUTE 41 |
| #define CHANNEL_INFO 42 |
| #define CHARGE_CONCURRENCY_ON_TAG 43 |
| #define CHARGE_CONCURRENCY_OFF_TAG 44 |
| #define DEVICEPP_MUTE 45 |
| #define DEVICEPP_UNMUTE 46 |
| #define ORIENTATION_TAG 47 |
| #define HANDSET_PROT_ENABLE 48 |
| #define MUX_DEMUX_CHANNELS 49 |
| |
| /* This sleep is added to give time to kernel and |
| * spf to recover from SSR so that audio-hal will |
| * not continously try to open a session if it fails |
| * during SSR. |
| */ |
| #define SSR_RECOVERY 10000 |
| |
| /* Soft pause has to wait for ramp period to ensure volume stepping finishes. |
| * This period of time was previously consumed in elite before acknowleging |
| * pause completion. But it's not the case in Gecko. |
| * FIXME: load the ramp period config from acdb. |
| */ |
| #define VOLUME_RAMP_PERIOD (200*1000) |
| |
| /* |
| * The sleep is required for mute to ramp down. |
| */ |
| #define MUTE_RAMP_PERIOD (40*1000) |
| |
| class Device; |
| class ResourceManager; |
| class Session; |
| |
| class Stream |
| { |
| protected: |
| uint32_t mNoOfDevices; |
| std::vector <std::shared_ptr<Device>> mDevices; // current running devices |
| std::vector <std::shared_ptr<Device>> mPalDevices; // pal devices set from client, which may differ from mDevices |
| Session* session; |
| struct pal_stream_attributes* mStreamAttr; |
| int mGainLevel; |
| int mOrientation = 0; |
| std::mutex mStreamMutex; |
| static std::mutex mBaseStreamMutex; //TBD change this. as having a single static mutex for all instances of Stream is incorrect. Replace |
| static std::shared_ptr<ResourceManager> rm; |
| struct modifier_kv *mModifiers; |
| uint32_t mNoOfModifiers; |
| std::string mStreamSelector; |
| std::string mDevPPSelector; |
| size_t inBufSize = BUF_SIZE_CAPTURE; |
| size_t outBufSize = BUF_SIZE_PLAYBACK; |
| size_t inBufCount = NO_OF_BUF; |
| size_t outBufCount = NO_OF_BUF; |
| size_t outMaxMetadataSz; |
| size_t inMaxMetadataSz; |
| stream_state_t currentState; |
| stream_state_t cachedState; |
| uint32_t mInstanceID = 0; |
| static std::condition_variable pauseCV; |
| static std::mutex pauseMutex; |
| bool mutexLockedbyRm = false; |
| bool mDutyCycleEnable = false; |
| sem_t mInUse; |
| int connectToDefaultDevice(Stream* streamHandle, uint32_t dir); |
| public: |
| virtual ~Stream() {}; |
| struct pal_volume_data* mVolumeData = NULL; |
| pal_stream_callback streamCb; |
| uint64_t cookie; |
| bool isPaused = false; |
| bool a2dpMuted = false; |
| bool a2dpPaused = false; |
| bool force_nlpi_vote = false; |
| bool isMMap = false; |
| std::vector<pal_device_id_t> suspendedDevIds; |
| virtual int32_t open() = 0; |
| virtual int32_t close() = 0; |
| virtual int32_t start() = 0; |
| virtual int32_t stop() = 0; |
| virtual int32_t prepare() = 0; |
| virtual int32_t drain(pal_drain_type_t type __unused) {return 0;} |
| virtual int32_t setStreamAttributes(struct pal_stream_attributes *sattr) = 0; |
| virtual int32_t setVolume(struct pal_volume_data *volume) = 0; |
| virtual int32_t mute(bool state) = 0; |
| virtual int32_t mute_l(bool state) = 0; |
| virtual int32_t pause() = 0; |
| virtual int32_t pause_l() = 0; |
| virtual int32_t resume() = 0; |
| virtual int32_t resume_l() = 0; |
| virtual int32_t flush() {return 0;} |
| virtual int32_t suspend() {return 0;} |
| virtual int32_t read(struct pal_buffer *buf) = 0; |
| |
| virtual int32_t addRemoveEffect(pal_audio_effect_t effect, bool enable) = 0; //TBD: make this non virtual and prrovide implementation as StreamPCM and StreamCompressed are doing the same things |
| virtual int32_t setParameters(uint32_t param_id, void *payload) = 0; |
| virtual int32_t write(struct pal_buffer *buf) = 0; //TBD: make this non virtual and prrovide implementation as StreamPCM and StreamCompressed are doing the same things |
| virtual int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) = 0; |
| virtual int32_t getCallBack(pal_stream_callback *cb) = 0; |
| virtual int32_t getParameters(uint32_t param_id, void **payload) = 0; |
| virtual int32_t setECRef(std::shared_ptr<Device> dev, bool is_enable) = 0; |
| virtual int32_t setECRef_l(std::shared_ptr<Device> dev, bool is_enable) = 0; |
| virtual int32_t ssrDownHandler() = 0; |
| virtual int32_t ssrUpHandler() = 0; |
| virtual int32_t createMmapBuffer(int32_t min_size_frames __unused, |
| struct pal_mmap_buffer *info __unused) {return -EINVAL;} |
| virtual int32_t GetMmapPosition(struct pal_mmap_position *position __unused) {return -EINVAL;} |
| virtual int32_t getTagsWithModuleInfo(size_t *size __unused, uint8_t *payload __unused) {return -EINVAL;}; |
| int32_t getStreamAttributes(struct pal_stream_attributes *sattr); |
| int32_t getModifiers(struct modifier_kv *modifiers,uint32_t *noOfModifiers); |
| const std::string& getStreamSelector() const; |
| const std::string& getDevicePPSelector() const; |
| int32_t getStreamType(pal_stream_type_t* streamType); |
| int32_t getStreamDirection(pal_stream_direction_t *dir); |
| uint32_t getRenderLatency(); |
| uint32_t getLatency(); |
| int32_t getAssociatedDevices(std::vector <std::shared_ptr<Device>> &adevices); |
| int32_t getPalDevices(std::vector <std::shared_ptr<Device>> &PalDevices); |
| void clearOutPalDevices(Stream *streamHandle); |
| void addPalDevice(Stream* streamHandle, struct pal_device *dattr); |
| int32_t getSoundCardId(); |
| int32_t getAssociatedSession(Session** session); |
| int32_t setBufInfo(pal_buffer_config *in_buffer_config, |
| pal_buffer_config *out_buffer_config); |
| int32_t getBufInfo(size_t *in_buf_size, size_t *in_buf_count, |
| size_t *out_buf_size, size_t *out_buf_count); |
| int32_t getMaxMetadataSz(size_t *in_max_metadata_sz, size_t *out_max_metadata_sz); |
| int32_t getVolumeData(struct pal_volume_data *vData); |
| void setGainLevel(int level) { mGainLevel = level; }; |
| int getGainLevel() { return mGainLevel; }; |
| void setDutyCycleEnable(bool enable) { mDutyCycleEnable = enable; }; |
| bool getDutyCycleEnable() { return mDutyCycleEnable; }; |
| void setOrientation(int orientation) { mOrientation = orientation; }; |
| int getOrientation() { return mOrientation; }; |
| /* static so that this method can be accessed wihtout object */ |
| static Stream* create(struct pal_stream_attributes *sattr, struct pal_device *dattr, |
| uint32_t no_of_devices, struct modifier_kv *modifiers, uint32_t no_of_modifiers); |
| bool isStreamAudioOutFmtSupported(pal_audio_fmt_t format); |
| int32_t getTimestamp(struct pal_session_time *stime); |
| int32_t handleBTDeviceNotReady(bool& a2dpSuspend); |
| int disconnectStreamDevice(Stream* streamHandle, pal_device_id_t dev_id); |
| int disconnectStreamDevice_l(Stream* streamHandle, pal_device_id_t dev_id); |
| int connectStreamDevice(Stream* streamHandle, struct pal_device *dattr); |
| int connectStreamDevice_l(Stream* streamHandle, struct pal_device *dattr); |
| int switchDevice(Stream* streamHandle, uint32_t no_of_devices, struct pal_device *deviceArray); |
| bool isGKVMatch(pal_key_vector_t* gkv); |
| int32_t getEffectParameters(void *effect_query, size_t *payload_size); |
| uint32_t getInstanceId() { return mInstanceID; } |
| inline void setInstanceId(uint32_t sid) { mInstanceID = sid; } |
| int initStreamSmph(); |
| int deinitStreamSmph(); |
| int postStreamSmph(); |
| int waitStreamSmph(); |
| bool checkStreamMatch(pal_device_id_t pal_device_id, |
| pal_stream_type_t pal_stream_type); |
| int32_t getEffectParameters(void *effect_query); |
| int32_t setEffectParameters(void *effect_param); |
| int32_t rwACDBParameters(void *payload, uint32_t sampleRate, |
| bool isParamWrite); |
| stream_state_t getCurState() { return currentState; } |
| bool isActive() { return currentState == STREAM_STARTED; } |
| bool isAlive() { return currentState != STREAM_IDLE; } |
| bool isA2dpMuted() { return a2dpMuted; } |
| /* Detection stream related APIs */ |
| virtual int32_t Resume() { return 0; } |
| virtual int32_t Pause() { return 0; } |
| virtual int32_t EnableLPI(bool is_enable) { return 0; } |
| virtual int32_t HandleConcurrentStream(bool active) { return 0; } |
| virtual int32_t DisconnectDevice(pal_device_id_t device_id) { return 0; } |
| virtual int32_t ConnectDevice(pal_device_id_t device_id) { return 0; } |
| static void handleSoftPauseCallBack(uint64_t hdl, uint32_t event_id, void *data, |
| uint32_t event_size, uint32_t miid); |
| static void handleStreamException(struct pal_stream_attributes *attributes, |
| pal_stream_callback cb, uint64_t cookie); |
| void lockStreamMutex() { |
| mStreamMutex.lock(); |
| mutexLockedbyRm = true; |
| }; |
| void unlockStreamMutex() { |
| mutexLockedbyRm = false; |
| mStreamMutex.unlock(); |
| }; |
| bool isMutexLockedbyRm() { return mutexLockedbyRm; } |
| /* GetPalDevice only applies to Sound Trigger streams */ |
| std::shared_ptr<Device> GetPalDevice(Stream *streamHandle, pal_device_id_t dev_id); |
| void setCachedState(stream_state_t state); |
| }; |
| |
| class StreamNonTunnel : public Stream |
| { |
| public: |
| StreamNonTunnel(const struct pal_stream_attributes *sattr, struct pal_device *dattr, |
| const uint32_t no_of_devices, |
| const struct modifier_kv *modifiers, const uint32_t no_of_modifiers, |
| const std::shared_ptr<ResourceManager> rm); |
| virtual ~StreamNonTunnel(); |
| int32_t open() override; |
| int32_t close() override; |
| int32_t start() override; |
| int32_t stop() override; |
| int32_t prepare() override; |
| int32_t setStreamAttributes( struct pal_stream_attributes *sattr __unused) {return 0;}; |
| int32_t setVolume( struct pal_volume_data *volume __unused) {return 0;}; |
| int32_t mute(bool state __unused) {return 0;}; |
| int32_t mute_l(bool state __unused) {return 0;}; |
| int32_t pause() {return 0;}; |
| int32_t pause_l() {return 0;}; |
| int32_t resume() {return 0;}; |
| int32_t resume_l() {return 0;}; |
| int32_t drain(pal_drain_type_t type) override; |
| int32_t flush(); |
| int32_t suspend() override; |
| int32_t getTagsWithModuleInfo(size_t *size , uint8_t *payload) override; |
| int32_t setBufInfo(size_t *in_buf_size, size_t in_buf_count, |
| size_t *out_buf_size, size_t out_buf_count); |
| |
| int32_t addRemoveEffect(pal_audio_effect_t effect __unused, bool enable __unused) {return 0;}; |
| int32_t read(struct pal_buffer *buf) override; |
| int32_t write(struct pal_buffer *buf) override; |
| int32_t registerCallBack(pal_stream_callback cb, uint64_t cookie) override; |
| int32_t getCallBack(pal_stream_callback *cb) override; |
| int32_t getParameters(uint32_t param_id, void **payload) override; |
| int32_t setParameters(uint32_t param_id, void *payload) override; |
| static int32_t isSampleRateSupported(uint32_t sampleRate); |
| static int32_t isChannelSupported(uint32_t numChannels); |
| static int32_t isBitWidthSupported(uint32_t bitWidth); |
| int32_t setECRef(std::shared_ptr<Device> dev __unused, bool is_enable __unused) {return 0;}; |
| int32_t setECRef_l(std::shared_ptr<Device> dev __unused, bool is_enable __unused) {return 0;}; |
| int32_t ssrDownHandler() override; |
| int32_t ssrUpHandler() override; |
| private: |
| /*This notifies that the system went through/is in a ssr*/ |
| bool ssrInNTMode; |
| }; |
| |
| #endif//STREAM_H_ |