prototooth/gap_linux.go
Ayke van Laethem e453c4d3f9
Add Linux support
Very much experimental, no BLE service support yet and BLE LocalName in
advertisement packet doesn't seem to work. So rather useless at the
moment.
2019-11-09 17:55:19 +01:00

81 lines
2.0 KiB
Go

// +build !baremetal
package bluetooth
import (
"errors"
"github.com/muka/go-bluetooth/api"
"github.com/muka/go-bluetooth/bluez/profile/advertising"
)
var (
ErrMalformedAdvertisement = errors.New("bluetooth: malformed advertisement packet")
)
// Advertisement encapsulates a single advertisement instance.
type Advertisement struct {
adapter *Adapter
advertisement *api.Advertisement
properties *advertising.LEAdvertisement1Properties
}
// NewAdvertisement creates a new advertisement instance but does not configure
// it.
func (a *Adapter) NewAdvertisement() *Advertisement {
return &Advertisement{
adapter: a,
}
}
// Configure this advertisement.
func (a *Advertisement) Configure(broadcastData, scanResponseData []byte, options *AdvertiseOptions) error {
if a.advertisement != nil {
panic("todo: configure advertisement a second time")
}
if scanResponseData != nil {
panic("todo: scan response data")
}
// Quick-and-dirty advertisement packet parser.
a.properties = &advertising.LEAdvertisement1Properties{
Type: advertising.AdvertisementTypeBroadcast,
Timeout: 1<<16 - 1,
}
for len(broadcastData) != 0 {
if len(broadcastData) < 2 {
return ErrMalformedAdvertisement
}
fieldLength := broadcastData[0]
fieldType := broadcastData[1]
fieldValue := broadcastData[2 : fieldLength+1]
if int(fieldLength) > len(broadcastData) {
return ErrMalformedAdvertisement
}
switch fieldType {
case 1:
// BLE advertisement flags. Ignore.
case 9:
// Complete Local Name.
a.properties.LocalName = string(fieldValue)
default:
return ErrMalformedAdvertisement
}
broadcastData = broadcastData[fieldLength+1:]
}
return nil
}
// Start advertisement. May only be called after it has been configured.
func (a *Advertisement) Start() error {
if a.advertisement != nil {
panic("todo: start advertisement a second time")
}
_, err := api.ExposeAdvertisement(a.adapter.id, a.properties, uint32(a.properties.Timeout))
if err != nil {
return err
}
return nil
}