134 lines
2.8 KiB
Go
134 lines
2.8 KiB
Go
|
package darwin
|
||
|
|
||
|
// profcache: Profile Cache. This allows a device to match profile objects
|
||
|
// with their corresponding CoreBluetooth objects (e.g., ble.Servive <->
|
||
|
// cbgo.Service).
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/JuulLabs-OSS/ble"
|
||
|
"github.com/JuulLabs-OSS/cbgo"
|
||
|
)
|
||
|
|
||
|
type profCache struct {
|
||
|
mtx sync.RWMutex
|
||
|
|
||
|
svcCbMap map[*ble.Service]cbgo.Service
|
||
|
chrCbMap map[*ble.Characteristic]cbgo.Characteristic
|
||
|
dscCbMap map[*ble.Descriptor]cbgo.Descriptor
|
||
|
|
||
|
cbSvcMap map[cbgo.Service]*ble.Service
|
||
|
cbChrMap map[cbgo.Characteristic]*ble.Characteristic
|
||
|
cbDscMap map[cbgo.Descriptor]*ble.Descriptor
|
||
|
}
|
||
|
|
||
|
func newProfCache() profCache {
|
||
|
return profCache{
|
||
|
svcCbMap: map[*ble.Service]cbgo.Service{},
|
||
|
chrCbMap: map[*ble.Characteristic]cbgo.Characteristic{},
|
||
|
dscCbMap: map[*ble.Descriptor]cbgo.Descriptor{},
|
||
|
|
||
|
cbSvcMap: map[cbgo.Service]*ble.Service{},
|
||
|
cbChrMap: map[cbgo.Characteristic]*ble.Characteristic{},
|
||
|
cbDscMap: map[cbgo.Descriptor]*ble.Descriptor{},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) addSvc(s *ble.Service, cbs cbgo.Service) {
|
||
|
pc.mtx.Lock()
|
||
|
defer pc.mtx.Unlock()
|
||
|
|
||
|
pc.svcCbMap[s] = cbs
|
||
|
pc.cbSvcMap[cbs] = s
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) addChr(c *ble.Characteristic, cbc cbgo.Characteristic) {
|
||
|
pc.mtx.Lock()
|
||
|
defer pc.mtx.Unlock()
|
||
|
|
||
|
pc.chrCbMap[c] = cbc
|
||
|
pc.cbChrMap[cbc] = c
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) addDsc(d *ble.Descriptor, cbd cbgo.Descriptor) {
|
||
|
pc.mtx.Lock()
|
||
|
defer pc.mtx.Unlock()
|
||
|
|
||
|
pc.dscCbMap[d] = cbd
|
||
|
pc.cbDscMap[cbd] = d
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) findCbSvc(s *ble.Service) (cbgo.Service, error) {
|
||
|
pc.mtx.RLock()
|
||
|
defer pc.mtx.RUnlock()
|
||
|
|
||
|
cbs, ok := pc.svcCbMap[s]
|
||
|
if !ok {
|
||
|
return cbs, fmt.Errorf("no CB service with UUID=%v", s.UUID)
|
||
|
}
|
||
|
|
||
|
return cbs, nil
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) findSvc(cbs cbgo.Service) (*ble.Service, error) {
|
||
|
pc.mtx.RLock()
|
||
|
defer pc.mtx.RUnlock()
|
||
|
|
||
|
s, ok := pc.cbSvcMap[cbs]
|
||
|
if !ok {
|
||
|
return nil, fmt.Errorf("no service with UUID=%v", cbs.UUID())
|
||
|
}
|
||
|
|
||
|
return s, nil
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) findCbChr(c *ble.Characteristic) (cbgo.Characteristic, error) {
|
||
|
pc.mtx.RLock()
|
||
|
defer pc.mtx.RUnlock()
|
||
|
|
||
|
cbc, ok := pc.chrCbMap[c]
|
||
|
if !ok {
|
||
|
return cbc, fmt.Errorf("no CB characteristic with UUID=%v", c.UUID)
|
||
|
}
|
||
|
|
||
|
return cbc, nil
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) findChr(cbc cbgo.Characteristic) (*ble.Characteristic, error) {
|
||
|
pc.mtx.RLock()
|
||
|
defer pc.mtx.RUnlock()
|
||
|
|
||
|
c, ok := pc.cbChrMap[cbc]
|
||
|
if !ok {
|
||
|
return nil, fmt.Errorf("no characteristic with UUID=%v", cbc.UUID())
|
||
|
}
|
||
|
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) findCbDsc(d *ble.Descriptor) (cbgo.Descriptor, error) {
|
||
|
pc.mtx.RLock()
|
||
|
defer pc.mtx.RUnlock()
|
||
|
|
||
|
cbd, ok := pc.dscCbMap[d]
|
||
|
if !ok {
|
||
|
return cbd, fmt.Errorf("no CB descriptor with UUID=%v", d.UUID)
|
||
|
}
|
||
|
|
||
|
return cbd, nil
|
||
|
}
|
||
|
|
||
|
func (pc *profCache) findDsc(cbd cbgo.Descriptor) (*ble.Descriptor, error) {
|
||
|
pc.mtx.RLock()
|
||
|
defer pc.mtx.RUnlock()
|
||
|
|
||
|
d, ok := pc.cbDscMap[cbd]
|
||
|
if !ok {
|
||
|
return nil, fmt.Errorf("no descriptor with UUID=%v", cbd.UUID())
|
||
|
}
|
||
|
|
||
|
return d, nil
|
||
|
}
|