版权声明:转载请注明出处。技术交流加微信:life5270 https://blog.csdn.net/JaLLs/article/details/84558112
/*
* user_service.c
*
* Created on: 2018年11月26日
* Author: Jim
*/
/**
****************************************************************************************
* contact me by wechat: life5270
* @file user_service.c
*
* @brief user_tx_rx Service sample implementation
*
* Copyright (C) 2015 Dialog Semiconductor.
* This computer program includes Confidential, Proprietary Information
* of Dialog Semiconductor. All Rights Reserved.
*
****************************************************************************************
*/
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "stdio.h"
#include "osal.h"
#include "ble_att.h"
#include "ble_bufops.h"
#include "ble_common.h"
#include "ble_gatt.h"
#include "ble_gatts.h"
#include "ble_storage.h"
#include "ble_uuid.h"
#include "svc_defines.h"
#include "svc_types.h"
#include "user_service.h"
#define UUID_TX_RX_SERVICE (0x1840)
#define UUID_TX_RX_CHARACTER (0x2907)
static const uint8_t read_test[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05
};
static void user_sev_read_cb(ble_service_t *svc, uint16_t conn_idx)
{
read_date_cfm(svc, conn_idx, ATT_ERROR_OK, read_test);
}
static void user_sev_recieve_cb(ble_service_t *svc, uint16_t conn_idx, \
const uint8_t *value,uint8_t length)
{
// printf("value[0]:%x\r\n",value[0]);
// printf("value[1]:%x\r\n",value[1]);
// printf("value[2]:%x\r\n",value[2]);
// printf("value[3]:%x\r\n",value[3]);
/*if you use WRITE NO RESPONSE,DO NOT USE THIS*/
// write_date_response(svc, conn_idx, ATT_ERROR_OK);
service_send_date(svc, conn_idx, value,length);
// notify other clients that data has recieved
//OS_TASK_NOTIFY(ble_peripheral_task_handle, CTS_SET_TIME_NOTIF, eSetBits);
}
static const user_service_callbacks_t user_callbacks = {
.read_date_cb = user_sev_read_cb,
.recieve_date_cb = user_sev_recieve_cb,
};
typedef struct {
ble_service_t svc;
// callbacks
const user_service_callbacks_t *cb;
// handles
uint16_t user_val_h;
uint16_t user_ccc_h;
} user_service_t;
static void do_user_read(user_service_t *user_svc, const ble_evt_gatts_read_req_t *evt)
{
if (!user_svc->cb || !user_svc->cb->read_date_cb) {
ble_gatts_read_cfm(evt->conn_idx, evt->handle, ATT_ERROR_READ_NOT_PERMITTED, 0, NULL);
return;
}
// Ask client for data information
user_svc->cb->read_date_cb(&user_svc->svc, evt->conn_idx);
// callback executed properly, will be replied
}
static att_error_t do_user_write(user_service_t *user_svc, uint16_t conn_idx, uint16_t offset,
uint16_t length, const uint8_t *value)
{
if (offset) {
return ATT_ERROR_ATTRIBUTE_NOT_LONG;
}
if (!user_svc->cb || !user_svc->cb->recieve_date_cb) {
return ATT_ERROR_WRITE_NOT_PERMITTED;
}
user_svc->cb->recieve_date_cb(&user_svc->svc, conn_idx, value,length);
printf("1111\r\n");
return ATT_ERROR_OK;
}
static att_error_t do_user_ccc_write(user_service_t *user_svc, uint16_t conn_idx, uint16_t offset,
uint16_t length, const uint8_t *value)
{
uint16_t ccc;
if (offset) {
return ATT_ERROR_ATTRIBUTE_NOT_LONG;
}
if (length != sizeof(ccc)) {
return ATT_ERROR_INVALID_VALUE_LENGTH;
}
ccc = get_u16(value);
ble_storage_put_u32(conn_idx, user_svc->user_ccc_h, ccc, true);
printf("2222\r\n");
return ATT_ERROR_OK;
}
static void handle_read_req(ble_service_t *svc, const ble_evt_gatts_read_req_t *evt)
{
user_service_t *user_svc = (user_service_t *) svc;
if (evt->handle == user_svc->user_val_h) {
do_user_read(user_svc, evt);
}else if (evt->handle == user_svc->user_ccc_h) {
uint16_t ccc = 0x0000;
ble_storage_get_u16(evt->conn_idx, user_svc->user_ccc_h, &ccc);
// we're little-endian, ok to write directly from uint16_t
ble_gatts_read_cfm(evt->conn_idx, evt->handle, ATT_ERROR_OK, sizeof(ccc), &ccc);
} else {
ble_gatts_read_cfm(evt->conn_idx, evt->handle, ATT_ERROR_READ_NOT_PERMITTED, 0, NULL);
}
}
static void handle_write_req(ble_service_t *svc, const ble_evt_gatts_write_req_t *evt)
{
user_service_t *user_svc = (user_service_t *) svc;
att_error_t status = ATT_ERROR_WRITE_NOT_PERMITTED;
if (evt->handle == user_svc->user_val_h) {
status = do_user_write(user_svc, evt->conn_idx, evt->offset, evt->length, evt->value);
goto done;
} else if (evt->handle == user_svc->user_ccc_h) {
status = do_user_ccc_write(user_svc, evt->conn_idx, evt->offset, evt->length, evt->value);
goto done;
}
done:
if (status == ((att_error_t) -1)) {
// write handler executed properly, will be replied by cfm call
return;
}
ble_gatts_write_cfm(evt->conn_idx, evt->handle, status);
}
static void cleanup(ble_service_t *svc)
{
user_service_t *user_svc = (user_service_t *) svc;
ble_storage_remove_all(user_svc->user_ccc_h);
OS_FREE(user_svc);
}
ble_service_t *user_service_init(const user_service_callbacks_t *cb)
{
user_service_t *user_svc;
uint16_t num_attr;
att_uuid_t uuid;
/* Make sure recieve_date_cb is defined */
OS_ASSERT(cb->recieve_date_cb);
user_svc = OS_MALLOC(sizeof(*user_svc));
memset(user_svc, 0, sizeof(*user_svc));
user_svc->svc.read_req = handle_read_req;
user_svc->svc.write_req = handle_write_req;
user_svc->svc.cleanup = cleanup;
user_svc->cb = cb;
num_attr = ble_gatts_get_num_attr(0, 1, 1);
ble_uuid_create16(UUID_TX_RX_SERVICE, &uuid);
ble_gatts_add_service(&uuid, GATT_SERVICE_PRIMARY, num_attr);
// Write is optional
ble_uuid_create16(UUID_TX_RX_CHARACTER, &uuid);
ble_gatts_add_characteristic(&uuid, GATT_PROP_READ|GATT_PROP_NOTIFY |GATT_PROP_WRITE_NO_RESP,
ATT_PERM_RW, 10,
GATTS_FLAG_CHAR_READ_REQ, NULL, &user_svc->user_val_h);
ble_uuid_create16(UUID_GATT_CLIENT_CHAR_CONFIGURATION, &uuid);
ble_gatts_add_descriptor(&uuid, ATT_PERM_RW, 2, 0, &user_svc->user_ccc_h);
ble_gatts_register_service(&user_svc->svc.start_h, &user_svc->user_val_h, &user_svc->user_ccc_h,0);
user_svc->svc.end_h = user_svc->svc.start_h + num_attr;
ble_service_add(&user_svc->svc);
return &user_svc->svc;
}
ble_service_t *user_sev_init()
{
ble_service_t *user_svc;
user_svc=user_service_init(&user_callbacks);
return user_svc;
}
void service_send_date(ble_service_t *svc, uint16_t conn_idx, const uint8_t *value,uint8_t length)
{
user_service_t *user_svc = (user_service_t *) svc;
uint16_t ccc = 0x0000;
ble_storage_get_u16(conn_idx, user_svc->user_ccc_h, &ccc);
if (!(ccc & GATT_CCC_NOTIFICATIONS)) {
return;
}
// printf("111\r\n");
ble_gatts_send_event(conn_idx, user_svc->user_val_h, GATT_EVENT_NOTIFICATION, length, value);
}
void read_date_cfm(ble_service_t *svc, uint16_t conn_idx, att_error_t status,
const uint8_t *value)
{
user_service_t *user_svc = (user_service_t *) svc;
ble_gatts_read_cfm(conn_idx, user_svc->user_val_h, ATT_ERROR_OK, 6, &value);
}
/*WRITE RESPONSE*/
void write_date_response(ble_service_t *svc, uint16_t conn_idx, att_error_t status)
{
user_service_t *user_svc = (user_service_t *) svc;
ble_gatts_write_cfm(conn_idx, user_svc->user_val_h, status);
}
/*
* user_service.h
*
* Created on: 2018年11月26日
* Author: Jim
*/
/**
****************************************************************************************
* contact me by wechat: life5270
* @file user_service.h
*
* @brief user_service Service implementation API
*
* Copyright (C) 2015 Dialog Semiconductor.
* This computer program includes Confidential, Proprietary Information
* of Dialog Semiconductor. All Rights Reserved.
*
****************************************************************************************
*/
#ifndef SDK_BLE_SERVICES_INCLUDE_USER_SERVICE_H_
#define SDK_BLE_SERVICES_INCLUDE_USER_SERVICE_H_
#include <stdint.h>
#include <ble_service.h>
#include <svc_types.h>
typedef void (* user_read_cb_t) (ble_service_t *svc, uint16_t conn_idx);
typedef void (* user_recieve_cb_t) (ble_service_t *svc, uint16_t conn_idx,\
const uint8_t *value,uint8_t length);
/** CTS application callbacks */
typedef struct {
/** User callback to call on every read data request */
user_read_cb_t read_date_cb;
/** User callback to call on write request, can be NULL, that will make characteristic RO */
user_recieve_cb_t recieve_date_cb;
} user_service_callbacks_t;
/**
* Register user_service instance
*
* Function initializes and register User Service.
* \param [in] cb application callbacks
*
* \return service instance
*
*/
ble_service_t *user_service_init(const user_service_callbacks_t *cb);
ble_service_t *user_sev_init();
/**
* Notify connected client about send data
*
* \param [in] svc service instance
* \param [in] conn_idx connection index
* \param [in] value data to send
* \param [in] length data length
*/
void service_send_date(ble_service_t *svc, uint16_t conn_idx, const uint8_t *value,uint8_t length);
/**
* Response for \p write callback
*
* \param [in] svc service instance
* \param [in] conn_idx connection index
* \param [in] status ATT error
*
*/
void write_date_response(ble_service_t *svc, uint16_t conn_idx, att_error_t status);
/**
* Response for \p write callback
* */
void read_date_cfm(ble_service_t *svc, uint16_t conn_idx, att_error_t status,
const uint8_t *value);
#endif /* SDK_BLE_SERVICES_INCLUDE_USER_SERVICE_H_ */