⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ag_athandler.c

📁 bluetooth audio gateway
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "ag_private.h"
#include "ag_parse.h"
#include "ag.h"

#include <ctype.h>
#include <message.h>
#include <print.h>
#include <stdlib.h>
#include <string.h>


/* Hands-free AG supported featues */
typedef enum {
    three_way_calls,
    echo_cancel,
    voice_recog,
    in_band_ring,
    voice_tag
} hf_features_t;


/*
    getHfSupportedFeature

    Return true if a feature is supported, false otherwise
*/
static uint16 getHfSupportedFeature(hf_features_t feature)
{
    /* 
        Check if this is supported by the AG. 
        Only the 5 LSB of the LSW are valid so mask out the rest.
    */
    uint16 support = (AGState.hfAgSupportedFeatures & 0x001f);
    
    /* 
        The enum above defines the position of this feature in the 
        service record so shift by that many and mask out the other bits 
    */
    support = (support >> (uint16)feature) & 0x01;

    return support;
}

     
/*
    volumeCmdReceived

    Check the volume command is within the allowed range and pass it
    on to the AG app, otherwise send an error
*/
static void volumeCmdReceived(const BD_ADDR_T *addr, uint16 gain)
{
    /* 
        Check the value is within the allowed range (since it is an 
        unsigned value only check the upper limit)
    */
    if (gain <= 15)
    {
        /* Ack receiving the cmd */
        agSendOk();
        
        /* Pass the speaker volume to the app */
        agVolumeChangeInd(*addr, gain);        
    }
    else
    {
        /* Volume gain not within the range allowed by the profile */
        agSendError();
    }
}


/*
    microphoneCmdReceived

    Check gain is within the allowed range and pass it up to the app
    else send back an error
*/
static void microphoneCmdReceived(const BD_ADDR_T *addr, uint16 gain)
{
    /* gain is unsigned so will always be >= zero */
    if (gain <= 15)
    {
        /* ack the cmd */
        agSendOk();
        
        /* send a message up to the driver app */
        agMicChangeInd(*addr, gain);                
    }
    else
    {
        /* Microphone gain not within the range allowed by the profile */
        agSendError();
    }
}


/*
    handleUnrecognised

    Could not parse the data so pass it on to client to have a go at it.
*/
void handleUnrecognised(const uint8 *data, uint16 length, const BD_ADDR_T *addr)
{
    /*
        The message does not contain a recognised AT command or response.
        Pass the data on to the application to have a go at 
    */

    {
        uint16 i = 0;
        PRINT(("pass data to client len 0x%x\n", length));
        for(i=0; i<length; i++)
        {
            PRINT(("%c ", data[i]));
        }
        PRINT(("\n"));
    }

    /* Send ERROR to indicate unrecognised AT command */
    agSendError();

    /* pass this on to the interface to deal with it */
    handleUnparsedData(agGetConnectionHandle(addr), length, data);
}


/*
    handleRing

    Unsolicited ring code received
*/
void handleRing(const BD_ADDR_T *addr)
{
    /* AG should not be receiving ring cmds so send an error */
    agSendErrorToClient(AgErrorUnexpectedPrimitive, addr);
    agSendError();
}


/*
    handleOK

    OK response received
*/
void handleOK(const BD_ADDR_T * addr)
{
    /* Ignore for now */

    /* keep the compiler happy */
    addr = addr;
}


/*
    handleError

    Error response received
*/
void handleError(const BD_ADDR_T * addr)
{
    /* Ignore for now */

    /* keep the compiler happy */
    addr = addr;
}


/*
    handleMicrophoneGain

    Microphone gain cmd (AT+VGM) received
*/
void handleMicrophoneGain(const BD_ADDR_T * addr, const struct MicrophoneGain *s)
{    
    if (agIsCurrentlyHandsFree())
    {
        /* HFP does not need a SCO to send or receive mic gain cmds */
        microphoneCmdReceived(addr, s->gain);
    }
    else
    {
        /* These should only be sent when there is a SCO up for the HSP */
        if (agScoConnectedQuery())            
            microphoneCmdReceived(addr, s->gain);
        else
            agSendError();    
    }
}


/*
    handleSpeakerGain

    Speaker gain cmd (AT+VGS) received
*/
void handleSpeakerGain(const BD_ADDR_T * addr, const struct SpeakerGain *s)
{    
    /* Process volume cmds depending on the type of device we're talking to */
    if (agIsCurrentlyHandsFree())
    {
        /* HFP does not need SCO to send and receive vol cmds */
        volumeCmdReceived(addr, s->gain);
    }
    else
    {
        /* HSP Vol cmds not allowed without a SCO being up */
        if (agScoConnectedQuery())
            volumeCmdReceived(addr, s->gain);
        else
            agSendError();
    }
}


/*
    handleButtonPress

    Handle the receipt of a buttom press AT commdand (AT+CKPD). 
    Currently only values of '200' are supported 
*/
void handleButtonPress(const BD_ADDR_T * addr, const struct ButtonPress *s)
{
    /* keep the compiler happy */
    addr = addr;
    
    if (s->button == 200)
    {        
        /* acknowledge receipt of AT cmd */        
        agSendOk();
    
        /* button press */
        agButtonPressInd(*addr);
    }
    else
    {
        agSendError();
    }
}


/*
    handleCustomButtonPress

    The AT command specification defines a number of values that can be
    sent as arguments to the AT+CKPD command. By being able to handle these
    correctly the AG can interoperate with more devices.

    "AT+CKPD="e"  -  connection end (i.e. reject call)    
    "AT+CKPD="q"  -  quiet/ mute
    "AT+CKPD="r"  -  recall last number
*/  
void handleCustomButtonPress(const BD_ADDR_T * addr, const struct CustomButtonPress *s)
{        
    if (s->button.length && (s->button.data[0] == 'e' || s->button.data[0] == 'E'))
    {
        /* acknowledge receipt of AT cmd */
        agSendOk();

        /* stop sending ring indications to the headset */
        agStopRings();

        /* 
            To be consistent with the rest of the AG implementation the AG
            will send the external driver an indication that the call has been
            rejected but it will not drop the RFCOMM connection (if possible it
            will put it in sniff or park). The driver can then decide whether to 
            disconnect the RFCOMM connection. If there is an ongoing call 
            then disconnect the call.
        */                
        if (agScoConnectedQuery())
        {
            agButtonPressInd(*addr);
        }
        else
        {
            /* tell the interface the call has been rejected */
            handleCallAnsweredInd(agGetConnectionHandle(addr), 0);
        }        
    }
    else
    {        
        /* Unrecognised command so send an ERROR to ack receiving it */
        agSendError();
    }
}


/*
    handleIndicatorDescriptionRequest

    Request for a description of the supported indicators
    AT cmd: AT+CIND=?
*/
void handleIndicatorDescriptionRequest(const BD_ADDR_T * addr)
{
    /* keep the compiler happy */
    addr = addr;
    
    /* Respond with the supported indicators */    
    agSendCindTestResponse();        

    /* acknowledge the command */
    agSendOk();
}


/*
    handleIndicatorStatusRequest
    
    Request for the current state of the supported indicators to be returned
    AT cmd: AT+CIND?
*/
void handleIndicatorStatusRequest(const BD_ADDR_T * addr)
{
    /* keep the compiler happy */
    addr = addr;
    
	/* Send a CIND read reply containing current values of supported indicators */
    agSendCindReadResponse();            

    /* acknowledge the command */
    agSendOk();
}


/*
    handleIndicatorReportActivation

    Activate indicator status reporting
    AT cmd: AT+CMER= ...
*/
void handleIndicatorReportActivation(const BD_ADDR_T * addr, const struct IndicatorReportActivation *s)
{    
    uint16 error_flag = 0;

    /* Chack the mode first */
    if (s->mode == 3)
    {                   
        /* Look at the next value to see if indicator reporting is enabled */
        if (s->ind == 1)
        {
            /* Enable event reporting */
            AGState.hfIndicatorUpdateEnabled = 1;
        }
        else if (s->ind == 0)
        {
            /* Disable event reporting */
            AGState.hfIndicatorUpdateEnabled = 0;
        }
        else 
        {   
            /* unrecognised indicator value so send an error */
            error_flag = 1;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -