Søren Rasmussen
07a23c1845
Some checks reported errors
continuous-integration/drone/push Build encountered an error
136 lines
3.3 KiB
Go
136 lines
3.3 KiB
Go
// pmgrdlg.go: Implements the PeripheralManagerDelegate interface.
|
|
// CoreBluetooth communicates events asynchronously via callbacks. This file
|
|
// implements a synchronous interface by translating these callbacks into
|
|
// channel operations.
|
|
|
|
package darwin
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/JuulLabs-OSS/ble"
|
|
"github.com/JuulLabs-OSS/cbgo"
|
|
)
|
|
|
|
func (d *Device) PeripheralManagerDidUpdateState(pmgr cbgo.PeripheralManager) {
|
|
d.evl.stateChanged.RxSignal(struct{}{})
|
|
}
|
|
|
|
func (d *Device) DidAddService(pmgr cbgo.PeripheralManager, svc cbgo.Service, err error) {
|
|
d.evl.svcAdded.RxSignal(err)
|
|
}
|
|
|
|
func (d *Device) DidStartAdvertising(pmgr cbgo.PeripheralManager, err error) {
|
|
d.evl.advStarted.RxSignal(err)
|
|
}
|
|
|
|
func (d *Device) DidReceiveReadRequest(pmgr cbgo.PeripheralManager, cbreq cbgo.ATTRequest) {
|
|
chr, _ := d.pc.findChr(cbreq.Characteristic())
|
|
if chr == nil || chr.ReadHandler == nil {
|
|
return
|
|
}
|
|
|
|
c := d.findConn(cbreq.Central().Identifier())
|
|
if c == nil {
|
|
var err error
|
|
c, err = newPeripheralConn(d, cbreq.Central())
|
|
if err != nil {
|
|
log.Printf("failed to process read response: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
req := ble.NewRequest(c, nil, cbreq.Offset())
|
|
buf := bytes.NewBuffer(make([]byte, 0, c.txMTU-1))
|
|
rsp := ble.NewResponseWriter(buf)
|
|
chr.ReadHandler.ServeRead(req, rsp)
|
|
cbreq.SetValue(buf.Bytes())
|
|
|
|
pmgr.RespondToRequest(cbreq, cbgo.ATTError(rsp.Status()))
|
|
}
|
|
|
|
func (d *Device) DidReceiveWriteRequests(pmgr cbgo.PeripheralManager, cbreqs []cbgo.ATTRequest) {
|
|
serveOne := func(cbreq cbgo.ATTRequest) {
|
|
chr, _ := d.pc.findChr(cbreq.Characteristic())
|
|
if chr == nil || chr.WriteHandler == nil {
|
|
return
|
|
}
|
|
|
|
c := d.findConn(cbreq.Central().Identifier())
|
|
if c == nil {
|
|
var err error
|
|
c, err = newPeripheralConn(d, cbreq.Central())
|
|
if err != nil {
|
|
log.Printf("failed to process write response: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
req := ble.NewRequest(c, cbreq.Value(), cbreq.Offset())
|
|
rsp := ble.NewResponseWriter(nil)
|
|
chr.WriteHandler.ServeWrite(req, rsp)
|
|
|
|
pmgr.RespondToRequest(cbreq, cbgo.ATTError(rsp.Status()))
|
|
}
|
|
|
|
for _, cbreq := range cbreqs {
|
|
serveOne(cbreq)
|
|
}
|
|
}
|
|
|
|
func (d *Device) CentralDidSubscribe(pmgr cbgo.PeripheralManager, cent cbgo.Central, cbchr cbgo.Characteristic) {
|
|
c := d.findConn(cent.Identifier())
|
|
if c == nil {
|
|
var err error
|
|
c, err = newPeripheralConn(d, cent)
|
|
if err != nil {
|
|
log.Printf("failed to process subscribe request: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
if c.notifiers[cbchr] != nil {
|
|
return
|
|
}
|
|
|
|
chr, _ := d.pc.findChr(cbchr)
|
|
if chr == nil {
|
|
return
|
|
}
|
|
|
|
send := func(b []byte) (int, error) {
|
|
sent := d.pm.UpdateValue(b, cbchr, nil)
|
|
if !sent {
|
|
return len(b), fmt.Errorf("failed to send notification: tx queue full")
|
|
}
|
|
|
|
return len(b), nil
|
|
}
|
|
n := ble.NewNotifier(send)
|
|
c.notifiers[cbchr] = n
|
|
req := ble.NewRequest(c, nil, 0) // convey *conn to user handler.
|
|
|
|
go chr.NotifyHandler.ServeNotify(req, n)
|
|
}
|
|
|
|
func (d *Device) CentralDidUnsubscribe(pmgr cbgo.PeripheralManager, cent cbgo.Central, chr cbgo.Characteristic) {
|
|
c := d.findConn(cent.Identifier())
|
|
if c == nil {
|
|
var err error
|
|
c, err = newPeripheralConn(d, cent)
|
|
if err != nil {
|
|
log.Printf("failed to process unsubscribe request: %v", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
n := c.notifiers[chr]
|
|
if n != nil {
|
|
if err := n.Close(); err != nil {
|
|
log.Printf("failed to close notifier: %v", err)
|
|
}
|
|
delete(c.notifiers, chr)
|
|
}
|
|
}
|