From b39ac19d07f9395f79bc176ff5a6a8275182f327 Mon Sep 17 00:00:00 2001 From: Andelf Date: Sun, 3 Dec 2023 14:23:43 +0800 Subject: [PATCH] feat(blk): blinky sub demo now works --- examples/ble-blinky.rs | 127 ++++++++++++++++++++++------ examples/ble-peripheral-devinfo.rs | 16 ++-- src/ble/ffi.rs | 21 ++--- src/ble/gap.rs | 2 - src/ble/gatt.rs | 128 +++++++++++++++++++++-------- src/ble/gattservapp.rs | 31 ++++--- 6 files changed, 228 insertions(+), 97 deletions(-) diff --git a/examples/ble-blinky.rs b/examples/ble-blinky.rs index c54f3ef..3b96cea 100644 --- a/examples/ble-blinky.rs +++ b/examples/ble-blinky.rs @@ -37,12 +37,12 @@ static mut SCAN_RSP_DATA: &[u8] = &[ // complete name 0x12, // length of this data GAP_ADTYPE_LOCAL_NAME_COMPLETE, - b'S', - b'i', - b'm', - b'p', + b'B', b'l', - b'e', + b'i', + b'n', + b'k', + b'y', b' ', b'P', b'e', @@ -105,21 +105,21 @@ static mut SYSTEM_ID: [u8; 8] = [0u8; 8]; static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ // Device Information Service GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::primaryServiceUUID.as_ptr() }, }, permissions: GATT_PERMIT_READ, handle: 0, // The first must be a Service attribute - value: &gattAttrType_t { + value: &GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::DEVINFO_SERV_UUID as *const _ as _, } as *const _ as _, }, // System ID Declaration GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, @@ -129,7 +129,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // System ID Value GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::SYSTEM_ID_UUID as *const _ as _, }, @@ -139,7 +139,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Serial Number String Declaration GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, @@ -149,7 +149,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Serial Number Value GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::SERIAL_NUMBER_UUID as *const _ as _, }, @@ -159,7 +159,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Temperature GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, @@ -169,7 +169,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Serial Number Value GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::TEMP_UUID as *const _ as _, }, @@ -293,30 +293,29 @@ static mut BLINKY_CLIENT_CHARCFG: [gattCharCfg_t; 4] = unsafe { core::mem::zeroe static mut BLINKY_ATTR_TABLE: [GattAttribute; 6] = [ // Blinky Service GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::primaryServiceUUID.as_ptr() }, }, permissions: GATT_PERMIT_READ, handle: 0, - value: &gattAttrType_t { + value: &GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &BLINKY_SERV_UUID as *const _ as _, } as *const _ as _, }, - // Blinky Data Declaration and Value GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, permissions: GATT_PERMIT_READ, handle: 0, - value: &GATT_PROP_NOTIFY as *const _ as _, + value: &(GATT_PROP_NOTIFY | GATT_PROP_READ) as *const _ as _, }, GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &BLINKY_DATA_UUID as *const _ as _, }, @@ -326,7 +325,7 @@ static mut BLINKY_ATTR_TABLE: [GattAttribute; 6] = [ }, // Blinky client config GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::clientCharCfgUUID.as_ptr() }, }, @@ -334,10 +333,9 @@ static mut BLINKY_ATTR_TABLE: [GattAttribute; 6] = [ handle: 0, value: unsafe { BLINKY_CLIENT_CHARCFG.as_ptr() as _ }, }, - // Command GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, @@ -346,7 +344,7 @@ static mut BLINKY_ATTR_TABLE: [GattAttribute; 6] = [ value: &GATT_PROP_WRITE as *const _ as _, }, GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &BLINKY_CMD_UUID as *const _ as _, }, @@ -389,11 +387,11 @@ unsafe fn blinky_init() { return 0; } unsafe extern "C" fn blinky_on_write_attr( - _conn_handle: u16, + conn_handle: u16, attr: *mut GattAttribute, value: *mut u8, len: u16, - _offset: u16, + offset: u16, method: u8, ) -> u8 { let uuid = *((*attr).type_.uuid as *const u16); @@ -407,6 +405,32 @@ unsafe fn blinky_init() { } else if cmd == 0x00 { BLINKY_ON.store(false, Ordering::Relaxed); } + } else if uuid == BLINKY_CONF_UUID { + // sub to notrification + // let status = GATTServApp::process_ccc_write_req(conn_handle, attr, value, len, offset, GATT_CLIENT_CFG_NOTIFY); + // if status.is_ok() { + // println!("! on_write_attr sub"); + // let val = slice::from_raw_parts(value, len as usize); + // println!("! on_write_attr sub value {:?}", val); + // } + //APP_CHANNEL.try_send(AppEvent::BlinkySubscribed(conn_handle)); + //println!("! on_write_attr sub"); + } else if uuid == gatt_uuid::GATT_CLIENT_CHAR_CFG_UUID { + // client char cfg + let status = + GATTServApp::process_ccc_write_req(conn_handle, attr, value, len, offset, GATT_CLIENT_CFG_NOTIFY); + if status.is_ok() { + println!("! on_write_attr sub"); + let val = slice::from_raw_parts(value, len as usize); + println!("! on_write_attr sub value {:?}", val); + if val == &[0x01, 0x00] { + APP_CHANNEL.try_send(AppEvent::BlinkySubscribed(conn_handle)); + } else { + APP_CHANNEL.try_send(AppEvent::BlinkyUnsubscribed(conn_handle)); + } + } + } else { + return ATT_ERR_ATTR_NOT_FOUND; } return 0; @@ -434,6 +458,8 @@ unsafe fn blinky_init() { pub enum AppEvent { Connected(u16), Disconnected(u16), + BlinkySubscribed(u16), + BlinkyUnsubscribed(u16), } static APP_CHANNEL: Channel = Channel::new(); @@ -564,7 +590,57 @@ async fn peripheral(spawner: Spawner, task_id: u8, mut subscriber: ble::EventSub AppEvent::Disconnected(conn_handle) => unsafe { GATTServApp::init_char_cfg(conn_handle, BLINKY_CLIENT_CHARCFG.as_mut_ptr()); }, + AppEvent::BlinkySubscribed(conn_handle) => unsafe { + spawner.spawn(blinky_notification(conn_handle)).unwrap(); + }, + _ => { + // other event. just broadcast + } + }, + } + } +} + +#[embassy_executor::task] +async fn blinky_notification(conn_handle: u16) { + let mut ticker = Ticker::every(Duration::from_millis(1000)); + + static mut NOTIFY_MSG: gattMsg_t = gattMsg_t { + handleValueNoti: attHandleValueNoti_t { + handle: 0, + len: 2, + pValue: ptr::null_mut(), + }, + }; + loop { + match select(ticker.next(), APP_CHANNEL.receive()).await { + Either::First(_) => unsafe { + let val = GATTServApp::read_char_cfg(conn_handle, BLINKY_CLIENT_CHARCFG.as_ptr()); + if val == 0x01 { + // notification is no + let on = BLINKY_ON.load(Ordering::Relaxed); + let val: u8 = if on { 0x01 } else { 0x00 }; + // let mut msg = gattMsg_t::alloc_handle_value_notification(conn_handle, 2); + + unsafe { + NOTIFY_MSG.handleValueNoti.pValue = + GATT_bm_alloc(0, ATT_HANDLE_VALUE_NOTI, 2, ptr::null_mut(), 0) as _; + NOTIFY_MSG.handleValueNoti.handle = BLINKY_ATTR_TABLE[2].handle; + NOTIFY_MSG.handleValueNoti.len = 2; + + core::ptr::copy(&val as *const _ as _, NOTIFY_MSG.handleValueNoti.pValue, 2); + println!("!! handle {}", BLINKY_ATTR_TABLE[2].handle); + + let rc = GATT_Notification(conn_handle, &NOTIFY_MSG.handleValueNoti, 0); + println!("!! notify rc {:?}", rc); + } + } }, + Either::Second(AppEvent::Disconnected(_)) | Either::Second(AppEvent::BlinkyUnsubscribed(_)) => { + println!("disconnect, stop notification"); + return; + } + _ => (), } } } @@ -659,6 +735,7 @@ async fn main(spawner: Spawner) -> ! { let mut ble_config = ble::Config::default(); ble_config.pa_config = None; + ble_config.mac_addr = [0xca, 0xfe, 0xba, 0xbe, 0x01, 0x01].into(); let (task_id, sub) = hal::ble::init(ble_config).unwrap(); println!("BLE hal task id: {}", task_id); diff --git a/examples/ble-peripheral-devinfo.rs b/examples/ble-peripheral-devinfo.rs index 28fb9a7..dfdac1a 100644 --- a/examples/ble-peripheral-devinfo.rs +++ b/examples/ble-peripheral-devinfo.rs @@ -106,21 +106,21 @@ static mut SYSTEM_ID: [u8; 8] = [0u8; 8]; static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ // Device Information Service GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::primaryServiceUUID.as_ptr() }, }, permissions: GATT_PERMIT_READ, handle: 0, // The first must be a Service attribute - value: &gattAttrType_t { + value: &GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::DEVINFO_SERV_UUID as *const _ as _, } as *const _ as _, }, // System ID Declaration GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, @@ -130,7 +130,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // System ID Value GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::SYSTEM_ID_UUID as *const _ as _, }, @@ -140,7 +140,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Serial Number String Declaration GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, @@ -150,7 +150,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Serial Number Value GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::SERIAL_NUMBER_UUID as *const _ as _, }, @@ -160,7 +160,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Temperature GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: unsafe { gatt_uuid::characterUUID.as_ptr() }, }, @@ -170,7 +170,7 @@ static mut DEVICE_INFO_TABLE: [GattAttribute; 7] = [ }, // Serial Number Value GattAttribute { - type_: gattAttrType_t { + type_: GattAttrType { len: ATT_BT_UUID_SIZE, uuid: &gatt_uuid::TEMP_UUID as *const _ as _, }, diff --git a/src/ble/ffi.rs b/src/ble/ffi.rs index 784b35a..756dc9c 100644 --- a/src/ble/ffi.rs +++ b/src/ble/ffi.rs @@ -1,7 +1,10 @@ #![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)] +use core::ffi::c_void; use core::num::NonZeroU8; +use super::gatt::gattMsg_t; + // pub type bStatus_t = u8; // SUCCESS(0x00):指令按预期执行。 // INVALIDPARAMETER(0x02):无效的连接句柄或请求字段。 @@ -547,15 +550,14 @@ pub const DEVDISC_MODE_LIMITED: u8 = 0x02; pub const DEVDISC_MODE_ALL: u8 = 0x03; pub type pfnEcc_key_t = Option ::core::ffi::c_int>; -pub type pfnEcc_dhkey_t = - Option< - unsafe extern "C" fn( - peer_pub_key_x: *mut u8, - peer_pub_key_y: *mut u8, - our_priv_key: *mut u8, - out_dhkey: *mut u8, - ) -> ::core::ffi::c_int, - >; +pub type pfnEcc_dhkey_t = Option< + unsafe extern "C" fn( + peer_pub_key_x: *mut u8, + peer_pub_key_y: *mut u8, + our_priv_key: *mut u8, + out_dhkey: *mut u8, + ) -> ::core::ffi::c_int, +>; pub type pfnEcc_alg_f4_t = Option< unsafe extern "C" fn(u: *mut u8, v: *mut u8, x: *mut u8, z: u8, out_enc_data: *mut u8) -> ::core::ffi::c_int, >; @@ -720,4 +722,3 @@ extern "C" { } // GATT - diff --git a/src/ble/gap.rs b/src/ble/gap.rs index d885a2d..758651d 100644 --- a/src/ble/gap.rs +++ b/src/ble/gap.rs @@ -506,7 +506,6 @@ pub struct gapRolesBroadcasterCBs_t { pub pfnScanRecv: gapRolesScanReqRecv_t, } - /// GAP Role pub struct GAPRole; @@ -528,7 +527,6 @@ impl GAPRole { } } - // GAP extern "C" { diff --git a/src/ble/gatt.rs b/src/ble/gatt.rs index 9796522..2c24abf 100644 --- a/src/ble/gatt.rs +++ b/src/ble/gatt.rs @@ -1,7 +1,39 @@ #![allow(non_snake_case, non_camel_case_types)] +use core::ffi::c_void; +use core::ptr; + use super::ffi::{bStatus_t, tmos_event_hdr_t}; +pub const ATT_ERROR_RSP: u8 = 1; +pub const ATT_EXCHANGE_MTU_REQ: u8 = 2; +pub const ATT_EXCHANGE_MTU_RSP: u8 = 3; +pub const ATT_FIND_INFO_REQ: u8 = 4; +pub const ATT_FIND_INFO_RSP: u8 = 5; +pub const ATT_FIND_BY_TYPE_VALUE_REQ: u8 = 6; +pub const ATT_FIND_BY_TYPE_VALUE_RSP: u8 = 7; +pub const ATT_READ_BY_TYPE_REQ: u8 = 8; +pub const ATT_READ_BY_TYPE_RSP: u8 = 9; +pub const ATT_READ_REQ: u8 = 10; +pub const ATT_READ_RSP: u8 = 11; +pub const ATT_READ_BLOB_REQ: u8 = 12; +pub const ATT_READ_BLOB_RSP: u8 = 13; +pub const ATT_READ_MULTI_REQ: u8 = 14; +pub const ATT_READ_MULTI_RSP: u8 = 15; +pub const ATT_READ_BY_GRP_TYPE_REQ: u8 = 16; +pub const ATT_READ_BY_GRP_TYPE_RSP: u8 = 17; +pub const ATT_WRITE_REQ: u8 = 18; +pub const ATT_WRITE_RSP: u8 = 19; +pub const ATT_PREPARE_WRITE_REQ: u8 = 22; +pub const ATT_PREPARE_WRITE_RSP: u8 = 23; +pub const ATT_EXECUTE_WRITE_REQ: u8 = 24; +pub const ATT_EXECUTE_WRITE_RSP: u8 = 25; +pub const ATT_HANDLE_VALUE_NOTI: u8 = 27; +pub const ATT_HANDLE_VALUE_IND: u8 = 29; +pub const ATT_HANDLE_VALUE_CFM: u8 = 30; +pub const ATT_WRITE_CMD: u8 = 82; +pub const ATT_SIGNED_WRITE_CMD: u8 = 210; + // ATT Error Codes /// The attribute handle given was not valid on this server pub const ATT_ERR_INVALID_HANDLE: u8 = 0x01; @@ -492,50 +524,55 @@ pub const GATT_PROP_INDICATE: u8 = 32; pub const GATT_PROP_AUTHEN: u8 = 64; pub const GATT_PROP_EXTENDED: u8 = 128; -// GATT Client Characteristic Configuration Bit Fields -pub const GATT_CLIENT_CFG_NOTIFY: u32 = 1; -pub const GATT_CLIENT_CFG_INDICATE: u32 = 2; - -#[doc = " @brief Callback function prototype to read an attribute value.\n\n @note blePending can be returned ONLY for the following\n read operations:\n - Read Request: ATT_READ_REQ\n - Read Blob Request: ATT_READ_BLOB_REQ\n\n @note If blePending is returned then it's the responsibility of the application to respond to\n ATT_READ_REQ and ATT_READ_BLOB_REQ message with ATT_READ_RSP and ATT_READ_BLOB_RSP\n message respectively.\n\n @note Payload 'pValue' used with ATT_READ_RSP and ATT_READ_BLOB_RSP must be allocated using GATT_bm_alloc().\n\n @param connHandle - connection request was received on\n @param pAttr - pointer to attribute\n @param pValue - pointer to data to be read (to be returned)\n @param pLen - length of data (to be returned)\n @param offset - offset of the first octet to be read\n @param maxLen - maximum length of data to be read\n @param method - type of read message\n\n @return SUCCESS: Read was successfully.
\n blePending: A response is pending for this client.
\n Error, otherwise: ref ATT_ERR_CODE_DEFINES.
"] -pub type pfnGATTReadAttrCB_t = - Option< - unsafe extern "C" fn( - connHandle: u16, - pAttr: *mut GattAttribute, - pValue: *mut u8, - pLen: *mut u16, - offset: u16, - maxLen: u16, - method: u8, - ) -> u8, - >; -#[doc = " @brief Callback function prototype to write an attribute value.\n\n @note blePending can be returned ONLY for the following\n write operations:\n - Write Request: ATT_WRITE_REQ\n - Write Command: ATT_WRITE_CMD\n - Write Long: ATT_EXECUTE_WRITE_REQ\n - Reliable Writes: Multiple ATT_PREPARE_WRITE_REQ followed by one final ATT_EXECUTE_WRITE_REQ\n\n @note If blePending is returned then it's the responsibility of the application to 1) respond to\n ATT_WRITE_REQ and ATT_EXECUTE_WRITE_REQ message with ATT_WRITE_RSP and ATT_EXECUTE_WRITE_RSP\n message respectively, and 2) free each request payload 'pValue' using BM_free().\n\n @note Write Command (ATT_WRITE_CMD) does NOT require a response message.\n\n @param connHandle - connection request was received on\n @param pAttr - pointer to attribute\n @param pValue - pointer to data to be written\n @param pLen - length of data\n @param offset - offset of the first octet to be written\n @param method - type of write message\n\n @return SUCCESS: Write was successfully.
\n blePending: A response is pending for this client.
\n Error, otherwise: ref ATT_ERR_CODE_DEFINES.
"] -pub type pfnGATTWriteAttrCB_t = Option< - unsafe extern "C" fn( - connHandle: u16, - pAttr: *mut GattAttribute, - pValue: *mut u8, - len: u16, - offset: u16, - method: u8, - ) -> u8, ->; -#[doc = " @brief Callback function prototype to authorize a Read or Write operation\n on a given attribute.\n\n @param connHandle - connection request was received on\n @param pAttr - pointer to attribute\n @param opcode - request opcode (ATT_READ_REQ or ATT_WRITE_REQ)\n\n @return SUCCESS: Operation authorized.
\n ATT_ERR_INSUFFICIENT_AUTHOR: Authorization required.
"] -pub type pfnGATTAuthorizeAttrCB_t = - Option bStatus_t>; - +// rename from gattAttrType_t #[doc = " GATT Attribute Type format."] #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct gattAttrType_t { +pub struct GattAttrType { #[doc = "!< Length of UUID (2 or 16)"] pub len: u8, #[doc = "!< Pointer to UUID"] pub uuid: *const u8, } -unsafe impl Sync for gattAttrType_t {} -unsafe impl Send for gattAttrType_t {} +impl GattAttrType { + pub const fn new_u16(uuid: u16) -> Self { + Self { + len: 2, + uuid: &uuid as *const u16 as *const u8, + } + } + + pub const fn new_u128(uuid: &'static [u8]) -> Self { + Self { + len: 16, + uuid: uuid.as_ptr(), + } + } + + pub fn as_u16(&self) -> u16 { + unsafe { *(self.uuid as *const u16) } + } + + pub fn as_u128(&self) -> [u8; 16] { + unsafe { *(self.uuid as *const [u8; 16]) } + } +} + +unsafe impl Sync for GattAttrType {} +unsafe impl Send for GattAttrType {} + +impl PartialEq for GattAttrType { + fn eq(&self, other: &Self) -> bool { + unsafe { + self.len == other.len && (self.uuid == other.uuid) && { + let len = self.len as usize; + core::slice::from_raw_parts(self.uuid, len) == core::slice::from_raw_parts(other.uuid, len) + } + } + } +} +impl Eq for GattAttrType {} // Renamed from gattAttribute_t #[doc = " GATT Attribute format."] @@ -543,7 +580,7 @@ unsafe impl Send for gattAttrType_t {} #[derive(Debug, Copy, Clone)] pub struct GattAttribute { #[doc = "!< Attribute type (2 or 16 octet UUIDs)"] - pub type_: gattAttrType_t, + pub type_: GattAttrType, #[doc = "!< Attribute permissions"] pub permissions: u8, #[doc = "!< Attribute handle - assigned internally by attribute server"] @@ -554,3 +591,22 @@ pub struct GattAttribute { unsafe impl Sync for GattAttribute {} unsafe impl Send for GattAttribute {} + +extern "C" { + #[doc = " @brief This sub-procedure is used when a server is configured to\n indicate a characteristic value to a client and expects an\n attribute protocol layer acknowledgement that the indication\n was successfully received.\n\n The ATT Handle Value Indication is used in this sub-procedure.\n\n If the return status from this function is SUCCESS, the calling\n application task will receive an tmos GATT_MSG_EVENT message.\n The type of the message will be ATT_HANDLE_VALUE_CFM.\n\n @note This sub-procedure is complete when ATT_HANDLE_VALUE_CFM\n (with SUCCESS or bleTimeoutstatus) is received by the calling application task.\n\n @param connHandle - connection to use\n @param pInd - pointer to indication to be sent\n @param authenticated - whether an authenticated link is required\n @param taskId - task to be notified of response\n\n @return SUCCESS: Indication was sent successfully.
\n INVALIDPARAMETER: Invalid connection handle or request field.
\n MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
\n bleNotConnected: Connection is down.
\n blePending: A confirmation is pending with this client.
\n bleMemAllocError: Memory allocation error occurred.
\n bleTimeout: Previous transaction timed out.
"] + pub fn GATT_Indication( + connHandle: u16, + pInd: *const attHandleValueInd_t, + authenticated: u8, + taskId: u8, + ) -> bStatus_t; + #[doc = " @brief This sub-procedure is used when a server is configured to\n notify a characteristic value to a client without expecting\n any attribute protocol layer acknowledgement that the\n notification was successfully received.\n\n The ATT Handle Value Notification is used in this sub-procedure.\n\n @note A notification may be sent at any time and does not invoke a confirmation.\n No confirmation will be sent to the calling application task for\n this sub-procedure.\n\n @param connHandle - connection to use\n @param pNoti - pointer to notification to be sent\n @param authenticated - whether an authenticated link is required\n\n @return SUCCESS: Notification was sent successfully.
\n INVALIDPARAMETER: Invalid connection handle or request field.
\n MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
\n bleNotConnected: Connection is down.
\n bleMemAllocError: Memory allocation error occurred.
\n bleTimeout: Previous transaction timed out.
"] + pub fn GATT_Notification(connHandle: u16, pNoti: *const attHandleValueNoti_t, authenticated: u8) -> bStatus_t; +} + +extern "C" { + #[doc = " @brief GATT implementation of the allocator functionality.\n\n @note This function should only be called by GATT and the upper layer protocol/application.\n\n @param connHandle - connection that message is to be sent on.\n @param opcode - opcode of message that buffer to be allocated for.\n @param size - number of bytes to allocate from the heap.\n @param pSizeAlloc - number of bytes allocated for the caller from the heap.\n @param flag - .\n\n @return pointer to the heap allocation; NULL if error or failure."] + pub fn GATT_bm_alloc(connHandle: u16, opcode: u8, size: u16, pSizeAlloc: *mut u16, flag: u8) -> *mut c_void; + #[doc = " @brief GATT implementation of the de-allocator functionality.\n\n @param pMsg - pointer to GATT message containing the memory to free.\n @param opcode - opcode of the message\n\n @return none"] + pub fn GATT_bm_free(pMsg: *mut gattMsg_t, opcode: u8); +} diff --git a/src/ble/gattservapp.rs b/src/ble/gattservapp.rs index f96520e..d6ff9b4 100644 --- a/src/ble/gattservapp.rs +++ b/src/ble/gattservapp.rs @@ -14,8 +14,8 @@ use super::ffi::bStatus_t; use super::gatt::GattAttribute; // GATT Client Characteristic Configuration Bit Fields -pub const GATT_CLIENT_CFG_NOTIFY: u32 = 1; -pub const GATT_CLIENT_CFG_INDICATE: u32 = 2; +pub const GATT_CLIENT_CFG_NOTIFY: u16 = 1; +pub const GATT_CLIENT_CFG_INDICATE: u16 = 2; // All profile services bit fields pub const GATT_ALL_SERVICES: u32 = 4294967295; @@ -27,18 +27,17 @@ pub const GATT_MAX_ENCRYPT_KEY_SIZE: u8 = 16; pub const INVALID_CONNHANDLE: u16 = 0xFFFF; #[doc = " @brief Callback function prototype to read an attribute value.\n\n @note blePending can be returned ONLY for the following\n read operations:\n - Read Request: ATT_READ_REQ\n - Read Blob Request: ATT_READ_BLOB_REQ\n\n @note If blePending is returned then it's the responsibility of the application to respond to\n ATT_READ_REQ and ATT_READ_BLOB_REQ message with ATT_READ_RSP and ATT_READ_BLOB_RSP\n message respectively.\n\n @note Payload 'pValue' used with ATT_READ_RSP and ATT_READ_BLOB_RSP must be allocated using GATT_bm_alloc().\n\n @param connHandle - connection request was received on\n @param pAttr - pointer to attribute\n @param pValue - pointer to data to be read (to be returned)\n @param pLen - length of data (to be returned)\n @param offset - offset of the first octet to be read\n @param maxLen - maximum length of data to be read\n @param method - type of read message\n\n @return SUCCESS: Read was successfully.
\n blePending: A response is pending for this client.
\n Error, otherwise: ref ATT_ERR_CODE_DEFINES.
"] -pub type pfnGATTReadAttrCB_t = - Option< - unsafe extern "C" fn( - conn_handle: u16, - pAttr: *mut GattAttribute, - pValue: *mut u8, - pLen: *mut u16, - offset: u16, - max_len: u16, - method: u8, - ) -> u8, - >; +pub type pfnGATTReadAttrCB_t = Option< + unsafe extern "C" fn( + conn_handle: u16, + pAttr: *mut GattAttribute, + pValue: *mut u8, + pLen: *mut u16, + offset: u16, + max_len: u16, + method: u8, + ) -> u8, +>; #[doc = " @brief Callback function prototype to write an attribute value.\n\n @note blePending can be returned ONLY for the following\n write operations:\n - Write Request: ATT_WRITE_REQ\n - Write Command: ATT_WRITE_CMD\n - Write Long: ATT_EXECUTE_WRITE_REQ\n - Reliable Writes: Multiple ATT_PREPARE_WRITE_REQ followed by one final ATT_EXECUTE_WRITE_REQ\n\n @note If blePending is returned then it's the responsibility of the application to 1) respond to\n ATT_WRITE_REQ and ATT_EXECUTE_WRITE_REQ message with ATT_WRITE_RSP and ATT_EXECUTE_WRITE_RSP\n message respectively, and 2) free each request payload 'pValue' using BM_free().\n\n @note Write Command (ATT_WRITE_CMD) does NOT require a response message.\n\n @param connHandle - connection request was received on\n @param pAttr - pointer to attribute\n @param pValue - pointer to data to be written\n @param pLen - length of data\n @param offset - offset of the first octet to be written\n @param method - type of write message\n\n @return SUCCESS: Write was successfully.
\n blePending: A response is pending for this client.
\n Error, otherwise: ref ATT_ERR_CODE_DEFINES.
"] pub type pfnGATTWriteAttrCB_t = Option< unsafe extern "C" fn( @@ -109,7 +108,7 @@ impl GATTServApp { } #[inline] - pub fn read_char_cfg(connHandle: u16, charCfgTbl: *mut gattCharCfg_t) -> u16 { + pub fn read_char_cfg(connHandle: u16, charCfgTbl: *const gattCharCfg_t) -> u16 { unsafe { ffi::GATTServApp_ReadCharCfg(connHandle, charCfgTbl) } } @@ -151,7 +150,7 @@ mod ffi { #[doc = " @brief Send out a Service Changed Indication.\n\n @param connHandle - connection to use\n @param taskId - task to be notified of confirmation\n\n @return SUCCESS: Indication was sent successfully.
\n FAILURE: Service Changed attribute not found.
\n INVALIDPARAMETER: Invalid connection handle or request field.
\n MSG_BUFFER_NOT_AVAIL: No HCI buffer is available.
\n bleNotConnected: Connection is down.
\n blePending: A confirmation is pending with this client.
"] pub fn GATTServApp_SendServiceChangedInd(connHandle: u16, taskId: u8) -> bStatus_t; #[doc = " @brief Read the client characteristic configuration for a given client.\n\n @note Each client has its own instantiation of the Client Characteristic Configuration.\n Reads of the Client Characteristic Configuration only shows the configuration\n for that client.\n\n @param connHandle - connection handle.\n @param charCfgTbl - client characteristic configuration table.\n\n @return attribute value"] - pub fn GATTServApp_ReadCharCfg(connHandle: u16, charCfgTbl: *mut gattCharCfg_t) -> u16; + pub fn GATTServApp_ReadCharCfg(connHandle: u16, charCfgTbl: *const gattCharCfg_t) -> u16; #[doc = " @brief Write the client characteristic configuration for a given client.\n\n @note Each client has its own instantiation of the Client Characteristic Configuration.\n Writes of the Client Characteristic Configuration only only affect the\n configuration of that client.\n\n @param connHandle - connection handle.\n @param charCfgTbl - client characteristic configuration table.\n @param value - attribute new value.\n\n @return Success or Failure"] pub fn GATTServApp_WriteCharCfg(connHandle: u16, charCfgTbl: *mut gattCharCfg_t, value: u16) -> u8; #[doc = " @brief Process the client characteristic configuration\n write request for a given client.\n\n @param connHandle - connection message was received on.\n @param pAttr - pointer to attribute.\n @param pValue - pointer to data to be written.\n @param len - length of data.\n @param offset - offset of the first octet to be written.\n @param validCfg - valid configuration.\n\n @return Success or Failure"]