extern void GattOnConnection(uint16 st_ucid)
{
    uint8 dev_index = AppGetConnectedDeviceIndex();

    uint8 service_changed_data[4];

    service_changed_data[0] = WORD_LSB((HANDLE_GATT_SERVICE_END+1));
    service_changed_data[1] = WORD_MSB((HANDLE_GATT_SERVICE_END+1));
    service_changed_data[2] = WORD_LSB(ATT_HIGHEST_POSSIBLE_HANDLE);
    service_changed_data[3] = WORD_MSB(ATT_HIGHEST_POSSIBLE_HANDLE);


    if((g_gatt_data.serv_changed[dev_index]) &&
       (g_gatt_data.serv_changed_config[dev_index] == 
                            gatt_client_config_indication))
    {
        GattCharValueIndication(st_ucid,
                                HANDLE_SERVICE_CHANGED,
                                sizeof(service_changed_data),
                                service_changed_data);

        /* Now that the indication has been sent, clear the flag in the NVM */
        g_gatt_data.serv_changed[dev_index] = FALSE;

        Nvm_Write((uint16*)&(g_gatt_data.serv_changed[dev_index]),
                 sizeof(g_gatt_data.serv_changed[dev_index]),
                 (g_gatt_data.nvm_offset + SERV_CHANGED_SEND_IND(dev_index)));
    }
}
extern app_time_error_code ConfigureCTSNotification(bool disable_notify)
{
    if(g_time_serv_data.notify_configured == TRUE)
    {
        return error_success;
    }

    /* if current time service supported by the server enable
     * for notifications.
     */
    if(g_time_serv_data.connected_device_services & cts_supported)
    {
        sys_status ret = sys_status_success;

        /* Set the value to disable notification on the client config handle */
        uint8 notification_enabled[2] =
                        { WORD_LSB(gatt_client_config_none),
                          WORD_MSB(gatt_client_config_none)};

        if(g_time_serv_data.conf_handle_ptr)
        {
            /* since it is already busy */
            return error_cmd_inprogress;
        }

        /* enable the notification if disabling is set to false. normally
         * it will be enabled.
         */
        if(disable_notify == FALSE)
        {
            notification_enabled[0] = WORD_LSB(gatt_client_config_notification);
            notification_enabled[1] = WORD_MSB(gatt_client_config_notification);
        }

        /* Start with enabling notifications on client configuration
         * descriptors of current time characteristic.
         */
        g_time_serv_data.conf_handle_ptr = &g_time_serv_data.cur_time_ccd_hndl;

        /* Send the write request */
        ret = GattWriteCharValueReq(GetConnectionID(),
                              GATT_WRITE_REQUEST,
                              g_time_serv_data.cur_time_ccd_hndl,
                              sizeof(notification_enabled) /*size_value*/,
                              notification_enabled);
        if(ret != sys_status_success)
        {
            g_time_serv_data.conf_handle_ptr = NULL;
            return error_not_ready;
        }
    }

    return error_success;
}
示例#3
0
/*----------------------------------------------------------------------------*
 *  NAME
 *      startBeaconing
 *
 *  DESCRIPTION
 *      This function is called to start beacon advertisements
 *
 *  RETURNS
 *      Nothing.
 *
 *---------------------------------------------------------------------------*/
void startBeaconing(void)
{
    uint8 advData[BEACON_ADVERT_SIZE];
    uint16 offset = 0;
    
    /* set the GAP Broadcaster role */
    GapSetMode(gap_role_broadcaster,
               gap_mode_discover_no,
               gap_mode_connect_no,
               gap_mode_bond_no,
               gap_mode_security_none);
    
    /* clear the existing advertisement data */
    LsStoreAdvScanData(0, NULL, ad_src_advertise);

    /* set the advertisement interval */
    GapSetAdvInterval(BEACON_ADVERTISING_INTERVAL_MIN, BEACON_ADVERTISING_INTERVAL_MAX);
    
    /* store the manufacturing data */
    advData[offset++] = AD_TYPE_MANUF;

    /* Apple company code, little endian */
    advData[offset++] = 0x4C;
    advData[offset++] = 0x00;
    
    advData[offset++] = 2;         /* Magic number */
    advData[offset++] = 0x15;      /* Length of the beacon payload */
    
    /* Beacon UUID */
    MemCopy(advData + offset, g_app_data.uuid, sizeof(g_app_data.uuid));
    offset += sizeof(g_app_data.uuid);

    /* Beacon major */
    advData[offset++] = WORD_MSB(g_app_data.major);
    advData[offset++] = WORD_LSB(g_app_data.major);
    
    /* Beacon minor */
    advData[offset++] = WORD_MSB(g_app_data.minor);
    advData[offset++] = WORD_LSB(g_app_data.minor);

    /* Beacon TX Power */
    advData[offset++] = g_app_data.txPower;

    /* store the advertisement data */
    LsStoreAdvScanData(BEACON_ADVERT_SIZE, advData, ad_src_advertise);
    
    /* Start broadcasting */
    LsStartStopAdvertise(TRUE, whitelist_disabled, ls_addr_type_random);
}
示例#4
0
int timer_set_square(unsigned long timer, unsigned long freq) {
	if (freq == 0)
	{
		return 1; // The frequency can't be set to 0.
	}
	if (freq > TIMER_FREQ)
	{
		return 1; // The number to put in the counter can't be lower than 1. TIMER_FREQ + 1 doesn't cause problems because the result is truncated, but if the user/programmer uses that value he's probably doing something wrong.
	}
	freq = TIMER_FREQ / freq;
	int BCD;
	if ((BCD = get_timer_BCD(timer)) == -1)
	{
		return 1; // Error obtaining the least significant bit from the status byte.
	}
	if (((BCD == TIMER_BCD) && freq > MAX_BCD_IN_WORD) || freq > MAX_BINARY_IN_WORD)
	{
		return 1; // The counter only accepts numbers with a maximum of 16 bits.
	}
	unsigned char timer_bit, timer_port;
	switch (timer)
	{
	case 0:
		timer_bit = TIMER_SEL0;
		timer_port = TIMER_0;
		break;
	case 1:
		timer_bit = TIMER_SEL1;
		timer_port = TIMER_1;
		break;
	case 2:
		timer_bit = TIMER_SEL2;
		timer_port = TIMER_2;
		break;
	default:
		return 1;
	}
	switch (get_timer_BCD(timer))
	{
	case TIMER_BIN:
		if (sys_outb(TIMER_CTRL, timer_bit | TIMER_SQR_WAVE | TIMER_LSB_MSB | TIMER_BIN) == OK)
		{
			if (sys_outb(timer_port, WORD_LSB((unsigned)freq)) == OK)
			{
				return sys_outb(timer_port, WORD_MSB((unsigned)(freq)));
			}
		}
		return 1;
	case TIMER_BCD:
		if (sys_outb(TIMER_CTRL, timer_bit | TIMER_SQR_WAVE | TIMER_LSB_MSB | TIMER_BCD) == OK)
		{
			if (sys_outb(timer_port, WORD_LSB(binary_to_BCD((unsigned)freq))) == OK)
			{
				return sys_outb(timer_port, WORD_MSB(binary_to_BCD((unsigned)(freq))));
			}
		}
		return 1;
	default:	// -1
		return 1;
	}
}
示例#5
0
/*----------------------------------------------------------------------------*
 *  NAME
 *      gattSetAdvertParams
 *
 *  DESCRIPTION
 *      This function is used to set advertisement parameters.
 *
 *  PARAMETERS
 *      p_addr [in]             Bonded host address
 *      fast_connection [in]    TRUE:  Fast advertisements
 *                              FALSE: Slow advertisements
 *
 *  RETURNS
 *      Nothing
 *----------------------------------------------------------------------------*/
static void gattSetAdvertParams(TYPED_BD_ADDR_T *p_addr, bool fast_connection)
{
    uint8 advert_data[MAX_ADV_DATA_LEN];/* Advertisement packet */
    uint16 length;                      /* Length of advertisement packet */
    /* Advertisement interval, microseconds */
    uint32 adv_interval_min;
    uint32 adv_interval_max;

    /* Tx power level value prefixed with 'Tx Power' AD Type */
    /* Refer to BT4.0 specification, Vol3-part-C-Section-11.1.5 */ 
    uint8 device_tx_power[TX_POWER_VALUE_LENGTH] = {
                AD_TYPE_TX_POWER
                };

    /* Device appearance */
    uint8 device_appearance[ATTR_LEN_DEVICE_APPEARANCE + 1] = {
                AD_TYPE_APPEARANCE,
                WORD_LSB(APPEARANCE_APPLICATION_VALUE),
                WORD_MSB(APPEARANCE_APPLICATION_VALUE)
                };

    /* A variable to keep track of the data added to advert_data. The limit is 
     * MAX_ADV_DATA_LEN. GAP layer will add AD Flags to advert_data which is 3
     * bytes. Refer BT Spec 4.0, Vol 3, Part C, Sec 11.1.3:
     *
     * First byte is length
     * second byte is AD TYPE = 0x1
     * Third byte is Flags description 
     */
    uint16 length_added_to_adv = 3;

    if(fast_connection)
    {
        adv_interval_min = FC_ADVERTISING_INTERVAL_MIN;
        adv_interval_max = FC_ADVERTISING_INTERVAL_MAX;
    }

    if((GapSetMode(gap_role_peripheral, gap_mode_discover_general,
                        gap_mode_connect_undirected, 
                        gap_mode_bond_yes,
                        gap_mode_security_unauthenticate) != ls_err_none) ||
       (GapSetAdvInterval(adv_interval_min, adv_interval_max) 
                        != ls_err_none))
    {
        ReportPanic(app_panic_set_advert_params);
    }

    /* Add bonded device to white list.*/
    if(IsWhiteListEnabled())
    {
        /* Initial case when advertisements are started for Bonded host for 
         * 10 seconds. White list is configured with the Bonded host address
         */
        if(LsAddWhiteListDevice(p_addr)!= ls_err_none)
        {
            ReportPanic(app_panic_add_whitelist);
        }
    }

    /* Reset existing advertising data */
    if(LsStoreAdvScanData(0, NULL, ad_src_advertise) != ls_err_none)
    {
        ReportPanic(app_panic_set_advert_data);
    }

    /* Reset existing scan response data */
    if(LsStoreAdvScanData(0, NULL, ad_src_scan_rsp) != ls_err_none)
    {
        ReportPanic(app_panic_set_scan_rsp_data);
    }

    /* Setup ADVERTISEMENT DATA */

    /* Add UUID list of the services supported by the device */
    length = GetSupportedUUIDServiceList(advert_data);

    /* One added for Length field, which will be added to Adv Data by GAP 
     * layer 
     */
    length_added_to_adv += (length + 1);

    if (LsStoreAdvScanData(length, advert_data, 
                        ad_src_advertise) != ls_err_none)
    {
        ReportPanic(app_panic_set_advert_data);
    }

    /* One added for Length field, which will be added to Adv Data by GAP 
     * layer 
     */
    length_added_to_adv += (sizeof(device_appearance) + 1);

    /* Add device appearance to the advertisements */
    if (LsStoreAdvScanData(ATTR_LEN_DEVICE_APPEARANCE + 1, 
        device_appearance, ad_src_advertise) != ls_err_none)
    {
        ReportPanic(app_panic_set_advert_data);
    }

    /* Change the Radio and Adv tx params for CONFIG mode */
    
    /* Update the radio tx power level here */
    LsSetTransmitPowerLevel(RADIO_TX_POWER_CONFIG); 

    /* Update the adv tx power level here */
    device_tx_power[TX_POWER_VALUE_LENGTH - 1] = ADV_TX_POWER_CONFIG;
    
    /* NOTE: The 2 tx params above are reset to the tx_power_mode on disconnection */

    /* One added for Length field, it will be added to Adv Data by GAP layer */
    length_added_to_adv += (TX_POWER_VALUE_LENGTH + 1);

    /* Add tx power value of device to the advertising data */
    if (LsStoreAdvScanData(TX_POWER_VALUE_LENGTH, device_tx_power, 
                          ad_src_advertise) != ls_err_none)
    {
        ReportPanic(app_panic_set_advert_data);
    }

    addDeviceNameToAdvData(length_added_to_adv, 0);

}
示例#6
0
/*----------------------------------------------------------------------------*
 *  NAME
 *      initBeacon
 *
 *  DESCRIPTION
 *      This function initialises beacon data
 *
 *  RETURNS
 *      Nothing.
 *
 *---------------------------------------------------------------------------*/
void initBeacon(void)
{
    /* read the config values from CsKeys */
    uint16 beaconUuidMsw = CSReadUserKey(BEACON_UUID_MSW_USER_KEY_IDX);
    uint16 beaconMajor = CSReadUserKey(BEACON_MAJOR_USER_KEY_IDX);
    uint16 beaconMinor = CSReadUserKey(BEACON_MINOR_USER_KEY_IDX);
    uint16 txPower = CSReadUserKey(BEACON_TX_POWER_USER_KEY_IDX);
    
    /* set up beacon UUID */
    if(beaconUuidMsw == BEACON_USER_KEY_DEFAULT_VALUE)
    {
        g_app_data.uuid[0] = BEACON_UUID_00;
        g_app_data.uuid[1] = BEACON_UUID_01;
    }
    else
    {
        g_app_data.uuid[0] = WORD_MSB(beaconUuidMsw);
        g_app_data.uuid[1] = WORD_LSB(beaconUuidMsw);
    }
    
    g_app_data.uuid[2] = BEACON_UUID_02;
    g_app_data.uuid[3] = BEACON_UUID_03;
    g_app_data.uuid[4] = BEACON_UUID_04;
    g_app_data.uuid[5] = BEACON_UUID_05;
    g_app_data.uuid[6] = BEACON_UUID_06;
    g_app_data.uuid[7] = BEACON_UUID_07;
    g_app_data.uuid[8] = BEACON_UUID_08;
    g_app_data.uuid[9] = BEACON_UUID_09;
    g_app_data.uuid[10] = BEACON_UUID_10;
    g_app_data.uuid[11] = BEACON_UUID_11;
    g_app_data.uuid[12] = BEACON_UUID_12;
    g_app_data.uuid[13] = BEACON_UUID_13;
    g_app_data.uuid[14] = BEACON_UUID_14;
    g_app_data.uuid[15] = BEACON_UUID_15;

    /* set up beacon major */
    if(beaconMajor == BEACON_USER_KEY_DEFAULT_VALUE)
    {
        g_app_data.major = BEACON_DEFAULT_MAJOR;
    }
    else
    {
        g_app_data.major = beaconMajor;
    }
    
    /* set up beacon minor */
    if(beaconMinor == BEACON_USER_KEY_DEFAULT_VALUE)
    {
        g_app_data.minor = BEACON_DEFAULT_MINOR;
    }
    else
    {
        g_app_data.minor = beaconMinor;
    }

    /* set up the TX power */
    if(txPower == BEACON_USER_KEY_DEFAULT_VALUE)
    {
        g_app_data.txPower = BEACON_DEFAULT_TX_POWER;
    }
    else
    {
        g_app_data.txPower = txPower;
    }
}