Commit 688d4aa2 authored by Kevin Seidel's avatar Kevin Seidel
Browse files

allow custom advertisement packets

parent 2e29b000
......@@ -2,7 +2,7 @@ package ble
// A Client is a GATT client.
type Client interface {
// Address returns platform specific unique ID of the remote peripheral, e.g. MAC on Linux, Client UUID on OS X.
// Addr returns platform specific unique ID of the remote peripheral, e.g. MAC on Linux, Client UUID on OS X.
Addr() Addr
// Name returns the name of the remote peripheral.
......
......@@ -121,6 +121,21 @@ func (d *Device) Init() error {
return nil
}
// Advertise advertises the given Advertisement
func (d *Device) Advertise(ctx context.Context, adv ble.Advertisement) error {
if err := d.sendReq(d.pm, 8, xpc.Dict{
"kCBAdvDataLocalName": adv.LocalName(),
"kCBAdvDataServiceUUIDs": adv.Services(),
"kCBAdvDataAppleMfgData": adv.ManufacturerData(),
}).err(); err != nil {
return err
}
<-ctx.Done()
d.stopAdvertising()
return ctx.Err()
}
// AdvertiseMfgData ...
func (d *Device) AdvertiseMfgData(ctx context.Context, id uint16, md []byte) error {
l := len(md)
......
......@@ -17,6 +17,9 @@ type Device interface {
// Stop detatch the GATT server from a peripheral device.
Stop() error
// Advertise advertises a given Advertisement
Advertise(ctx context.Context, adv Advertisement) error
// AdvertiseNameAndServices advertises device name, and specified service UUIDs.
// It tres to fit the UUIDs in the advertising packet as much as possi
// If name doesn't fit in the advertising packet, it will be put in scan response.
......
......@@ -93,6 +93,16 @@ func (d *Device) Stop() error {
return d.HCI.Close()
}
func (d *Device) Advertise(ctx context.Context, adv ble.Advertisement) error {
if err := d.HCI.AdvertiseAdv(adv); err != nil {
return err
}
<-ctx.Done()
d.HCI.StopAdvertising()
return ctx.Err()
}
// AdvertiseNameAndServices advertises device name, and specified service UUIDs.
// It tres to fit the UUIDs in the advertising packet as much as possible.
// If name doesn't fit in the advertising packet, it will be put in scan response.
......
......@@ -39,6 +39,51 @@ func (h *HCI) StopScanning() error {
return h.Send(&h.params.scanEnable, nil)
}
// AdvertiseAdv advertises a given Advertisement
func (h *HCI) AdvertiseAdv(a ble.Advertisement) error {
ad, err := adv.NewPacket(adv.Flags(adv.FlagGeneralDiscoverable | adv.FlagLEOnly))
if err != nil {
return err
}
f := adv.AllUUID
// Current length of ad packet plus two bytes of length and tag.
l := ad.Len() + 1 + 1
for _, u := range a.Services() {
l += u.Len()
}
if l > adv.MaxEIRPacketLength {
f = adv.SomeUUID
}
for _, u := range a.Services() {
if err := ad.Append(f(u)); err != nil {
if err == adv.ErrNotFit {
break
}
return err
}
}
sr, _ := adv.NewPacket()
switch {
case ad.Append(adv.CompleteName(a.LocalName())) == nil:
case sr.Append(adv.CompleteName(a.LocalName())) == nil:
case sr.Append(adv.ShortName(a.LocalName())) == nil:
}
if a.ManufacturerData() != nil {
manufacuturerData := adv.ManufacturerData(1337, a.ManufacturerData())
switch {
case ad.Append(manufacuturerData) == nil:
case sr.Append(manufacuturerData) == nil:
}
}
if err := h.SetAdvertisement(ad.Bytes(), sr.Bytes()); err != nil {
return nil
}
return h.Advertise()
}
// AdvertiseNameAndServices advertises device name, and specified service UUIDs.
// It tries to fit the UUIDs in the advertising data as much as possible.
// If name doesn't fit in the advertising data, it will be put in scan response.
......
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