📄 ag_athandler.c
字号:
#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 + -