136 lines
3.6 KiB
Go
136 lines
3.6 KiB
Go
|
package hci
|
||
|
|
||
|
import (
|
||
|
"net"
|
||
|
|
||
|
"github.com/JuulLabs-OSS/ble"
|
||
|
"github.com/JuulLabs-OSS/ble/linux/adv"
|
||
|
"github.com/JuulLabs-OSS/ble/linux/hci/evt"
|
||
|
)
|
||
|
|
||
|
// RandomAddress is a Random Device Address.
|
||
|
type RandomAddress struct {
|
||
|
ble.Addr
|
||
|
}
|
||
|
|
||
|
// [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).
|
||
|
)
|
||
|
|
||
|
func newAdvertisement(e evt.LEAdvertisingReport, i int) *Advertisement {
|
||
|
return &Advertisement{e: e, i: i}
|
||
|
}
|
||
|
|
||
|
// Advertisement implements ble.Advertisement and other functions that are only
|
||
|
// available on Linux.
|
||
|
type Advertisement struct {
|
||
|
e evt.LEAdvertisingReport
|
||
|
i int
|
||
|
sr *Advertisement
|
||
|
|
||
|
// cached packets.
|
||
|
p *adv.Packet
|
||
|
}
|
||
|
|
||
|
// setScanResponse ssociate sca response to the existing advertisement.
|
||
|
func (a *Advertisement) setScanResponse(sr *Advertisement) {
|
||
|
a.sr = sr
|
||
|
a.p = nil // clear the cached.
|
||
|
}
|
||
|
|
||
|
// packets returns the combined advertising packet and scan response (if presents)
|
||
|
func (a *Advertisement) packets() *adv.Packet {
|
||
|
if a.p != nil {
|
||
|
return a.p
|
||
|
}
|
||
|
return adv.NewRawPacket(a.Data(), a.ScanResponse())
|
||
|
}
|
||
|
|
||
|
// LocalName returns the LocalName of the remote peripheral.
|
||
|
func (a *Advertisement) LocalName() string {
|
||
|
return a.packets().LocalName()
|
||
|
}
|
||
|
|
||
|
// ManufacturerData returns the ManufacturerData of the advertisement.
|
||
|
func (a *Advertisement) ManufacturerData() []byte {
|
||
|
return a.packets().ManufacturerData()
|
||
|
}
|
||
|
|
||
|
// ServiceData returns the service data of the advertisement.
|
||
|
func (a *Advertisement) ServiceData() []ble.ServiceData {
|
||
|
return a.packets().ServiceData()
|
||
|
}
|
||
|
|
||
|
// Services returns the service UUIDs of the advertisement.
|
||
|
func (a *Advertisement) Services() []ble.UUID {
|
||
|
return a.packets().UUIDs()
|
||
|
}
|
||
|
|
||
|
// OverflowService returns the UUIDs of overflowed service.
|
||
|
func (a *Advertisement) OverflowService() []ble.UUID {
|
||
|
return a.packets().UUIDs()
|
||
|
}
|
||
|
|
||
|
// TxPowerLevel returns the tx power level of the remote peripheral.
|
||
|
func (a *Advertisement) TxPowerLevel() int {
|
||
|
pwr, _ := a.packets().TxPower()
|
||
|
return pwr
|
||
|
}
|
||
|
|
||
|
// SolicitedService returns UUIDs of solicited services.
|
||
|
func (a *Advertisement) SolicitedService() []ble.UUID {
|
||
|
return a.packets().ServiceSol()
|
||
|
}
|
||
|
|
||
|
// Connectable indicates weather the remote peripheral is connectable.
|
||
|
func (a *Advertisement) Connectable() bool {
|
||
|
return a.EventType() == evtTypAdvDirectInd || a.EventType() == evtTypAdvInd
|
||
|
}
|
||
|
|
||
|
// RSSI returns RSSI signal strength.
|
||
|
func (a *Advertisement) RSSI() int {
|
||
|
return int(a.e.RSSI(a.i))
|
||
|
}
|
||
|
|
||
|
// Addr returns the address of the remote peripheral.
|
||
|
func (a *Advertisement) Addr() ble.Addr {
|
||
|
b := a.e.Address(a.i)
|
||
|
addr := net.HardwareAddr([]byte{b[5], b[4], b[3], b[2], b[1], b[0]})
|
||
|
if a.e.AddressType(a.i) == 1 {
|
||
|
return RandomAddress{addr}
|
||
|
}
|
||
|
return addr
|
||
|
}
|
||
|
|
||
|
// EventType returns the event type of Advertisement.
|
||
|
// This is linux sepcific.
|
||
|
func (a *Advertisement) EventType() uint8 {
|
||
|
return a.e.EventType(a.i)
|
||
|
}
|
||
|
|
||
|
// AddressType returns the address type of the Advertisement.
|
||
|
// This is linux sepcific.
|
||
|
func (a *Advertisement) AddressType() uint8 {
|
||
|
return a.e.AddressType(a.i)
|
||
|
}
|
||
|
|
||
|
// Data returns the advertising data of the packet.
|
||
|
// This is linux sepcific.
|
||
|
func (a *Advertisement) Data() []byte {
|
||
|
return a.e.Data(a.i)
|
||
|
}
|
||
|
|
||
|
// ScanResponse returns the scan response of the packet, if it presents.
|
||
|
// This is linux sepcific.
|
||
|
func (a *Advertisement) ScanResponse() []byte {
|
||
|
if a.sr == nil {
|
||
|
return nil
|
||
|
}
|
||
|
return a.sr.Data()
|
||
|
}
|