📄 av_headset_controls.c
字号:
/****************************************************************************
Copyright (C) Cambridge Silicon Radio Ltd. 2004
FILE NAME
av_headset_controls.c
DESCRIPTION
NOTES
*/
/****************************************************************************
Header files
*/
#include "headset_private.h"
#include "av_headset_controls.h"
#include "av_headset_kalimba.h"
#include "hfp_headset_slc.h"
#include "cvc_headset.h"
#include <stdlib.h>
#include <string.h>
#include <panic.h>
#include <pio.h>
#include <ps.h>
#include <codec.h>
#include <pcm.h>
static void controls_handler(Task task, MessageId id, Message message);
static const uint8 vgsToCodecGain[16] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 17, 19};
/*
Send remote control command to remote device
*/
static void sendAVRCP(headsetTaskData* app, avc_operation_id op_id, uint8 state)
{
app->avrcp_pending = TRUE;
/* Send a key press */
AvrcpPassthrough(app->avrcp,
subunit_panel,
0,
state,
op_id,
0,
0);
}
/*************************************************************************
NAME
avHeadsetInitialiseControls
DESCRIPTION
Initialises power and button control
RETURNS
*/
void avHeadsetInitialiseControls(headsetTaskData* app)
{
/* hold power on so user can release the button */
PioSet(POWER_HOLD,POWER_HOLD);
PioSetDir(POWER_HOLD,POWER_HOLD);
/* Read the volume from PS. The volume is stored as:
HF Volume | AV volume
---------------------------------
|15| | | | | | |8|7| | | | | | |0|
---------------------------------
*/
if (!PsRetrieve(VOLUME_LEVEL, &app->speaker_volume, sizeof(app->speaker_volume)))
/* set the headset gain to a reasonable value */
app->speaker_volume = 10 | (10 << VOLUME_SHIFT);
DEBUG(("avHeadsetInitialiseControls()\n"));
/* initial the handler task */
app->controls_task.handler = controls_handler;
}
/*************************************************************************
NAME
avHeadsetStartPowerDown
DESCRIPTION
Start to power down the headset gracefully
RETURNS
*/
void avHeadsetStartPowerDown(headsetTaskData* app)
{
if (app->powering_down)
return;
app->powering_down = TRUE;
/* Close down any active AV link */
if ((app->a2dp_state == avHeadsetA2dpConnected) || (app->a2dp_state == avHeadsetA2dpStreaming))
{
app->a2dp_state = avHeadsetA2dpConnected;
A2dpClose(app->a2dp, app->media_sink);
}
/* Close down any active AVRCP link */
if (app->avrcp_state == avHeadsetAvrcpConnected)
{
avHeadsetSetAvrcpState(avHeadsetAvrcpDisconnecting);
AvrcpDisconnect(app->avrcp);
}
/* Close down any active AG link */
if ((app->hfp_state != headsetInitialising) && (app->hfp_state != headsetReady))
hfpHeadsetDisconnectSlc(app);
MessageSendLater(getAppTask(), APP_POWER_OFF_IND, 0, (uint32) 5000);
avHeadsetCheckPowerDownStatus(app);
}
/*************************************************************************
NAME
avHeadsetCheckPowerDownStatus
DESCRIPTION
Checks if connections have been successfully dropped and we have
initiated power down. We can then power off.
RETURNS
*/
void avHeadsetCheckPowerDownStatus(const headsetTaskData *app)
{
if (!app->powering_down)
return;
if ((app->a2dp_state == avHeadsetA2dpReady) && (app->avrcp_state == avHeadsetAvrcpReady) && (app->hfp_state == headsetReady))
{
DEBUG(("OK! We can power down early\n"));
(void) MessageCancelAll(getAppTask(), APP_POWER_OFF_IND);
MessageSend(getAppTask(), APP_POWER_OFF_IND, 0);
}
}
/*************************************************************************
NAME
avHeadsetPowerDown
DESCRIPTION
Power down the headset
RETURNS
*/
void avHeadsetPowerDown(const headsetTaskData *app)
{
DEBUG(("PowerDown and Panic\n"));
/* Power down the codec */
CodecPowerDown(app->codec_task);
/* Store the current volume */
(void) PsStore(VOLUME_LEVEL, &app->speaker_volume, sizeof(app->speaker_volume));
/* disable power hold and LED */
PioSetDir(POWER_HOLD | LED, 0);
PioSet(POWER_HOLD | LED,0);
/* in case the interface board is attached
and keeping us alive we also halt the program. */
Panic();
}
/*************************************************************************
NAME
avHeadsetHandleAvVolUp
DESCRIPTION
Increase AV volume in single step increments
RETURNS
*/
void avHeadsetHandleAvVolUp(headsetTaskData* app)
{
if ((app->speaker_volume & 0xFF) < 15)
app->speaker_volume++;
#ifdef INCLUDE_CVC
if (app->active_profile== hfp_active)
{
CvcHeadsetGainRequest(app->speaker_volume);
DEBUG(("clarity on speaker gain request VolUp=%d\n",app->speaker_volume));
}
else if (app->active_profile== av_active)
#endif
{
avHeadsetUpdateAvVolume(app->codec_task, app->speaker_volume);
DEBUG(("avHeadsetUpdate volume for a2dp VolUp=%d\n",app->speaker_volume));
}
}
/*************************************************************************
NAME
avHeadsetHandleAvVolDown
DESCRIPTION
Decrease AV volume in single step increments
RETURNS
*/
void avHeadsetHandleAvVolDown(headsetTaskData* app)
{
if ((app->speaker_volume & 0xFF) > 0)
app->speaker_volume--;
#ifdef INCLUDE_CVC
if (app->active_profile== hfp_active)
{
CvcHeadsetGainRequest(app->speaker_volume);
DEBUG(("clarity on speaker gain request VolDown=%d\n",app->speaker_volume));
}
else if (app->active_profile== av_active)
#endif
{
avHeadsetUpdateAvVolume(app->codec_task, app->speaker_volume);
DEBUG(("avHeadsetUpdate volume for a2dp VolDown=%d\n",app->speaker_volume));
}
}
/*************************************************************************
NAME
avHeadsetHandleHfVolUp
DESCRIPTION
Increase Hands free volume in single step increments
RETURNS
*/
void avHeadsetHandleHfVolUp(headsetTaskData* app)
{
uint16 ag_volume = app->speaker_volume >> VOLUME_SHIFT;
if (ag_volume < 15)
ag_volume++;
app->speaker_volume = (app->speaker_volume & 0xFF) | (ag_volume << VOLUME_SHIFT);
#ifdef INCLUDE_CVC
CvcHeadsetVolume(app->speaker_volume);
#else
avHeadsetUpdateHfVolume(app->codec_task, app->speaker_volume);
#endif
}
/*************************************************************************
NAME
avHeadsetHandleHfVolDown
DESCRIPTION
Decrease Hands free volume in single step increments
RETURNS
*/
void avHeadsetHandleHfVolDown(headsetTaskData* app)
{
uint16 ag_volume = app->speaker_volume >> VOLUME_SHIFT;
if (ag_volume > 0)
ag_volume--;
app->speaker_volume = (app->speaker_volume & 0xFF) | (ag_volume << VOLUME_SHIFT);
#ifdef INCLUDE_CVC
CvcHeadsetVolume(app->speaker_volume);
#else
avHeadsetUpdateHfVolume(app->codec_task, app->speaker_volume);
#endif
}
/*************************************************************************
NAME
avHeadsetUpdateAvVolume
DESCRIPTION
Set the codec gain to an absolute value
RETURNS
*/
void avHeadsetUpdateAvVolume(Task codec_task, uint16 gain)
{
gain &= 0xFF;
if (gain <= 15)
CodecSetOutputGain(codec_task, vgsToCodecGain[gain], left_and_right_ch);
DEBUG(("AV volume: %d\n",gain));
}
/*************************************************************************
NAME
avHeadsetUpdateHfVolume
DESCRIPTION
Set the codec gain to an absolute value
RETURNS
*/
void avHeadsetUpdateHfVolume(Task codec_task, uint16 gain)
{
gain = gain >> VOLUME_SHIFT;
if (gain <= 15)
CodecSetOutputGain(codec_task, vgsToCodecGain[gain], left_and_right_ch);
DEBUG(("HF volume: %d\n",gain));
}
enum
{
PAUSE_PRESS,
PAUSE_RELEASE,
PLAY_PRESS,
PLAY_RELEASE,
FORWARD_PRESS,
FORWARD_RELEASE,
BACKWARD_PRESS,
BACKWARD_RELEASE,
STOP_PRESS,
STOP_RELEASE
};
/*************************************************************************
NAME
controls_handler
DESCRIPTION
Called when a button state change is pending which can now be sent.
Messages will only be delivered when avrcp_pending is FALSE and
hence when we are clear to send the message.
RETURNS
*/
static void controls_handler(Task task, MessageId id, Message message)
{
task = task;
message = message;
switch (id)
{
case PAUSE_PRESS:
DEBUG(("Sending Pause Pressed\n"));
sendAVRCP(getApp(), opid_pause, 0);
break;
case PAUSE_RELEASE:
DEBUG(("Sending Pause Released\n"));
sendAVRCP(getApp(), opid_pause, 1);
break;
case PLAY_PRESS:
DEBUG(("Sending Play Pressed\n"));
sendAVRCP(getApp(), opid_play, 0);
break;
case PLAY_RELEASE:
DEBUG(("Sending Play Released\n"));
sendAVRCP(getApp(), opid_play, 1);
break;
case FORWARD_PRESS:
DEBUG(("Sending Forward Pressed\n"));
sendAVRCP(getApp(), opid_forward, 0);
break;
case FORWARD_RELEASE:
DEBUG(("Sending Forward Released\n"));
sendAVRCP(getApp(), opid_forward, 1);
break;
case BACKWARD_PRESS:
DEBUG(("Sending Backward Pressed\n"));
sendAVRCP(getApp(), opid_backward, 0);
break;
case BACKWARD_RELEASE:
DEBUG(("Sending Backward Released\n"));
sendAVRCP(getApp(), opid_backward, 1);
break;
case STOP_PRESS:
DEBUG(("Sending Stop Pressed\n"));
sendAVRCP(getApp(), opid_stop, 0);
break;
case STOP_RELEASE:
DEBUG(("Sending Stop Released\n"));
sendAVRCP(getApp(), opid_stop, 1);
break;
default:
break;
}
}
/*************************************************************************
NAME
avHeadsetPausePress
DESCRIPTION
Signal that pause has been pressed.
Note that the AV Control specification states that the pause
button will toggle between playing/paused.
RETURNS
*/
void avHeadsetPausePress(headsetTaskData* app)
{
/* see controls_handler description */
MessageSendConditionally(&app->controls_task, PAUSE_PRESS, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetPauseRelease
DESCRIPTION
Signal that pause has been released
RETURNS
*/
void avHeadsetPauseRelease(headsetTaskData* app)
{
/* see button_handler message queue description */
MessageSendConditionally(&app->controls_task, PAUSE_RELEASE, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetPlayPress
DESCRIPTION
Signal that play has been pressed
RETURNS
*/
void avHeadsetPlayPress(headsetTaskData* app)
{
/* see controls_handler description */
MessageSendConditionally(&app->controls_task, PLAY_PRESS, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetPlayRelease
DESCRIPTION
Signal that play has been released
RETURNS
*/
void avHeadsetPlayRelease(headsetTaskData* app)
{
/* see button_handler message queue description */
MessageSendConditionally(&app->controls_task, PLAY_RELEASE, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetForwardPress
DESCRIPTION
Signal that Forward has been pressed
RETURNS
*/
void avHeadsetForwardPress(headsetTaskData* app)
{
/* see controls_handler description */
MessageSendConditionally(&app->controls_task, FORWARD_PRESS, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetForwardRelease
DESCRIPTION
Signal that Forward has been released
RETURNS
*/
void avHeadsetForwardRelease(headsetTaskData* app)
{
/* see button_handler message queue description */
MessageSendConditionally(&app->controls_task, FORWARD_RELEASE, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetBackwardPress
DESCRIPTION
Signal that Backward has been pressed
RETURNS
*/
void avHeadsetBackwardPress(headsetTaskData* app)
{
/* see controls_handler description */
MessageSendConditionally(&app->controls_task, BACKWARD_PRESS, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetBackwardRelease
DESCRIPTION
Signal that Backward has been released
RETURNS
*/
void avHeadsetBackwardRelease(headsetTaskData* app)
{
/* see button_handler message queue description */
MessageSendConditionally(&app->controls_task, BACKWARD_RELEASE, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetStopPress
DESCRIPTION
Signal that Stop has been pressed
RETURNS
*/
void avHeadsetStopPress(headsetTaskData* app)
{
/* see controls_handler description */
MessageSendConditionally(&app->controls_task, STOP_PRESS, NULL, &app->avrcp_pending);
}
/*************************************************************************
NAME
avHeadsetStopRelease
DESCRIPTION
Signal that Stop has been released
RETURNS
*/
void avHeadsetStopRelease(headsetTaskData* app)
{
/* see button_handler message queue description */
MessageSendConditionally(&app->controls_task, STOP_RELEASE, NULL, &app->avrcp_pending);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -