藍芽BLE-DA14683自定義藍芽資料收發服務程式碼
阿新 • • 發佈:2018-12-29
/* * 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_ */