如何开启hid dfu升级---qcc 514x/518x headset
默认SDK都没办法hid dfu升级,下面步骤教大家如何开启hid dfu升级
/*!
\copyright Copyright (c) 2017 - 2023 Qualcomm Technologies International, Ltd.
All Rights Reserved.
Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\version
\file dfu.c
\ingroup dfu
\brief Device firmware upgrade management.
Over the air upgrade is managed from this file.
*/
#ifdef INCLUDE_DFU
#include "dfu.h"
#include "system_state.h"
#include "adk_log.h"
#include "phy_state.h"
#include "bt_device.h"
#include "device_properties.h"
#include "device_db_serialiser.h"
#include <charger_monitor.h>
#include <system_state.h>
#include <vmal.h>
#include <panic.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <upgrade.h>
#include <ps.h>
#include <gatt_connect.h>
#include <gatt_handler.h>
#include <gatt_server_gatt.h>
#include <connection_manager.h>
#include <device_list.h>
#include <connection_manager_list.h>
#include "dfu_rules.h"
#ifdef INCLUDE_DFU_PEER
#include "dfu_peer.h"
#include "bt_device.h"
#include <app/message/system_message.h>
#include <peer_signalling.h>
#include <tws_topology_config.h>
#include <mirror_profile.h>
#include <handover_profile.h>
#include <power_manager.h>
#endif
#ifdef INCLUDE_DFU_CASE
#include "dfu_case.h"
#endif
#ifndef HOSTED_TEST_ENVIRONMENT
/*! There is checking that the messages assigned by this module do
not overrun into the next module's message ID allocation */
ASSERT_MESSAGE_GROUP_NOT_OVERFLOWED(DFU, DFU_MESSAGE_END)
#endif
/*!< Task information for UPGRADE support */
dfu_task_data_t app_dfu;
/*! Identifiers for messages used internally by the DFU module */
typedef enum dfu_internal_messages_t
{
DFU_INTERNAL_BASE = INTERNAL_MESSAGE_BASE ,
DFU_INTERNAL_CONTINUE_HASH_CHECK_REQUEST,
#ifdef INCLUDE_DFU_PEER
DFU_INTERNAL_UPGRADE_APPLY_RES_ON_PEER_PROFILES_CONNECTED,
#endif
/*! This must be the final message */
DFU_INTERNAL_MESSAGE_END
};
ASSERT_INTERNAL_MESSAGES_NOT_OVERFLOWED(DFU_INTERNAL_MESSAGE_END)
LOGGING_PRESERVE_MESSAGE_ENUM(dfu_internal_messages_t)
LOGGING_PRESERVE_MESSAGE_TYPE(dfu_messages_t)
/* The upgrade libraries use of partitions is not relevant to the
partitions as used on devices targetted by this application.
As it is not possible to pass 0 partitions in the Init function
use a simple entry */
static const UPGRADE_UPGRADABLE_PARTITION_T logicalPartitions[]
= {UPGRADE_PARTITION_SINGLE(0x1000,DFU)
};
/*! Maximum size of buffer used to hold the variant string
supplied by the application. 6 chars, plus NULL terminator */
#define VARIANT_BUFFER_SIZE (7)
static void dfu_MessageHandler(Task task, MessageId id, Message message);
static void dfu_GattConnect(gatt_cid_t cid);
static void dfu_GattDisconnect(gatt_cid_t cid);
static void dfu_GetVersionInfo(dfu_VersionInfo *ver_info);
static void dfu_SetGattServiceUpdateFlags(void);
#ifdef INCLUDE_DFU_PEER
static void dfu_PeerSetContextTx(upgrade_context_t context);
static void dfu_PeerSyncVldtnCompleteTx(void);
#endif
static const gatt_connect_observer_callback_t dfu_gatt_connect_callback =
{
.OnConnection = dfu_GattConnect,
.OnDisconnection = dfu_GattDisconnect
};
static void dfu_NotifyStartedNeedConfirm(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_REQUESTED_TO_CONFIRM);
}
static void dfu_NotifyStartedWithInProgress(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_REQUESTED_IN_PROGRESS);
}
static void dfu_NotifyActivity(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_ACTIVITY);
}
static void dfu_NotifyStart(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_STARTED);
}
static void dfu_NotifyCompleted(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_COMPLETED);
}
static void dfu_NotifyAbort(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_CLEANUP_ON_ABORT);
}
static void dfu_NotifyAborted(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_ABORTED);
}
static void dfu_NotifyReadyforSilentCommit(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_READY_FOR_SILENT_COMMIT);
}
static void dfu_NotifyReadyToReboot(void)
{
TaskList_MessageSendId(TaskList_GetFlexibleBaseTaskList(Dfu_GetClientList()), DFU_READY_TO_REBOOT);
}
/*************************************************************************
Provide the logical partition map.
For earbuds this is initially hard coded, but may come from other
storage in time.
*/
static void dfu_GetLogicalPartitions(const UPGRADE_UPGRADABLE_PARTITION_T **partitions, uint16 *count)
{
uint16 num_partitions = sizeof(logicalPartitions)/sizeof(logicalPartitions[0]);
*partitions = logicalPartitions;
*count = num_partitions;
}
/*************************************************************************
Get the variant Id from the firmware and convert it into a variant
string that can be passed to UpgradeInit.
This function allocates a buffer for the string which must be freed
after the call to UpgradeInit.
*/
static void dfu_GetVariant(char *variant, size_t length)
{
int i = 0;
char chr;
uint32 product_id;
PanicFalse(length >= VARIANT_BUFFER_SIZE);
product_id = VmalVmReadProductId();
if (product_id == 0)
{
variant[0] = '\0';
return;
}
/* The product Id is encoded as two ascii chars + 4 integers in BCD format. */
/* The ascii chars may be undefined or invalid (e.g. '\0').
If so, don't include them in the variant string. */
chr = (char)((product_id >> 8) & 0xFF);
if (isalnum(chr))
variant[i++] = chr;
chr = (char)(product_id & 0xFF);
if (isalnum(chr))
variant[i++] = chr;
sprintf(&variant[i], "%04X", ((uint16)((product_id >> 16) & 0xFFFF)));
}
/******************** PUBLIC FUNCTIONS **************************/
bool Dfu_EarlyInit(Task init_task)
{
UNUSED(init_task);
DEBUG_LOG("Dfu_EarlyInit");
#if (THE_DFU_CLIENT_LIST_INIT_CAPACITY == 1)
TaskList_Initialise((task_list_t *)Dfu_GetClientList());
#else
TaskList_InitialiseWithCapacity(Dfu_GetClientList(), THE_DFU_CLIENT_LIST_INIT_CAPACITY);
#endif
return TRUE;
}
/*! Initialisation point for the over the air support in the upgrade library.
*
*/
bool Dfu_Init(Task init_task)
{
dfu_task_data_t *the_dfu=Dfu_GetTaskData();
uint16 num_partitions;
const UPGRADE_UPGRADABLE_PARTITION_T *logical_partitions;
char variant[VARIANT_BUFFER_SIZE];
dfu_VersionInfo ver_info;
UNUSED(init_task);
dfu_GetVersionInfo(&ver_info);
GattConnect_RegisterObserver(&dfu_gatt_connect_callback);
the_dfu->dfu_task.handler = dfu_MessageHandler;
the_dfu->reboot_permission_required = FALSE;
#ifdef INCLUDE_DFU_PEER
/*
* Register to use marshalled message channel with DFU domain for Peer DFU
* messages.
*/
appPeerSigMarshalledMsgChannelTaskRegister(Dfu_GetTask(),
PEER_SIG_MSG_CHANNEL_DFU,
dfu_peer_sig_marshal_type_descriptors,
NUMBER_OF_DFU_PEER_SIG_MARSHAL_TYPES);
/* Register for peer signaling notifications */
appPeerSigClientRegister(Dfu_GetTask());
/* Register for connect / disconnect events from mirror profile */
MirrorProfile_ClientRegister(Dfu_GetTask());
HandoverProfile_ClientRegister(Dfu_GetTask());
/* Register for power management during DFU process */
appPowerClientRegister(Dfu_GetTask());
appPowerClientAllowSleep(Dfu_GetTask());
#endif
ConManagerRegisterConnectionsClient(Dfu_GetTask());
dfu_GetVariant(variant, sizeof(variant));
dfu_GetLogicalPartitions(&logical_partitions, &num_partitions);
/* Initiate the DFU rules engine */
DfuRules_Init(Dfu_GetTask());
/* Allow storage of info at end of (SINK_UPGRADE_CONTEXT_KEY) */
UpgradeInit(Dfu_GetTask(), UPGRADE_CONTEXT_KEY, UPGRADE_LIBRARY_CONTEXT_OFFSET,
logical_partitions,
num_partitions,
UPGRADE_INIT_POWER_MANAGEMENT,
variant,
upgrade_perm_always_ask,
&ver_info.upgrade_ver,
ver_info.config_ver);
return TRUE;
}
bool Dfu_HandleSystemMessages(MessageId id, Message message, bool already_handled)
{
switch (id)
{
case MESSAGE_IMAGE_UPGRADE_ERASE_STATUS:
case MESSAGE_IMAGE_UPGRADE_COPY_STATUS:
case MESSAGE_IMAGE_UPGRADE_AUDIO_STATUS:
case MESSAGE_IMAGE_UPGRADE_HASH_ALL_SECTIONS_UPDATE_STATUS:
{
Task upg = Dfu_GetTask();
upg->handler(upg, id, message);
return TRUE;
}
}
return already_handled;
}
static void dfu_ForwardInitCfm(const UPGRADE_INIT_CFM_T *cfm)
{
UPGRADE_INIT_CFM_T *copy = PanicUnlessNew(UPGRADE_INIT_CFM_T);
*copy = *cfm;
MessageSend(SystemState_GetTransitionTask(), UPGRADE_INIT_CFM, copy);
}
static void dfu_HandleRestartedInd(const UPGRADE_RESTARTED_IND_T *restart)
{
/* This needs to base its handling on the reason in the message,
for instance upgrade_reconnect_not_required is a hint that errr,
reconnect isn't a priority. */
DEBUG_LOG("dfu_HandleRestartedInd 0x%x", restart->reason);
switch (restart->reason)
{
case upgrade_reconnect_not_required:
/* No need to reconnect, not even sure why we got this */
break;
case upgrade_reconnect_required_for_confirm:
Dfu_SetRebootReason(REBOOT_REASON_DFU_RESET);
dfu_NotifyStartedNeedConfirm();
#ifndef INCLUDE_DFU_PEER
/* If peer is NOT supported, commit new image here for silent commit option*/
if(UpgradeIsSilentCommitEnabled())
{
DEBUG_LOG("dfu_HandleRestartedInd: UpgradeCommitConfirmForSilentCommit");
UpgradeCommitConfirmForSilentCommit();
}
#endif
#ifdef INCLUDE_DFU_PEER
/* Prohibit sleep during commit phase */
DEBUG_LOG_VERBOSE("dfu_HandleRestartedInd Prohibit earbud to sleep");
appPowerClientProhibitSleep(Dfu_GetTask());
#endif
break;
case upgrade_reconnect_recommended_as_completed:
case upgrade_reconnect_recommended_in_progress:
/*
* Remember the reset reason, in order to progress an DFU
* if abruptly reset.
*/
Dfu_SetRebootReason(REBOOT_REASON_ABRUPT_RESET);
dfu_NotifyStartedWithInProgress();
#ifdef INCLUDE_DFU_PEER
/* Prohibit sleep during abrupt reset phase */
DEBUG_LOG_VERBOSE("dfu_HandleRestartedInd Prohibit earbud to sleep");
appPowerClientProhibitSleep(Dfu_GetTask());
#endif
break;
}
}
static void dfu_HandleUpgradeStatusInd(const UPGRADE_STATUS_IND_T *sts)
{
dfu_NotifyActivity();
switch (sts->state)
{
case upgrade_state_idle:
DEBUG_LOG("dfu_HandleUpgradeStatusInd. idle(%d)",sts->state);
break;
case upgrade_state_downloading:
DEBUG_LOG("dfu_HandleUpgradeStatusInd. downloading(%d)",sts->state);
break;
case upgrade_state_download_completed:
DEBUG_LOG("dfu_HandleUpgradeStatusInd. download completed(%d)",sts->state);
DfuRules_SetEvent(DFU_EVENT_DATA_TRANSFER_COMPLETE);
break;
case upgrade_state_validation_completed:
DEBUG_LOG("dfu_HandleUpgradeStatusInd. validation completed(%d)",sts->state);
#ifdef INCLUDE_DFU_PEER
if(UPGRADE_PEER_IS_CONNECTED)
{
/* Send the resume point info to peer device */
dfu_PeerSyncVldtnCompleteTx();
}
#endif
/* Event to handle the validaiton complete scenario */
DfuRules_SetEvent(DFU_EVENT_VALIDATION_COMPLETE);
break;
case upgrade_state_commiting:
DEBUG_LOG("dfu_HandleUpgradeStatusInd. commiting(%d)",sts->state);
break;
case upgrade_state_done: