📄 pioag_receive.c
字号:
#include "pioag_private.h"
#include "ag_types.h"
#include "ag.h"
#include <audio.h>
#include <panic.h>
#include <ps.h>
#include <stdlib.h>
#include <string.h>
static const audio_note error_beep[] =
{
AUDIO_TEMPO(180), AUDIO_VOLUME(64), AUDIO_TIMBRE(sine),
AUDIO_NOTE(E7, QUAVER),
AUDIO_NOTE(B7, QUAVER),
AUDIO_NOTE(E7, QUAVER),
AUDIO_NOTE(C7, QUAVER),
AUDIO_END
};
/*
pioAgConnectionAttemptTimeout
Timer function that times reconnection attempts.
*/
static Delay pioAgConnectionAttemptTimeout(TimerHandle h)
{
/* Keep compiler happy */
h = h;
/* Become connectable */
pioAgConnectReq(PioAgSlave, PIO_AG_SLAVE_CONNECT_TIMEOUT);
/* reset the timer handle */
PioAgState.connectionTimerHandle = NULL_TIMER;
return D_NEVER;
}
/*
handleStartCfm
Start cfm receivced from the AG
This function checks to see if the FEAG is already paired to a
headset, if it is it attempts to connect to it. If not it prompts
the user to enter a pin code.
*/
void handleStartCfm(void)
{
uint16 isPaired = 0;
/* Check to see if we are currently paired to another device */
if (PsRetrieve(PIO_AG_PS_IS_PAIRED, &(isPaired), sizeof(isPaired)) && isPaired)
{
/* We are currently paired to something, register it with the security manager */
pioAgSmAddDevReq();
/* Now try to connect to the device we're paired with */
pioAgConnectReq(PioAgSlave, PIO_AG_SLAVE_CONNECT_TIMEOUT);
}
else
{
/*
We are not paired to anything, clear the stored address and link key
and get the pin code.
*/
uint16 pinlen = 0;
uint16 *zeroBuf = (uint16*) PanicNull(calloc(32, sizeof(uint16)));
(void) PsStore(PIO_AG_PS_PEER_ADDR, zeroBuf, sizeof(BD_ADDR_T));
(void) PsStore(PIO_AG_PS_LINK_KEY, zeroBuf, AG_SIZE_LINK_KEY);
if(PsRetrieve(PIO_AG_PS_PIN_LENGTH, &pinlen, 1) && pinlen)
{
/*
We have a PIN so go into pairin mode, if the user wants to enter
a new pin they wil perferom a reset
*/
pioAgInquiryReq();
}
else
{
/* No Pin stored. Get Pin Code from user */
(void) PsStore(PIO_AG_PS_PIN_CODE, zeroBuf, MAX_PIN_LENGTH);
(void) PsStore(PIO_AG_PS_PIN_LENGTH, zeroBuf, 1);
if (pioAgResetReq())
{
pioAgGetPinCode();
}
}
free(zeroBuf);
}
}
/*
handleInquiryResultInd
Processes the Inquiry results accordingly, since we are only looking for
one device we can store it in the PS to indicate that a device has been found.
*/
void handleInquiryResultInd(const CM_INQUIRY_RESULT_IND_T *ind)
{
/* Store the address in our PS store */
(void) PsStore(PIO_AG_PS_PEER_ADDR, &ind->inq_result.bd_addr, sizeof(BD_ADDR_T));
}
/*
handleInquiryCompleteCfm
Inquiry has completed. Checks the status of the inquiry confirm event
and processes accordingly.
*/
void handleInquiryCompleteCfm(ag_inquiry_status_t status)
{
bd_addr_t bd_addr;
status = status;
if (PsRetrieve(PIO_AG_PS_PEER_ADDR, &bd_addr, sizeof(bd_addr_t)) &&
bd_addr.nap && bd_addr.uap && bd_addr.lap)
{
/* We found a device to pair to */
pairReqAction(bd_addr, 1, PIO_AG_PAIRING_TIMEOUT);
}
else
{
/* We didn't find anything so play an error beep and go idle */
(void) AudioPlay(error_beep);
}
PioAgState.inquiryComplete = 1;
}
/*
handlePinReq
Retrieve PIN code entered by the user and send to the lower layers.
*/
void handlePinReq(BD_ADDR_T addr)
{
bd_addr_t tmp_addr;
tmp_addr.nap = addr.nap;
tmp_addr.uap = addr.uap;
tmp_addr.lap = addr.lap;
/* Send the stored Pin code */
pioAgPinReplyReq(tmp_addr);
}
/*
handleLinkKeyReq
A request for the link key has arrived, send the stored link key back.
*/
void handleLinkKeyReq(uint16 handle)
{
uint8 link_key[AG_SIZE_LINK_KEY];
uint16 isValid = 0;
memset(link_key, 0, AG_SIZE_LINK_KEY);
if (PsRetrieve(PIO_AG_PS_LINK_KEY_VALID, &isValid, sizeof(uint16)) && isValid)
{
/* We have a valid link key, check that the handles match */
if (handle == PioAgState.handle)
{
/* The handles match fetch the link key from PS and send it back */
(void) PsRetrieve(PIO_AG_PS_LINK_KEY, link_key, AG_SIZE_LINK_KEY);
linkKeyResAction(1, handle, link_key);
}
else
{
/* The handle does not match, reject the request and flag an error */
linkKeyResAction(0, handle, link_key);
}
}
else
{
/* There is no valid link key so we have to send a reject here */
linkKeyResAction(0, handle, link_key);
}
}
/*
handlePairCfm
Process Pair Confirm accordingly, currently if the pairing fails nothing
happens. The state machine returns to idle so could start inquiries again.
*/
void handlePairCfm(BD_ADDR_T addr, ag_pair_status_t status, const uint8 *link_key)
{
uint16 isPaired, isValid;
switch (status)
{
/*
If the pairing succeeded, store link key, bd addr, etc in PS
and attempt connection
*/
case AgPairingComplete:
{
bd_addr_t tmp_addr;
tmp_addr.nap = addr.nap;
tmp_addr.uap = addr.uap;
tmp_addr.lap = addr.lap;
isPaired = 1;
isValid = 1;
(void) PsStore(PIO_AG_PS_LINK_KEY, link_key, AG_SIZE_LINK_KEY);
(void) PsStore(PIO_AG_PS_IS_PAIRED, &(isPaired), 1);
(void) PsStore(PIO_AG_PS_LINK_KEY_VALID, &(isValid), 1);
(void) PsStore(PIO_AG_PS_PEER_ADDR, &tmp_addr, sizeof(bd_addr_t));
/* Start trying to connect to the remote device */
PioAgState.connectionTimerHandle = TimerAdd(D_SEC(PIO_AG_CONNECTION_RETRY_TIMEOUT), pioAgConnectionAttemptTimeout);
}
break;
/* If pairing was cancelled, return to idle we must be resetting */
case AgPairingError:
case AgPairingCancelled:
case AgPairingFailed:
case AgPairingTimedOut:
(void) AudioPlay(error_beep);
break;
/* Flag an error, we got an unknown response */
default:
break;
}
}
/*
handleConnectionHandleMap
A connection request indicator has arrived, store the device handle.
*/
void handleConnectionHandleMap(uint16 hdl, bd_addr_t addr)
{
bd_addr_t bdAddr;
(void) PsRetrieve(PIO_AG_PS_PEER_ADDR, &bdAddr, sizeof(bd_addr_t));
if (bdAddr.nap == addr.nap &&
bdAddr.uap == addr.uap &&
bdAddr.lap == addr.lap)
{
/* Device address matches stored address */
PioAgState.handle = hdl;
}
else
{
/* Device addresses do not match */
PioAgState.handle = UNDEFINED_HANDLE;
}
}
/*
handleRfcommStatusInd
An RFCOMM connection may have been established, find out and deal with it.
*/
void handleRfcommStatusInd(ag_handle_t hdl, ag_connection_status_t status, ag_profile_role_t role)
{
/* keep the compiler happy */
hdl = hdl;
role = role;
switch(status)
{
/* If the attempt was a success, wait for user to establish a SCO */
case AgConnectComplete:
PioAgState.connectAsSlave = 0;
break;
/* If the attempt failed, flag error */
case AgConnectDisconnect:
case AgConnectDisconnectAbnormal:
case AgConnectFailed:
case AgConnectTimeout:
if (!agRfcommConnectedQuery())
{
/* If not connected, schedule another attempt to connect */
PioAgState.connectAsSlave = 0;
PioAgState.connectionTimerHandle = TimerAdd(D_SEC(PIO_AG_CONNECTION_RETRY_TIMEOUT), pioAgConnectionAttemptTimeout);
}
break;
/* The attempt was cancelled - resetting or flipping connect mode */
case AgConnectCancelled:
if (PioAgState.connectAsSlave)
{
/* If the connect as slave flag is set then try connecting as master */
pioAgConnectReq(PioAgMaster, PIO_AG_MASTER_CONNECT_TIMEOUT);
}
break;
default:
/* Flag an error, we got an unknown response */
break;
}
}
/*
handleButtonPressInd
A button press has been received from the headset, this could mean
one of two things, if there is no SCO connection then start one up.
If there is a SCO connection, tear it down.
*/
void handleButtonPressInd(ag_handle_t hdl)
{
if (agScoConnectedQuery())
{
/* Tear down SCO connection */
agScoDisconnectReqAction(hdl);
}
else
{
/* Start a SCO Connection, packet type hard coded */
agScoConnectReqAction(hdl, PIO_AG_HV3);
}
}
/*
handleScoStatusInd
Process the SCO connection status indicator and update state variable.
*/
void handleScoStatusInd(ag_handle_t hdl, ag_connection_status_t status, hci_connection_handle_t sco_handle)
{
hdl = hdl;
sco_handle = sco_handle;
/* if the connection was not opened or disconnected properly beep for error */
if (status != AgConnectComplete && status != AgConnectDisconnect)
(void) AudioPlay(error_beep);
}
/*
handleErrorInd
This function handles the error events from the EAG and stores
the results in the PS.
*/
void handleErrorInd(ag_handle_t hdl, ag_error_code_t error_reason)
{
/* TODO currently unused but could store this in the PS error ind keys */
hdl = hdl;
error_reason = error_reason;
/* Beep to indicate an error but not for warnings */
if (error_reason != AgWarnLocalSniffNotEnabled &&
error_reason != AgWarnLocalParkNotEnabled &&
error_reason != AgWarnLocalLowPwrModeNotEnabled &&
error_reason != AgWarnRemoteDevDoesNotSupportSniffMode &&
error_reason != AgWarnRemoteDevDoesNotSupportParkMode &&
error_reason != AgWarnRemoteLowPwrModeNotEnabled)
(void) AudioPlay(error_beep);
}
/*
handleVolumeChangeInd
Volume indication from headset
*/
void handleVolumeChangeInd(ag_handle_t hdl, uint8 gain)
{
/*
Currently this is ignored as it is not clear what to do with this
volume message (its an unsolicited result code informing the AG of
the volume settings at the headset)
*/
hdl = hdl;
gain = gain;
}
/*
handleMicrophoneChangeInd
Microphone gain indication from headset
*/
void handleMicrophoneChangeInd(ag_handle_t hdl, uint8 gain)
{
/*
Currently this is ignored as it is not clear what to do with this
mic gain message (its an unsolicited result code informing the AG of
the mic gain setting at the headset)
*/
hdl = hdl;
gain = gain;
}
void handleCallAnsweredInd(ag_handle_t hdl, uint16 accept_flag)
{
/* Not used by the headset profile AG so just ignore for now */
hdl = hdl;
accept_flag = accept_flag;
}
void handleRemoteDialReq(ag_handle_t hdl, dial_mode_t dial_what, uint16 length, const uint8 *data)
{
/* Not used by the headset profile AG so just ignore for now */
hdl = hdl;
dial_what = dial_what;
length = length;
data = data;
}
void handleUnparsedData(ag_handle_t hdl, uint16 length, const uint8 *data)
{
/* Just ignore data that the parser cannot cope with */
hdl = hdl;
length = length;
data = data;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -