Created
August 3, 2022 10:22
-
-
Save vadimkozhin/f297105a97950fb02421da7a80ad94bc to your computer and use it in GitHub Desktop.
Bare minimum OSH tag implementation using ST17H66 based cheap tags
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************************************************************************************************** | |
******* | |
**************************************************************************************************/ | |
/************************************************************************************************** | |
Filename: simpleBLEPeripheral.c | |
Revised: | |
Revision: | |
Description: This file contains the Simple BLE Peripheral sample application | |
**************************************************************************************************/ | |
/********************************************************************* | |
* INCLUDES | |
*/ | |
#include "bcomdef.h" | |
#include "rf_phy_driver.h" | |
#include "global_config.h" | |
#include "OSAL.h" | |
#include "OSAL_PwrMgr.h" | |
#include "gatt.h" | |
#include "hci.h" | |
#include "gapgattserver.h" | |
#include "gattservapp.h" | |
#include "devinfoservice.h" | |
#include "sbpProfile_ota.h" | |
#include "ota_app_service.h" | |
#include "peripheral.h" | |
#include "gapbondmgr.h" | |
#include "pwrmgr.h" | |
#include "gpio.h" | |
#include "simpleBLEPeripheral.h" | |
#include "ll.h" | |
#include "ll_hw_drv.h" | |
#include "ll_def.h" | |
#include "hci_tl.h" | |
#include "flash.h" | |
/********************************************************************* | |
* MACROS | |
*/ | |
//#define LOG(...) | |
/********************************************************************* | |
* CONSTANTS | |
*/ | |
// How often to perform periodic event | |
#define SBP_PERIODIC_EVT_PERIOD 5000 | |
#define DEVINFO_SYSTEM_ID_LEN 8 | |
#define DEVINFO_SYSTEM_ID 0 | |
#define DEFAULT_DISCOVERABLE_MODE GAP_ADTYPE_FLAGS_GENERAL | |
// Minimum connection interval (units of 1.25ms, 80=100ms) if automatic parameter update request is enabled | |
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 8//32//80 | |
// Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic parameter update request is enabled | |
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 16//48//800 | |
// Slave latency to use if automatic parameter update request is enabled | |
#define DEFAULT_DESIRED_SLAVE_LATENCY 0 | |
// Supervision timeout value (units of 10ms, 1000=10s) if automatic parameter update request is enabled | |
#define DEFAULT_DESIRED_CONN_TIMEOUT 300//1000 | |
// Whether to enable automatic parameter update request when a connection is formed | |
#define DEFAULT_ENABLE_UPDATE_REQUEST TRUE | |
// Connection Pause Peripheral time value (in seconds) | |
#define DEFAULT_CONN_PAUSE_PERIPHERAL 6 | |
#define INVALID_CONNHANDLE 0xFFFF | |
// Default passcode | |
#define DEFAULT_PASSCODE 0//19655 | |
// Length of bd addr as a string | |
#define B_ADDR_STR_LEN 15 | |
#define RESOLVING_LIST_ENTRY_NUM 10 | |
// Offset of advertData&scanRspData | |
#define RSP_OFFSET_MAC 4 | |
/********************************************************************* | |
* OHS mods | |
*/ | |
// Broadcast interval | |
// actual time = advInt * 625us | |
#define BROADCAST_INTERVAL 1000 | |
/********************************************************************* | |
* build define | |
*/ | |
/********************************************************************* | |
* TYPEDEFS | |
*/ | |
/********************************************************************* | |
* GLOBAL VARIABLES | |
*/ | |
perStatsByChan_t g_perStatsByChanTest; | |
/********************************************************************* | |
* EXTERNAL VARIABLES | |
*/ | |
volatile uint8_t g_current_advType = LL_ADV_CONNECTABLE_UNDIRECTED_EVT; | |
/********************************************************************* | |
* EXTERNAL FUNCTIONS | |
*/ | |
/********************************************************************* | |
* LOCAL VARIABLES | |
*/ | |
uint8 simpleBLEPeripheral_TaskID; // Task ID for internal task/event processing | |
static gaprole_States_t gapProfileState = GAPROLE_INIT; | |
uint8 dev_mac_data[MAC_DATA_LEN] = {0x00,0x00,0x00,0x00,0x00,0x00}; | |
/********************************************************************* | |
* OHS mods | |
*/ | |
// This is the advertisiment key from OHS app | |
// Should be unique for each tag | |
static uint8 public_key[] = | |
{ | |
0x3c, 0xde, 0x7d, 0x1, 0x84, 0x98, 0xef, | |
0x91, 0x77, 0xa6, 0x8f, 0x28, 0x7e, 0x1c, | |
0x9f, 0x41, 0xac, 0xd9, 0x12, 0x19, 0xd3, | |
0xb6, 0x4b, 0xe1, 0x31, 0x17, 0x96, 0x8e | |
}; | |
void set_addr_from_key(uint8 *dev_mac_data, uint8 *public_key) | |
{ | |
dev_mac_data[0] = public_key[0] | 0xc0; | |
dev_mac_data[1] = public_key[1]; | |
dev_mac_data[2] = public_key[2]; | |
dev_mac_data[3] = public_key[3]; | |
dev_mac_data[4] = public_key[4]; | |
dev_mac_data[5] = public_key[5]; | |
}; | |
void set_payload_from_key(uint8_t *payload, uint8_t *public_key) { | |
/* copy last 22 bytes */ | |
osal_memcpy(&payload[7], &public_key[6], 22); | |
/* append two bits of public key */ | |
payload[29] = public_key[0] >> 6; | |
} | |
/** Advertisement payload */ | |
static uint8 advertData[] = | |
{ | |
0x1e, /* Length (30) */ | |
0xff, /* Manufacturer Specific Data (type 0xff) */ | |
0x4c, 0x00, /* Company ID (Apple) */ | |
0x12, 0x19, /* Offline Finding type and length */ | |
0x00, /* State */ | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, /* First two bits */ | |
0x00, /* Hint (0x00) */ | |
}; | |
// GAP GATT Attributes | |
// This should be removed. For now it just helps identify tag in BLE scanner | |
static uint8 attDeviceName[GAP_DEVICE_NAME_LEN] = "OHS-DEMO"; | |
/********************************************************************* | |
* end of OHS mods | |
*/ | |
/********************************************************************* | |
* LOCAL FUNCTIONS | |
*/ | |
static void simpleBLEPeripheral_ProcessOSALMsg( osal_event_hdr_t *pMsg ); | |
static void peripheralStateNotificationCB( gaprole_States_t newState ); | |
//static void simpleProfileChangeCB( uint8 paramID ); | |
static void peripheralStateReadRssiCB( int8 rssi ); | |
/********************************************************************* | |
* PROFILE CALLBACKS | |
*/ | |
// GAP Role Callbacks | |
static gapRolesCBs_t simpleBLEPeripheral_PeripheralCBs = | |
{ | |
peripheralStateNotificationCB, // Profile State Change Callbacks | |
peripheralStateReadRssiCB // When a valid RSSI is read from controller (not used by application) | |
}; | |
#if (DEF_GAPBOND_MGR_ENABLE==1) | |
// GAP Bond Manager Callbacks, add 2017-11-15 | |
static gapBondCBs_t simpleBLEPeripheral_BondMgrCBs = | |
{ | |
NULL, // Passcode callback (not used by application) | |
NULL // Pairing / Bonding state Callback (not used by application) | |
}; | |
#endif | |
// Simple GATT Profile Callbacks | |
//static simpleProfileCBs_t simpleBLEPeripheral_SimpleProfileCBs = | |
//{ | |
// simpleProfileChangeCB // Charactersitic value change callback | |
//}; | |
/********************************************************************* | |
* PUBLIC FUNCTIONS | |
*/ | |
/********************************************************************* | |
* @fn SimpleBLEPeripheral_Init | |
* | |
* @brief Initialization function for the Simple BLE Peripheral App Task. | |
* This is called during initialization and should contain | |
* any application specific initialization (ie. hardware | |
* initialization/setup, table initialization, power up | |
* notificaiton ... ). | |
* | |
* @param task_id - the ID assigned by OSAL. This ID should be | |
* used to send messages and set timers. | |
* | |
* @return none | |
*/ | |
void SimpleBLEPeripheral_Init( uint8 task_id ) | |
{ | |
LOG("\n loop init\n "); | |
simpleBLEPeripheral_TaskID = task_id; | |
// uint8 i = 0; | |
// Setup the GAP | |
VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL ); | |
// Setup the GAP Peripheral Role Profile | |
{ | |
// device starts advertising upon initialization | |
uint8 initial_advertising_enable = FALSE; | |
uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST; | |
uint8 advChnMap = GAP_ADVCHAN_37 | GAP_ADVCHAN_38 | GAP_ADVCHAN_39; | |
// By setting this to zero, the device will go into the waiting state after | |
// being discoverable for 30.72 second, and will not being advertising again | |
// until the enabler is set back to TRUE | |
uint16 gapRole_AdvertOffTime = 0; | |
uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; | |
uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; | |
uint16 desired_slave_latency = DEFAULT_DESIRED_SLAVE_LATENCY; | |
uint16 desired_conn_timeout = DEFAULT_DESIRED_CONN_TIMEOUT; | |
uint8 peerPublicAddr[] = { | |
0x01, | |
0x02, | |
0x03, | |
0x04, | |
0x05, | |
0x06 | |
}; | |
{ | |
// Read from memory | |
LOG("dev_mac_data: 0x"); | |
LOG_DUMP_BYTE(dev_mac_data, MAC_DATA_LEN); | |
//VOID osal_memcpy(scanRspData + RSP_OFFSET_MAC, dev_mac_data, MAC_DATA_LEN); | |
// Action! | |
set_addr_from_key(dev_mac_data, public_key); | |
set_payload_from_key(advertData, public_key); | |
} | |
uint8 advType = g_current_advType; | |
// LL_ADV_NONCONNECTABLE_UNDIRECTED_EVT; | |
// LL_ADV_SCANNABLE_UNDIRECTED_EVT; | |
// LL_ADV_CONNECTABLE_LDC_DIRECTED_EVT;//; | |
// it seems a bug to set GAP_ADTYPE_ADV_NONCONN_IND = 0x03 | |
GAPRole_SetParameter( GAPROLE_ADV_EVENT_TYPE, sizeof( uint8 ), &advType ); | |
GAPRole_SetParameter( GAPROLE_ADV_DIRECT_ADDR, sizeof(peerPublicAddr), peerPublicAddr); | |
// set adv channel map | |
GAPRole_SetParameter( GAPROLE_ADV_CHANNEL_MAP, sizeof( uint8 ), &advChnMap); | |
// Set the GAP Role Parameters | |
GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); | |
GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); | |
//GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof( scanRspData), scanRspData ); | |
GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); | |
GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &enable_update_request ); | |
GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval ); | |
GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval ); | |
GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency ); | |
GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout ); | |
} | |
// Set the GAP Characteristics | |
GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName ); | |
// Set advertising interval | |
{ | |
uint16 advInt = BROADCAST_INTERVAL; //2400;//1600;//1600;//800;//1600; // actual time = advInt * 625us | |
GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt ); | |
GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt ); | |
GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, advInt ); | |
GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, advInt ); | |
} | |
#if (DEF_GAPBOND_MGR_ENABLE==1) | |
// Setup the GAP Bond Manager, add 2017-11-15 | |
{ | |
uint32 passkey = DEFAULT_PASSCODE; | |
uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; | |
uint8 mitm = TRUE; | |
uint8 ioCap = GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT; | |
uint8 bonding = TRUE; | |
GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey ); | |
GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode ); | |
GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm ); | |
GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap ); | |
GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding ); | |
} | |
#endif | |
// Initialize GATT attributes | |
GGS_AddService( GATT_ALL_SERVICES ); // GAP | |
GATTServApp_AddService( GATT_ALL_SERVICES ); // GATT attributes | |
// DevInfo_AddService(); // Device Information Service | |
SimpleProfile_AddService( GATT_ALL_SERVICES ); // Simple GATT Profile | |
// uint8 OTA_Passward_AscII[8] = {'R','G','B','L','i','g','h','t'}; | |
//ota_app_AddService_UseKey(8,OTA_Passward_AscII); | |
ota_app_AddService(); | |
#if (0) | |
{ | |
uint8_t mtuSet = 247; | |
llInitFeatureSet2MPHY(TRUE); | |
llInitFeatureSetDLE(TRUE); | |
ATT_SetMTUSizeMax(mtuSet); | |
// LOG("[2Mbps | DLE | MTU %d] \n",mtuSet); | |
} | |
#else | |
ATT_SetMTUSizeMax(23); | |
llInitFeatureSet2MPHY(FALSE); | |
llInitFeatureSetDLE(FALSE); | |
#endif | |
// Setup a delayed profile startup | |
osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT ); | |
// for receive HCI complete message | |
GAP_RegisterForHCIMsgs(simpleBLEPeripheral_TaskID); | |
LL_PLUS_PerStats_Init(&g_perStatsByChanTest); | |
LOG("=====SimpleBLEPeripheral_Init Done=======\n"); | |
} | |
/********************************************************************* | |
* @fn SimpleBLEPeripheral_ProcessEvent | |
* | |
* @brief Simple BLE Peripheral Application Task event processor. This function | |
* is called to process all events for the task. Events | |
* include timers, messages and any other user defined events. | |
* | |
* @param task_id - The OSAL assigned task ID. | |
* @param events - events to process. This is a bit map and can | |
* contain more than one event. | |
* | |
* @return events not processed | |
*/ | |
uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events ) | |
{ | |
VOID task_id; // OSAL required parameter that isn't used in this function | |
if ( events & SYS_EVENT_MSG ) | |
{ | |
uint8 *pMsg; | |
if ( (pMsg = osal_msg_receive( simpleBLEPeripheral_TaskID )) != NULL ) | |
{ | |
simpleBLEPeripheral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); | |
// Release the OSAL message | |
VOID osal_msg_deallocate( pMsg ); | |
} | |
// return unprocessed events | |
return (events ^ SYS_EVENT_MSG); | |
} | |
if ( events & SBP_START_DEVICE_EVT ) | |
{ | |
// Start the Device | |
VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs ); | |
#if (DEF_GAPBOND_MGR_ENABLE==1) | |
// Start Bond Manager, 2017-11-15 | |
VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs ); | |
#endif | |
HCI_LE_ReadResolvingListSizeCmd(); | |
return ( events ^ SBP_START_DEVICE_EVT ); | |
} | |
// enable adv | |
if ( events & SBP_RESET_ADV_EVT ) | |
{ | |
uint8 initial_advertising_enable = TRUE; | |
GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); | |
return ( events ^ SBP_RESET_ADV_EVT ); | |
} | |
if(events & SBP_DEALDATA){ | |
LOG("\ndeal app datas in events!!!\n"); | |
return(events ^ SBP_DEALDATA); | |
} | |
// Discard unknown events | |
LOG("\n loop 1\n "); | |
return 0; | |
} | |
/********************************************************************* | |
* @fn simpleBLEPeripheral_ProcessOSALMsg | |
* | |
* @brief Process an incoming task message. | |
* | |
* @param pMsg - message to process | |
* | |
* @return none | |
*/ | |
static void simpleBLEPeripheral_ProcessOSALMsg( osal_event_hdr_t *pMsg ) | |
{ | |
hciEvt_CmdComplete_t *pHciMsg; | |
LOG("\n loop 2\n "); | |
switch ( pMsg->event ){ | |
case HCI_GAP_EVENT_EVENT:{ | |
switch( pMsg->status ){ | |
case HCI_COMMAND_COMPLETE_EVENT_CODE: | |
pHciMsg = (hciEvt_CmdComplete_t *)pMsg; | |
LOG("==> HCI_COMMAND_COMPLETE_EVENT_CODE: %x\n", pHciMsg->cmdOpcode); | |
//safeToDealloc = gapProcessHCICmdCompleteEvt( (hciEvt_CmdComplete_t *)pMsg ); | |
break; | |
default: | |
//safeToDealloc = FALSE; // Send to app | |
break; | |
} | |
} | |
} | |
} | |
/********************************************************************* | |
* @fn peripheralStateReadRssiCB | |
* | |
* @brief Notification from the profile of a state change. | |
* | |
* @param newState - new state | |
* | |
* @return none | |
*/ | |
static void peripheralStateReadRssiCB( int8 rssi ) | |
{ | |
} | |
/********************************************************************* | |
* @fn peripheralStateNotificationCB | |
* | |
* @brief Notification from the profile of a state change. | |
* | |
* @param newState - new state | |
* | |
* @return none | |
*/ | |
static void peripheralStateNotificationCB( gaprole_States_t newState ) | |
{ | |
switch ( newState ) | |
{ | |
case GAPROLE_STARTED: | |
{ | |
#if(0) | |
uint8 systemId[DEVINFO_SYSTEM_ID_LEN]; | |
// use 6 bytes of device address for 8 bytes of system ID value | |
systemId[0] = ownAddress[0]; | |
systemId[1] = ownAddress[1]; | |
systemId[2] = ownAddress[2]; | |
// set middle bytes to zero | |
systemId[4] = 0x00; | |
systemId[3] = 0x00; | |
// shift three bytes up | |
systemId[7] = ownAddress[5]; | |
systemId[6] = ownAddress[4]; | |
systemId[5] = ownAddress[3]; | |
DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId); | |
#endif | |
extern uint8 ownPublicAddr[LL_DEVICE_ADDR_LEN]; | |
// update MAC.Attention to the sequence of MAC address!!! | |
for(uint8 i = 0;i < LL_DEVICE_ADDR_LEN;i++){ | |
ownPublicAddr[i] = dev_mac_data[LL_DEVICE_ADDR_LEN - 1 - i]; | |
} | |
LOG("Gaprole_start:\n"); | |
osal_set_event(simpleBLEPeripheral_TaskID, SBP_RESET_ADV_EVT); | |
} | |
break; | |
case GAPROLE_ADVERTISING: | |
{ | |
LOG("Gaprole_adversting:\n"); | |
LOG_DUMP_BYTE(dev_mac_data, MAC_DATA_LEN); | |
} | |
break; | |
case GAPROLE_CONNECTED: | |
HCI_PPLUS_ConnEventDoneNoticeCmd(simpleBLEPeripheral_TaskID, NULL); | |
LOG("Gaprole_Connected:\n"); | |
LOG_DUMP_BYTE(dev_mac_data, MAC_DATA_LEN); | |
break; | |
case GAPROLE_CONNECTED_ADV: | |
break; | |
case GAPROLE_WAITING: | |
LOG("Gaprole_Disconnection:\n"); | |
LOG_DUMP_BYTE(dev_mac_data, MAC_DATA_LEN); | |
break; | |
case GAPROLE_WAITING_AFTER_TIMEOUT: | |
LOG("Gaprole_waitting_after_timerout:\n"); | |
break; | |
case GAPROLE_ERROR: | |
break; | |
default: | |
break; | |
} | |
gapProfileState = newState; | |
LOG("[GAP ROLE %d]\n",newState); | |
VOID gapProfileState; | |
} | |
/********************************************************************* | |
* @fn simpleProfileChangeCB | |
* | |
* @brief Callback from SimpleBLEProfile indicating a value change | |
* | |
* @param paramID - parameter ID of the value that was changed. | |
* | |
* @return none | |
*/ | |
//static void simpleProfileChangeCB( uint8 paramID ) | |
//{ | |
// | |
// switch( paramID ) | |
// { | |
// case SIMPLEPROFILE_CHAR1: | |
// | |
// break; | |
// default: | |
// // not process other attribute change | |
// break; | |
// } | |
//} | |
/********************************************************************* | |
*********************************************************************/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment