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 }