From 47770f6c59f4344eb0d818d928becafdf7e6b224 Mon Sep 17 00:00:00 2001 From: deadprogram Date: Sat, 3 Oct 2020 10:13:15 +0200 Subject: [PATCH] gattc: add Read() characteristic method implementations for Linux and nRF528xx Signed-off-by: deadprogram --- adapter_nrf528xx.go | 10 ++++++++++ examples/discover/main.go | 6 ++++++ gattc_darwin.go | 5 +++++ gattc_linux.go | 6 ++++++ gattc_sd.go | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+) diff --git a/adapter_nrf528xx.go b/adapter_nrf528xx.go index 2327996..017ecde 100644 --- a/adapter_nrf528xx.go +++ b/adapter_nrf528xx.go @@ -219,6 +219,16 @@ func handleEvent() { } } } + case C.BLE_GATTC_EVT_READ_RSP: + readEvent := gattcEvent.params.unionfield_read_rsp() + if debug { + println("evt: read response, data length", readEvent.len) + } + readingCharacteristic.handle_value.Set(readEvent.handle) + readingCharacteristic.offset = readEvent.offset + // Create a Go slice from the data. + readingCharacteristic.value = (*[255]byte)(unsafe.Pointer(&readEvent.data[0]))[:readEvent.len:readEvent.len] + case C.BLE_GATTC_EVT_HVX: hvxEvent := gattcEvent.params.unionfield_hvx() switch hvxEvent._type { diff --git a/examples/discover/main.go b/examples/discover/main.go index 1d2a616..2c5b6d6 100644 --- a/examples/discover/main.go +++ b/examples/discover/main.go @@ -68,6 +68,12 @@ func main() { } for _, char := range chars { println("-- characteristic", char.UUID().String()) + val, err := char.Read() + if err != nil { + println("---", err.Error()) + } else { + println("--- value =", string(val)) + } } } diff --git a/gattc_darwin.go b/gattc_darwin.go index 81f3541..e1e224d 100644 --- a/gattc_darwin.go +++ b/gattc_darwin.go @@ -145,3 +145,8 @@ func (c *DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) er return nil } + +// Read reads the current characteristic value. +func (c DeviceCharacteristic) Read() (data []byte, err error) { + return nil, nil +} diff --git a/gattc_linux.go b/gattc_linux.go index 865aec1..c353ebf 100644 --- a/gattc_linux.go +++ b/gattc_linux.go @@ -232,3 +232,9 @@ func (c *DeviceCharacteristic) EnableNotifications(callback func(buf []byte)) er }() return c.characteristic.StartNotify() } + +// Read reads the current characteristic value. +func (c DeviceCharacteristic) Read() ([]byte, error) { + options := make(map[string]interface{}) + return c.characteristic.ReadValue(options) +} diff --git a/gattc_sd.go b/gattc_sd.go index 6a5fedf..43ce47a 100644 --- a/gattc_sd.go +++ b/gattc_sd.go @@ -337,6 +337,38 @@ func (c *DeviceCharacteristic) WriteWithoutResponse(p []byte) (n int, err error) return len(p), nil } +// A global used to pass information from the event handler back to the +// Read function below. +var readingCharacteristic struct { + handle_value volatile.Register16 + offset uint16 + value []byte +} + +// Read reads the current characteristic value up to MTU length. +// A future enhancement would be to be able to retrieve a longer +// value by making multiple calls. +func (c DeviceCharacteristic) Read() ([]byte, error) { + errCode := C.sd_ble_gattc_read(c.connectionHandle, c.valueHandle, 0) + if errCode != 0 { + return nil, Error(errCode) + } + + // wait for response with data + for readingCharacteristic.handle_value.Get() == 0 { + arm.Asm("wfe") + } + + // copy data since value is slice to unsafe pointer. + data := make([]byte, len(readingCharacteristic.value)) + copy(data, readingCharacteristic.value) + + // prepare for next read + readingCharacteristic.handle_value.Set(0) + + return data, nil +} + type gattcNotificationCallback struct { connectionHandle uint16 valueHandle uint16 // may be 0 if the slot is empty