#define HABR_UUID(uuid) 0x66, 0x9a, 0x0c, 0x20, 0x00, 0x08, 0xa9, 0xb4, 0xe4, 0x11, 0xd7, 0x85, uuid, 0x50 , 0x2e, 0x51 #define HH_BUTTON1_STATE_ATTR 0 #define HH_BUTTON2_STATE_ATTR 1 #define HH_CHANNEL1_PWM_ATTR 2 #define HH_CHANNEL2_PWM_ATTR 3 #define HH_SERVICE_UUID 0x10 #define HH_BUTTON1_STATE_UUID 0x11 #define HH_BUTTON2_STATE_UUID 0x12 #define HH_CHANNEL1_PWM_UUID 0x13 #define HH_CHANNEL2_PWM_UUID 0x14 #define HH_SERVICE 0x00000001 typedef void (*habrControlCB_t)( uint8 paramID ) ; typedef struct { habrControlCB_t pfnHabrCB; // Called when some att changed } HarbCBs_t; extern bStatus_t Habr_AddService(); extern bStatus_t Habr_RegisterAppCBs( HarbCBs_t *appCallbacks ); extern bStatus_t Habr_SetParameter( uint8 param, uint8 len, void *value ); extern bStatus_t Habr_GetParameter( uint8 param, void *value );
CONST uint8 HhServUUID[ATT_UUID_SIZE] = { HABR_UUID(HH_SERVICE_UUID) };
static uint8 hhButton1CharProps = GATT_PROP_NOTIFY; // static uint8 hhButton1Value = 0x00; // static gattCharCfg_t hhButton1Config[GATT_MAX_NUM_CONN]; // - NOTIFY static uint8 hhButton1UserDesc[]="Button 1 variable\0"; //
{ gattAttrType_t type; // handle UUID . uint8 permissions; // . uint16 handle; // - 0. uint8* const pValue; // ( 512 ). }
#include "bcomdef.h" #include "OSAL.h" #include "linkdb.h" #include "att.h" #include "gatt.h" #include "gatt_uuid.h" #include "gattservapp.h" #include "habrprofile.h" #include "OSAL_Clock.h" #define SERVAPP_NUM_ATTR_SUPPORTED 15 #define UUID_SIZE 16 CONST uint8 hhServUUID[ATT_UUID_SIZE] = { HABR_UUID(HH_SERVICE_UUID) }; CONST uint8 hhButton1UUID[ATT_UUID_SIZE] = { HABR_UUID(HH_BUTTON1_STATE_UUID) }; CONST uint8 hhButton2UUID[ATT_UUID_SIZE] = { HABR_UUID(HH_BUTTON2_STATE_UUID) }; CONST uint8 hhPWM1UUID[ATT_UUID_SIZE] = { HABR_UUID(HH_CHANNEL1_PWM_UUID) }; CONST uint8 hhPWM2UUID[ATT_UUID_SIZE] = { HABR_UUID(HH_CHANNEL2_PWM_UUID) }; static HarbCBs_t *habrahabrAppCBs_t = NULL; //attribute definitions static CONST gattAttrType_t hhService = {ATT_UUID_SIZE, hhServUUID}; static uint8 hhButton1CharProps = GATT_PROP_NOTIFY; static uint8 hhButton1Value = 0x00; static gattCharCfg_t hhButton1Config[GATT_MAX_NUM_CONN]; static uint8 hhButton1UserDesc[]="Button 1 variable\0"; static uint8 hhButton2CharProps = GATT_PROP_NOTIFY|GATT_PROP_READ; static uint8 hhButton2Value = 0x00; static gattCharCfg_t hhButton2Config[GATT_MAX_NUM_CONN]; static uint8 hhButton2UserDesc[]="Button 2 variable\0"; static uint8 hhPWM1CharProps = GATT_PROP_READ | GATT_PROP_WRITE; static uint8 hhPWM1Value = 0x00; static uint8 hhPWM1UserDesc[] = "PWM 1 variable\0"; static uint8 hhPWM2CharProps = GATT_PROP_READ | GATT_PROP_WRITE; static uint8 hhPWM2Value = 0x00; static uint8 hhPWM2UserDesc[] = "PWM 2 variable\0"; //attribute table static gattAttribute_t HabrProfileAttrTable[15]={ //Service { { ATT_BT_UUID_SIZE, primaryServiceUUID }, GATT_PERMIT_READ, 0, (uint8 *)&hhServUUID }, //Button1 { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &hhButton1CharProps }, { {UUID_SIZE, hhButton1UUID }, 0, 0, (uint8 *)&hhButton1Value }, { {ATT_BT_UUID_SIZE , clientCharCfgUUID}, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8 *)hhButton1Config }, { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, hhButton1UserDesc } , //Button2 { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &hhButton2CharProps }, { {UUID_SIZE, hhButton2UUID }, GATT_PERMIT_READ, 0, (uint8 *)&hhButton2Value }, { {ATT_BT_UUID_SIZE , clientCharCfgUUID}, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8 *)hhButton2Config }, { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, hhButton2UserDesc } , //PWM channel 1 { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &hhPWM1CharProps }, { {UUID_SIZE, hhPWM1UUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8*)&hhPWM1Value }, { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, hhPWM1UserDesc } , //PWM channel 2 { { ATT_BT_UUID_SIZE, characterUUID }, GATT_PERMIT_READ, 0, &hhPWM2CharProps }, { {UUID_SIZE, hhPWM2UUID }, GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8*)&hhPWM2Value }, { { ATT_BT_UUID_SIZE, charUserDescUUID }, GATT_PERMIT_READ, 0, hhPWM2UserDesc } };
static uint8 hh_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ); static bStatus_t hh_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ); static void hh_HandleConnStatusCB( uint16 connHandle, uint8 changeType ); CONST gattServiceCBs_t HH_CBs = { hh_ReadAttrCB, // Read callback function pointer hh_WriteAttrCB, // Write callback function pointer NULL };
bStatus_t Habr_AddService() { uint8 status = SUCCESS; GATTServApp_InitCharCfg( INVALID_CONNHANDLE, hhButton1Config ); GATTServApp_InitCharCfg( INVALID_CONNHANDLE, hhButton2Config ); VOID linkDB_Register( hh_HandleConnStatusCB ); status = GATTServApp_RegisterService(HabrProfileAttrTable, GATT_NUM_ATTRS(HabrProfileAttrTable), &HH_CBs ); return ( status ); }
bStatus_t Habr_RegisterAppCBs( HarbCBs_t *appCallbacks ){ if ( appCallbacks ) { habrahabrAppCBs_t = appCallbacks; return ( SUCCESS ); } else { return ( bleAlreadyInRequestedMode ); } } bStatus_t Habr_SetParameter( uint8 param, uint8 len, void *value ){ bStatus_t ret = SUCCESS; switch ( param ) { case HH_BUTTON1_STATE_ATTR: if(len == sizeof(uint8)) { hhButton1Value = *((uint8*)value); GATTServApp_ProcessCharCfg (hhButton1Config, (uint8 *)&hhButton1Value, FALSE, HabrProfileAttrTable ,GATT_NUM_ATTRS(HabrProfileAttrTable), INVALID_TASK_ID); } else{ ret = bleInvalidRange; } break; case HH_BUTTON2_STATE_ATTR: if(len == sizeof(uint8)) { hhButton2Value = *((uint8*)value); GATTServApp_ProcessCharCfg (hhButton2Config, (uint8 *)&hhButton2Value, FALSE, HabrProfileAttrTable ,GATT_NUM_ATTRS(HabrProfileAttrTable), INVALID_TASK_ID); } else{ ret = bleInvalidRange; } break; case HH_CHANNEL1_PWM_ATTR: if(len == sizeof(uint8)) { hhPWM1Value = *((uint8*)value); } else{ ret = bleInvalidRange; } break; case HH_CHANNEL2_PWM_ATTR: if(len == sizeof(uint8)) { hhPWM2Value = *((uint8*)value); } else{ ret = bleInvalidRange; } break; default: ret = INVALIDPARAMETER; break; } return(ret); }
static uint8 hh_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ) { bStatus_t status = SUCCESS; if ( offset > 0 ) { return ( ATT_ERR_ATTR_NOT_LONG ); } if ( pAttr->type.len == ATT_UUID_SIZE ) { // 128-bit UUID uint8 uuid[ATT_UUID_SIZE]; osal_memcpy(uuid, pAttr->type.uuid, ATT_UUID_SIZE); if(osal_memcmp(uuid,hhPWM2UUID,ATT_UUID_SIZE)|| osal_memcmp(uuid,hhPWM1UUID,ATT_UUID_SIZE)|| osal_memcmp(uuid,hhButton2UUID,ATT_UUID_SIZE)|| osal_memcmp(uuid,hhButton1UUID,ATT_UUID_SIZE)) { *pLen = 1; pValue[0] = *pAttr->pValue; } } else { // 16-bit UUID *pLen = 0; status = ATT_ERR_INVALID_HANDLE; } return ( status ); } }
static bStatus_t hh_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr, uint8 *pValue, uint8 len, uint16 offset ){ bStatus_t status = SUCCESS; uint8 notify = 0xFF; if ( pAttr->type.len == ATT_UUID_SIZE ) { const uint8 uuid[ATT_UUID_SIZE] = { HABR_UUID(pAttr->type.uuid[12]) }; if(osal_memcmp(uuid,hhPWM1UUID,ATT_UUID_SIZE)) { if ( offset == 0 ) { if ( len != 1 ){ status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; notify = HH_CHANNEL1_PWM_ATTR; } } else if(osal_memcmp(uuid,hhPWM2UUID,ATT_UUID_SIZE)){ if ( offset == 0 ) { if ( len != 1 ){ status = ATT_ERR_INVALID_VALUE_SIZE; } } else { status = ATT_ERR_ATTR_NOT_LONG; } if ( status == SUCCESS ) { uint8 *pCurValue = (uint8 *)pAttr->pValue; *pCurValue = pValue[0]; notify = HH_CHANNEL2_PWM_ATTR; } } } else if (pAttr->type.len== ATT_BT_UUID_SIZE) { uint16 uuid= BUILD_UINT16(pAttr->type.uuid[0],pAttr->type.uuid[1]); switch(uuid){ case GATT_CLIENT_CHAR_CFG_UUID: status=GATTServApp_ProcessCCCWriteReq(connHandle, pAttr, pValue, len, offset, GATT_CLIENT_CFG_NOTIFY); break; default: status = ATT_ERR_ATTR_NOT_FOUND; } } else{ status = ATT_ERR_INVALID_HANDLE; } // If an attribute changed then callback function to notify application of change if ( (notify != 0xFF) && habrahabrAppCBs_t && habrahabrAppCBs_t->pfnHabrCB ) habrahabrAppCBs_t->pfnHabrCB(notify); return ( status ); }
static void hh_HandleConnStatusCB( uint16 connHandle, uint8 changeType ){ if ( connHandle != LOOPBACK_CONNHANDLE ) { if ( ( changeType == LINKDB_STATUS_UPDATE_REMOVED ) || ( ( changeType == LINKDB_STATUS_UPDATE_STATEFLAGS ) && ( !linkDB_Up( connHandle ) ) ) ) { GATTServApp_InitCharCfg ( connHandle, hhButton1Config); GATTServApp_InitCharCfg ( connHandle, hhButton2Config); } } }
static void habrProfileCB (uint8 paramID); static HarbCBs_t HabrProfCBStruct = { habrProfileCB // Characteristic value change callback };
Habr_AddService(); Habr_RegisterAppCBs(&HabrProfCBStruct);
static void habrProfileCB (uint8 paramID){ uint8 u8buffer; switch(paramID){ case HH_CHANNEL1_PWM_ATTR: Habr_GetParameter(HH_CHANNEL1_PWM_ATTR, &u8buffer); Habr_SetParameter(HH_BUTTON1_STATE_ATTR, sizeof(uint8), &u8buffer); break; case HH_CHANNEL2_PWM_ATTR: Habr_GetParameter(HH_CHANNEL2_PWM_ATTR, &u8buffer); Habr_SetParameter(HH_BUTTON2_STATE_ATTR, sizeof(uint8), &u8buffer); break; default: break; } }
Source: https://habr.com/ru/post/246089/
All Articles