/********************************** (C) COPYRIGHT ******************************* * File Name : peripheral.C * Author : WCH * Version : V1.0 * Date : 2018/12/10 * Description : 外设从机多连接应用程序,初始化广播连接参数,然后广播,连接主机后, * 请求更新连接参数,通过自定义服务传输数据 *******************************************************************************/ /********************************************************************* * INCLUDES */ #include "CONFIG.h" #include "CH57x_common.h" #include "devinfoservice.h" #include "gattprofile.h" #include "peripheral.h" /********************************************************************* * MACROS */ /********************************************************************* * CONSTANTS */ // How often to perform periodic event #define SBP_PERIODIC_EVT_PERIOD 1600 // How often to perform read rssi event #define SBP_READ_RSSI_EVT_PERIOD /*3200*/4800 // Parameter update delay #define SBP_PARAM_UPDATE_DELAY 6400 // What is the advertising interval when device is discoverable (units of 625us, 80=50ms) #define DEFAULT_ADVERTISING_INTERVAL 80 // Limited discoverable mode advertises for 30.72s, and then stops // General discoverable mode advertises indefinitely #define DEFAULT_DISCOVERABLE_MODE GAP_ADTYPE_FLAGS_GENERAL // Minimum connection interval (units of 1.25ms, 20=25ms) #define DEFAULT_DESIRED_MIN_CONN_INTERVAL 20 // Maximum connection interval (units of 1.25ms, 100=125ms) #define DEFAULT_DESIRED_MAX_CONN_INTERVAL 100 // Slave latency to use parameter update #define DEFAULT_DESIRED_SLAVE_LATENCY 0 // Supervision timeout value (units of 10ms, 100=1s) #define DEFAULT_DESIRED_CONN_TIMEOUT 50 // Company Identifier: WCH #define WCH_COMPANY_ID 0x07D7 /********************************************************************* * TYPEDEFS */ /********************************************************************* * GLOBAL VARIABLES */ /********************************************************************* * EXTERNAL VARIABLES */ /********************************************************************* * EXTERNAL FUNCTIONS */ /********************************************************************* * LOCAL VARIABLES */ static uint8 Peripheral_TaskID = INVALID_TASK_ID; // Task ID for internal task/event processing static uint8 advertData[] = { // Flags; this sets the device to use limited discoverable // mode (advertises for 30 seconds at a time) instead of general // discoverable mode (advertises indefinitely) 0x02, // length of this data GAP_ADTYPE_FLAGS, DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, // service UUID, to notify central devices what services are included // in this peripheral 0x03, // length of this data GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all LO_UINT16( SIMPLEPROFILE_SERV_UUID ), HI_UINT16( SIMPLEPROFILE_SERV_UUID ) }; // GAP - SCAN RSP data (max size = 31 bytes) static uint8 scanRspData[31] = { // complete name 0x10, // length of this data GAP_ADTYPE_LOCAL_NAME_COMPLETE, 'B', 'L', 'V', '-', 'C', '1', ' ', 'R', 'C', 'U', ':', '8', '8', '8', '8', // connection interval range 0x05, // length of this data GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE, LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ), // 100ms HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ), LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ), // 1s HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ), // Tx power level // 0x02, // length of this data // GAP_ADTYPE_POWER_LEVEL, // 0 // 0dBm }; /************ **函 数:Set_BleDevice_Name **作 用:修改蓝牙名称 **参 数:rspData: 存放扫描信息的buff name:要修改的名字, len:名字的长度 **返回值:返回0成功 *************/ //uint8 Set_BleDevice_Name(uint8* name, u8 len) //{ // if(name == NULL || len == 0) return 1; //名字不能修改为空 // if(dataFlash_save_t.bleName_len == len && memcmp(name, &dataFlash_save_t.scanRspData[2], len) == 0) //蓝牙名未改变 // { // return 2; //名称相同 // } // memset(dataFlash_save_t.scanRspData, 0, 31); // //memset(attDeviceName, 0, BLE_DEVICE_NAME_LEN); // if(len < BLE_DEVICE_NAME_LEN) // { // memcpy(&dataFlash_save_t.scanRspData[2], name, len); // //memcpy(attDeviceName, name, len); // dataFlash_save_t.scanRspData[0] = len +1; // dataFlash_save_t.bleName_len = len; // } // else // { // memcpy(&dataFlash_save_t.scanRspData[2], name, BLE_DEVICE_NAME_LEN); // //memcpy(attDeviceName, name, BLE_DEVICE_NAME_LEN); // dataFlash_save_t.scanRspData[0] = BLE_DEVICE_NAME_LEN + 1; // dataFlash_save_t.bleName_len = BLE_DEVICE_NAME_LEN; // } // dataFlash_save_t.scanRspData[1] = GAP_ADTYPE_LOCAL_NAME_COMPLETE; // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+1] = 0x05; // length of this data // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+2] = GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE; // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+3] = LO_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ); // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+4] = HI_UINT16( DEFAULT_DESIRED_MIN_CONN_INTERVAL ); // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+5] = LO_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ); // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+6] = HI_UINT16( DEFAULT_DESIRED_MAX_CONN_INTERVAL ); // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+7] = 0x02; // length of this data // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+8] = GAP_ADTYPE_POWER_LEVEL; // dataFlash_save_t.scanRspData[dataFlash_save_t.scanRspData[0]+9] = 0; // 0dBm // // Set the GAP Characteristics 写 GAP 服务参数 // GGS_SetParameter( GGS_DEVICE_NAME_ATT, BLE_DEVICE_NAME_LEN, &dataFlash_save_t.scanRspData[2] ); // GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( dataFlash_save_t.scanRspData ), dataFlash_save_t.scanRspData ); // // dataFlash_save_t.flash_save_flg = 1; //标记需要保存 // return 0; //} // Connection item list /*static*/ peripheralConnItem_t peripheralConnList; /********************************************************************* * LOCAL FUNCTIONS */ static void Peripheral_ProcessTMOSMsg( tmos_event_hdr_t *pMsg ); static void peripheralStateNotificationCB( gapRole_States_t newState ,gapRoleEvent_t * pEvent); static void performPeriodicTask( void ); static void simpleProfileChangeCB( uint8 paramID ); static void peripheralParamUpdateCB( uint16 connHandle, uint16 connInterval, uint16 connSlaveLatency, uint16 connTimeout ); static void peripheralInitConnItem( peripheralConnItem_t* peripheralConnList ); static void peripheralRssiCB( uint16 connHandle, int8 rssi ); //static void peripheralChar4Notify( uint8 *pValue, uint16 len ); /********************************************************************* * PROFILE CALLBACKS */ // GAP Role Callbacks static gapRolesCBs_t Peripheral_PeripheralCBs = { peripheralStateNotificationCB, // Profile State Change Callbacks peripheralRssiCB, // When a valid RSSI is read from controller (not used by application) peripheralParamUpdateCB //参数更新完成回调 }; // GAP Bond Manager Callbacks static gapBondCBs_t Peripheral_BondMgrCBs = { NULL, // Passcode callback (not used by application) NULL // Pairing / Bonding state Callback (not used by application) }; // Simple GATT Profile Callbacks static simpleProfileCBs_t Peripheral_SimpleProfileCBs = { simpleProfileChangeCB // Charactersitic value change callback }; /********************************************************************* * PUBLIC FUNCTIONS */ /********************************************************************* * @fn Peripheral_Init * * @brief Initialization function for the 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 TMOS. This ID should be * used to send messages and set timers. * * @return none */ void Peripheral_Init( ) { Peripheral_TaskID = TMOS_ProcessEventRegister( Peripheral_ProcessEvent ); // Setup the GAP Peripheral Role Profile 设置GAP外围角色配置文件 { uint8 initial_advertising_enable = TRUE; uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; //最小连接间隔1(单位为1.25ms,20=25ms) uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; //最大连接间隔5(单位为1.25ms,100=25ms) // GAP - Advertisement data (max size = 31 bytes, though this is // best kept short to conserve power while advertisting) // Set the GAP Role Parameters 写 GAP Role 参数 GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); // GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( dataFlash_save_t.scanRspData ), dataFlash_save_t.scanRspData ); GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData ); GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval ); GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval ); } // Set the GAP Characteristics 写 GAP 服务参数 // GGS_SetParameter( GGS_DEVICE_NAME_ATT, dataFlash_save_t.bleName_len, &dataFlash_save_t.scanRspData[2] ); GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName ); // Set advertising interval { uint16 advInt = DEFAULT_ADVERTISING_INTERVAL; //广播间隔 //写 GAP 参数 GAP_SetParamValue( TGAP_DISC_ADV_INT_MIN, advInt ); GAP_SetParamValue( TGAP_DISC_ADV_INT_MAX, advInt ); } // Setup the GAP Bond Manager { uint32 passkey = 0; // passkey "000000" uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; //等待配对请求或从属安全请求 uint8 mitm = TRUE; uint8 bonding = TRUE; uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; ////仅显示设备 //写绑定相关参数 GAPBondMgr_SetParameter( GAPBOND_PERI_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey ); //MITM保护的默认密码。长度为uint32。范围是0-999999。默认值为0。 GAPBondMgr_SetParameter( GAPBOND_PERI_PAIRING_MODE, sizeof ( uint8 ), &pairMode ); //配对模式:@ref GAPBOND_Pairing_Mode_defined。读/写。大小是uint8。默认为GAPBOND_PAIRING_MODE_WAIT_REQ等待配对请求。 GAPBondMgr_SetParameter( GAPBOND_PERI_MITM_PROTECTION, sizeof ( uint8 ), &mitm ); //密钥保护,读/写。大小是uint8。默认值为0(禁用)。此处打开 GAPBondMgr_SetParameter( GAPBOND_PERI_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap ); //I/O功能。读/写。大小是uint8。默认值为仅显示设备 GAPBondMgr_SetParameter( GAPBOND_PERI_BONDING_ENABLED, sizeof ( uint8 ), &bonding ); //如果启用,将在配对过程中请求绑定。读/写。尺寸是uint8。默认值为0(禁用)。此处打开 } // 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 // Setup the SimpleProfile Characteristic Values { // uint8 charValue1[SIMPLEPROFILE_CHAR1_LEN] = { 1 }; // uint8 charValue2[SIMPLEPROFILE_CHAR2_LEN] = {192,168,1,94}; //uint8 charValue3[SIMPLEPROFILE_CHAR3_LEN] = { 3 }; // uint8 charValue4[SIMPLEPROFILE_CHAR4_LEN] = { 4 }; // uint8 charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 }; // SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR1, SIMPLEPROFILE_CHAR1_LEN, charValue1 ); // SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR2, SIMPLEPROFILE_CHAR2_LEN, charValue2 ); //SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR3, SIMPLEPROFILE_CHAR3_LEN, charValue3 ); // SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR4, SIMPLEPROFILE_CHAR4_LEN, charValue4 ); // SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5 ); } // Init Connection Item peripheralInitConnItem( &peripheralConnList ); // Register callback with SimpleGATTprofile //注册回调 SimpleProfile_RegisterAppCBs( &Peripheral_SimpleProfileCBs ); // Setup a delayed profile startup //设置延迟的配置文件启动 tmos_set_event( Peripheral_TaskID, SBP_START_DEVICE_EVT ); } /********************************************************************* * @fn peripheralInitConnItem * * @brief Init Connection Item * * @param peripheralConnList - * * @return NULL */ static void peripheralInitConnItem( peripheralConnItem_t* peripheralConnList ) { peripheralConnList->connHandle = GAP_CONNHANDLE_INIT; peripheralConnList->connInterval = 0; peripheralConnList->connSlaveLatency = 0; peripheralConnList->connTimeout = 0; } /********************************************************************* * @fn Peripheral_ProcessEvent * * @brief 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 TMOS 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 Peripheral_ProcessEvent( uint8 task_id, uint16 events ) { // VOID task_id; // TMOS required parameter that isn't used in this function if ( events & SYS_EVENT_MSG ){ uint8 *pMsg; if ( (pMsg = tmos_msg_receive( Peripheral_TaskID )) != NULL ){ Peripheral_ProcessTMOSMsg( (tmos_event_hdr_t *)pMsg ); // Release the TMOS message tmos_msg_deallocate( pMsg ); } // return unprocessed events return (events ^ SYS_EVENT_MSG); } if ( events & SBP_START_DEVICE_EVT ){ // Start the Device GAPRole_PeripheralStartDevice( Peripheral_TaskID, &Peripheral_BondMgrCBs, &Peripheral_PeripheralCBs ); return ( events ^ SBP_START_DEVICE_EVT ); } if ( events & SBP_PERIODIC_EVT ) { // Restart timer // if ( SBP_PERIODIC_EVT_PERIOD ){ // tmos_start_task( Peripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD ); // } // Perform periodic application task 执行定期应用任务 //performPeriodicTask(); //定期发送通知 return (events ^ SBP_PERIODIC_EVT); } if ( events & SBP_PARAM_UPDATE_EVT ) //参数更新 { // Send connect param update request //发送连接参数更新请求 GAPRole_PeripheralConnParamUpdateReq( peripheralConnList.connHandle, DEFAULT_DESIRED_MIN_CONN_INTERVAL, DEFAULT_DESIRED_MAX_CONN_INTERVAL, DEFAULT_DESIRED_SLAVE_LATENCY, DEFAULT_DESIRED_CONN_TIMEOUT, Peripheral_TaskID); return (events ^ SBP_PARAM_UPDATE_EVT); } if ( events & SBP_READ_RSSI_EVT ) { GAPRole_ReadRssiCmd(peripheralConnList.connHandle); tmos_start_task( Peripheral_TaskID, SBP_READ_RSSI_EVT, SBP_READ_RSSI_EVT_PERIOD ); return (events ^ SBP_READ_RSSI_EVT); } // Discard unknown events return 0; } /********************************************************************* * @fn Peripheral_ProcessTMOSMsg * * @brief Process an incoming task message. * * @param pMsg - message to process * * @return none */ static void Peripheral_ProcessTMOSMsg( tmos_event_hdr_t *pMsg ) { switch ( pMsg->event ){ default: break; } } /********************************************************************* * @fn Peripheral_LinkEstablished * * @brief Process link established. * * @param pEvent - event to process * * @return none */ static void Peripheral_LinkEstablished( gapRoleEvent_t * pEvent ) { gapEstLinkReqEvent_t *event = (gapEstLinkReqEvent_t *) pEvent; // See if already connected if( peripheralConnList.connHandle != GAP_CONNHANDLE_INIT ) { GAPRole_TerminateLink( pEvent->linkCmpl.connectionHandle ); PRINT( "Connection max...\n" ); } else { peripheralConnList.connHandle = event->connectionHandle; peripheralConnList.connInterval = event->connInterval; peripheralConnList.connSlaveLatency = event->connLatency; peripheralConnList.connTimeout = event->connTimeout; // Set timer for periodic event tmos_start_task( Peripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD ); // Set timer for param update event tmos_start_task( Peripheral_TaskID, SBP_PARAM_UPDATE_EVT, SBP_PARAM_UPDATE_DELAY ); // Start read rssi tmos_start_task( Peripheral_TaskID, SBP_READ_RSSI_EVT, SBP_READ_RSSI_EVT_PERIOD ); printf("Conn %x - Int %x \n", event->connectionHandle, event->connInterval); } } /********************************************************************* * @fn Peripheral_LinkTerminated * * @brief Process link terminated. * * @param pEvent - event to process * * @return none */ static void Peripheral_LinkTerminated( gapRoleEvent_t * pEvent ) { gapTerminateLinkEvent_t *event = (gapTerminateLinkEvent_t *) pEvent; if( event->connectionHandle == peripheralConnList.connHandle ) { peripheralConnList.connHandle = GAP_CONNHANDLE_INIT; peripheralConnList.connInterval = 0; peripheralConnList.connSlaveLatency = 0; peripheralConnList.connTimeout = 0; tmos_stop_task( Peripheral_TaskID, SBP_PERIODIC_EVT ); tmos_stop_task( Peripheral_TaskID, SBP_READ_RSSI_EVT ); // Restart advertising { uint8 advertising_enable = TRUE; GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &advertising_enable ); } } else { PRINT("ERR..\n"); } } /********************************************************************* * @fn peripheralRssiCB * * @brief RSSI callback. * * @param connHandle - connection handle * @param rssi - RSSI * * @return none */ static void peripheralRssiCB( uint16 connHandle, int8 rssi ) { PRINT( "RSSI -%d dB Conn %x \n", -rssi, connHandle); } /********************************************************************* * @fn peripheralParamUpdateCB * * @brief Parameter update complete callback * * @param connHandle - connect handle * connInterval - connect interval * connSlaveLatency - connect slave latency * connTimeout - connect timeout * * @return none */ static void peripheralParamUpdateCB( uint16 connHandle, uint16 connInterval, uint16 connSlaveLatency, uint16 connTimeout ) { if( connHandle == peripheralConnList.connHandle ) { peripheralConnList.connInterval = connInterval; peripheralConnList.connSlaveLatency = connSlaveLatency; peripheralConnList.connTimeout = connTimeout; printf("Update %x - Int %x \n", connHandle, connInterval); } else { PRINT("ERR..\n"); } } /********************************************************************* * @fn peripheralStateNotificationCB * * @brief Notification from the profile of a state change. * * @param newState - new state * * @return none */ static void peripheralStateNotificationCB( gapRole_States_t newState, gapRoleEvent_t * pEvent ) { switch ( newState ) { case GAPROLE_STARTED: PRINT( "Initialized..\n" ); break; case GAPROLE_ADVERTISING: if( pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT ) //gap连接结束 { Peripheral_LinkTerminated( pEvent ); PRINT( "Disconnected..Reason:%x\n", pEvent->linkTerminate.reason ); } PRINT( "Advertising..\n" ); break; case GAPROLE_CONNECTED: if( pEvent->gap.opcode == GAP_LINK_ESTABLISHED_EVENT ) //GAP建立连接 { Peripheral_LinkEstablished( pEvent ); } PRINT( "Connected..\n" ); break; case GAPROLE_CONNECTED_ADV: // PRINT( "Connected Advertising..\n" ); break; case GAPROLE_WAITING: if( pEvent->gap.opcode == GAP_END_DISCOVERABLE_DONE_EVENT ) { PRINT( "Waiting for advertising..\n" ); } else if( pEvent->gap.opcode == GAP_LINK_TERMINATED_EVENT ) { Peripheral_LinkTerminated( pEvent ); PRINT( "Disconnected..Reason:%x\n", pEvent->linkTerminate.reason ); } break; case GAPROLE_ERROR: PRINT( "Error..\n" ); break; default: break; } } /********************************************************************* * @fn performPeriodicTask * * @brief Perform a periodic application task. This function gets * called every five seconds as a result of the SBP_PERIODIC_EVT * TMOS event. In this example, the value of the third * characteristic in the SimpleGATTProfile service is retrieved * from the profile, and then copied into the value of the * the fourth characteristic. * 定时通知任务 * @param none * * @return none */ static void performPeriodicTask( void ) { static uint8 count = 0; uint8 notiData[SIMPLEPROFILE_CHAR4_LEN] = "Notify:"; sprintf((char*)¬iData[7], "%d", ++count); peripheralChar4Notify( notiData, strlen((char*)notiData) ); } /********************************************************************* * @fn peripheralChar4Notify * * @brief Prepare and send simpleProfileChar4 notification * * @param pValue - data to notify * len - length of data * * @return none */ /*static*/ void peripheralChar4Notify( uint8 *pValue, uint16 len ) { attHandleValueNoti_t noti; noti.len = len; noti.pValue = GATT_bm_alloc( peripheralConnList.connHandle, ATT_HANDLE_VALUE_NOTI, noti.len, NULL, 0 ); tmos_memcpy( noti.pValue, pValue, noti.len ); if( simpleProfile_Notify( peripheralConnList.connHandle, ¬i ) != SUCCESS ) { GATT_bm_free( (gattMsg_t *)¬i, ATT_HANDLE_VALUE_NOTI ); } } /********************************************************************* * @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: { uint8 newValue[SIMPLEPROFILE_CHAR1_LEN]; SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR1, newValue ); PRINT("profile ChangeCB CHAR1.. \n"); break; } case SIMPLEPROFILE_CHAR3: { uint8 newValue[GAP_DEVICE_NAME_LEN]; SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR3, newValue ); PRINT("profile ChangeCB CHAR3..\n"); break; } default: // should not reach here! break; } } /********************************************************************* *********************************************************************/