Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion darwin/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,16 @@ func (d *Device) Option(opts ...ble.Option) error {
//
// Concurrent Scan operations will result in undefined behavior.
func (d *Device) Scan(ctx context.Context, allowDup bool, h ble.AdvHandler) error {
return d.scan(ctx, allowDup, h, nil)
}

// ScanWithServices behaves like Scan but forwards the service UUID filter to
// CoreBluetooth so macOS will request scan responses for matching devices.
func (d *Device) ScanWithServices(ctx context.Context, allowDup bool, h ble.AdvHandler, services []ble.UUID) error {
return d.scan(ctx, allowDup, h, services)
}

func (d *Device) scan(ctx context.Context, allowDup bool, h ble.AdvHandler, services []ble.UUID) error {
// Because the OS delivers results to the delegate
// DidDiscoverPeripheral concurrently, we need a way to handle
// events when a Scan is in progress, and safely discard them
Expand All @@ -117,7 +127,7 @@ func (d *Device) Scan(ctx context.Context, allowDup bool, h ble.AdvHandler) erro

// Start scanning, and stop scanning when the context expires.
go func() {
d.cm.Scan(nil, &cbgo.CentralManagerScanOpts{
d.cm.Scan(uuidsToCbgoUUIDs(services), &cbgo.CentralManagerScanOpts{
AllowDuplicates: allowDup,
})
Comment on lines 129 to 132
<-ctx.Done()
Expand Down
33 changes: 33 additions & 0 deletions gatt.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ var ErrDefaultDevice = errors.New("default device is not set")

var defaultDevice Device

type serviceScanner interface {
ScanWithServices(ctx context.Context, allowDup bool, h AdvHandler, services []UUID) error
}

// SetDefaultDevice returns the default HCI device.
func SetDefaultDevice(d Device) {
defaultDevice = d
Expand Down Expand Up @@ -100,6 +104,35 @@ func Scan(ctx context.Context, allowDup bool, h AdvHandler, f AdvFilter) error {
return defaultDevice.Scan(ctx, allowDup, h2)
}

// ScanWithServices starts scanning while requesting that the backend use the
// provided service UUIDs as native scan filters when supported.
func ScanWithServices(ctx context.Context, allowDup bool, h AdvHandler, f AdvFilter, services []UUID) error {
if defaultDevice == nil {
return ErrDefaultDevice
}
defer untrap(trap(ctx))

if len(services) == 0 {
return Scan(ctx, allowDup, h, f)
}
Comment on lines +113 to +117

scanner, ok := defaultDevice.(serviceScanner)
if !ok {
return Scan(ctx, allowDup, h, f)
}

if f == nil {
return scanner.ScanWithServices(ctx, allowDup, h, services)
}

h2 := func(a Advertisement) {
if f(a) {
h(a)
}
}
return scanner.ScanWithServices(ctx, allowDup, h2, services)
}

// Find ...
func Find(ctx context.Context, allowDup bool, f AdvFilter) ([]Advertisement, error) {
if defaultDevice == nil {
Expand Down
Loading