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 package bt
import ( import "net"
"net"
"github.com/currantlabs/bt/hci/evt"
)
// AdvFilter ... // AdvFilter ...
type AdvFilter interface { type AdvFilter interface {
...@@ -34,30 +30,22 @@ func (f AdvHandlerFunc) Handle(a Advertisement) { ...@@ -34,30 +30,22 @@ func (f AdvHandlerFunc) Handle(a Advertisement) {
} }
// Advertisement ... // Advertisement ...
type Advertisement struct { type Advertisement interface {
e evt.LEAdvertisingReport // EventType ...
i int EventType() uint8
}
// NewAdvertisement ... // AddressType ...
func NewAdvertisement(e evt.LEAdvertisingReport, i int) *Advertisement { AddressType() uint8
return &Advertisement{e: e, i: i}
}
// EventType ... // RSSI ...
func (a Advertisement) EventType() uint8 { return a.e.EventType(a.i) } RSSI() int8
// AddressType ... // Address ...
func (a Advertisement) AddressType() uint8 { return a.e.AddressType(a.i) } Address() net.HardwareAddr
// RSSI ... // Data ...
func (a Advertisement) RSSI() int8 { return a.e.RSSI(a.i) } Data() []byte
// Address ... // ScanResponse ...
func (a Advertisement) Address() net.HardwareAddr { ScanResponse() []byte
b := a.e.Address(a.i)
return []byte{b[5], b[4], b[3], b[2], b[1], b[0]}
} }
// Data ...
func (a Advertisement) Data() []byte { return a.e.Data(a.i) }
...@@ -134,7 +134,8 @@ func (c centralManagerCilent) ExchangeMTU(rxMTU int) (int, error) { ...@@ -134,7 +134,8 @@ func (c centralManagerCilent) ExchangeMTU(rxMTU int) (int, error) {
} }
func (m *centralManager) advFilter(a bt.Advertisement) bool { 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 return false
} }
m.visitedLock.RLock() m.visitedLock.RLock()
......
...@@ -28,3 +28,12 @@ const ( ...@@ -28,3 +28,12 @@ const (
roleMaster = 0x00 roleMaster = 0x00
roleSlave = 0x01 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) { ...@@ -227,6 +227,8 @@ func (h *HCI) send(c Command) ([]byte, error) {
} }
func (h *HCI) asyncLoop() { func (h *HCI) asyncLoop() {
var ad []*advertisement
var last int
for { for {
select { select {
case <-h.done: case <-h.done:
...@@ -242,10 +244,40 @@ func (h *HCI) asyncLoop() { ...@@ -242,10 +244,40 @@ func (h *HCI) asyncLoop() {
// err = fmt.Errorf("hci: unsupported event packet: [ % X ]", b) // err = fmt.Errorf("hci: unsupported event packet: [ % X ]", b)
case <-h.chStartScan: case <-h.chStartScan:
h.chAdvEvt = make(chan []byte, 16) h.chAdvEvt = make(chan []byte, 16)
ad = make([]*advertisement, 16)
last = 0
case b := <-h.chAdvEvt: case b := <-h.chAdvEvt:
e := evt.LEAdvertisingReport(b) e := evt.LEAdvertisingReport(b)
for i := 0; i < int(e.NumReports()); i++ { 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) { if h.advFilter != nil && h.advFilter.Filter(*a) {
h.advHandler.Handle(*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