Commit 87f246c4 authored by Tzu-Jung Lee's avatar Tzu-Jung Lee
Browse files

adv: rework adverisement

1. Quick hack to make bt.Advertisement interface, have HCI implement it.
   Currently, it's too HCI-specific. So let's separate the interface and
   ipmlementation first. Later on, removed HCI-specific details from the
   interface, and keep the in the HCI implementation.

2. Associate the Scan Response to the Advertising Data.
parent f47f4eec
package bt
import (
"net"
"github.com/currantlabs/bt/hci/evt"
)
import "net"
// AdvFilter ...
type AdvFilter interface {
......@@ -34,30 +30,22 @@ func (f AdvHandlerFunc) Handle(a Advertisement) {
}
// Advertisement ...
type Advertisement struct {
e evt.LEAdvertisingReport
i int
}
type Advertisement interface {
// EventType ...
EventType() uint8
// NewAdvertisement ...
func NewAdvertisement(e evt.LEAdvertisingReport, i int) *Advertisement {
return &Advertisement{e: e, i: i}
}
// AddressType ...
AddressType() uint8
// EventType ...
func (a Advertisement) EventType() uint8 { return a.e.EventType(a.i) }
// RSSI ...
RSSI() int8
// AddressType ...
func (a Advertisement) AddressType() uint8 { return a.e.AddressType(a.i) }
// Address ...
Address() net.HardwareAddr
// RSSI ...
func (a Advertisement) RSSI() int8 { return a.e.RSSI(a.i) }
// Data ...
Data() []byte
// Address ...
func (a Advertisement) Address() net.HardwareAddr {
b := a.e.Address(a.i)
return []byte{b[5], b[4], b[3], b[2], b[1], b[0]}
// ScanResponse ...
ScanResponse() []byte
}
// Data ...
func (a Advertisement) Data() []byte { return a.e.Data(a.i) }
......@@ -134,7 +134,8 @@ func (c centralManagerCilent) ExchangeMTU(rxMTU int) (int, error) {
}
func (m *centralManager) advFilter(a bt.Advertisement) bool {
if adv.Packet(a.Data()).LocalName() != "Gopher" {
p := adv.Packet(append(a.Data(), a.ScanResponse()...))
if p.LocalName() != "Gopher" {
return false
}
m.visitedLock.RLock()
......
......@@ -28,3 +28,12 @@ const (
roleMaster = 0x00
roleSlave = 0x01
)
// [Vol 6, Part B, 4.4.2] [Vol 3, Part C, 11]
const (
evtTypAdvInd = 0x00 // Connectable undirected advertising (ADV_IND).
evtTypAdvDirectInd = 0x01 // Connectable directed advertising (ADV_DIRECT_IND).
evtTypAdvScanInd = 0x02 // Scannable undirected advertising (ADV_SCAN_IND).
evtTypAdvNonconnInd = 0x03 // Non connectable undirected advertising (ADV_NONCONN_IND).
evtTypScanRsp = 0x04 // Scan Response (SCAN_RSP).
)
......@@ -227,6 +227,8 @@ func (h *HCI) send(c Command) ([]byte, error) {
}
func (h *HCI) asyncLoop() {
var ad []*advertisement
var last int
for {
select {
case <-h.done:
......@@ -242,10 +244,40 @@ func (h *HCI) asyncLoop() {
// err = fmt.Errorf("hci: unsupported event packet: [ % X ]", b)
case <-h.chStartScan:
h.chAdvEvt = make(chan []byte, 16)
ad = make([]*advertisement, 16)
last = 0
case b := <-h.chAdvEvt:
e := evt.LEAdvertisingReport(b)
for i := 0; i < int(e.NumReports()); i++ {
a := bt.NewAdvertisement(e, i)
var a *advertisement
switch e.EventType(i) {
case evtTypAdvInd:
fallthrough
case evtTypAdvScanInd:
a = newAdvertisement(e, i)
ad[last] = a
last++
if last == len(ad) {
last = 0
}
case evtTypScanRsp:
sr := newAdvertisement(e, i)
for idx := last - 1; idx != last; idx-- {
if idx == -1 {
idx = len(ad) - 1
}
if ad[idx] == nil {
break
}
if ad[idx].Address().String() == sr.Address().String() {
ad[idx].sr = sr
a = ad[idx]
break
}
}
default:
a = newAdvertisement(e, i)
}
if h.advFilter != nil && h.advFilter.Filter(*a) {
h.advHandler.Handle(*a)
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment