Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions gap.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,61 @@ func (buf *rawAdvertisementPayload) addServiceUUID(uuid UUID) (ok bool) {
}
}

// ConnectionPriority is a coarse description of what a connection should be
// optimized for.
//
// It exists because not every platform accepts the connection parameters from
// the Bluetooth Core Specification. Some only accept a small fixed set of
// presets: on Windows, BluetoothLEPreferredConnectionParameters has no public
// constructor, just the static ThroughputOptimized, Balanced and PowerOptimized
// sets. A ConnectionPriority is the form of the request that those platforms
// can honour, and it maps onto the same three-way split that Android
// (CONNECTION_PRIORITY_HIGH, BALANCED and LOW_POWER) and CoreBluetooth
// (CBPeripheralManagerConnectionLatency low, medium and high) also use.
//
// The constants are named after the trade-off rather than after the resulting
// latency on purpose: those vendor enumerations do not agree on a direction, so
// that Apple's "low" and Android's "high" mean the same thing, and a name like
// "low" would be read backwards by half of the audience. It also keeps the term
// "connection latency" free, which the Core Specification uses for the number of
// connection events a peripheral may skip.
type ConnectionPriority uint8

const (
// ConnectionPriorityUnspecified leaves the connection parameters unchanged.
// It is the zero value, matching the other ConnectionParams fields, which
// also mean "leave alone" when unset.
ConnectionPriorityUnspecified ConnectionPriority = iota

// ConnectionPriorityThroughput optimizes for rapid communication, at the
// cost of power usage on both sides and of the number of connections the
// adapter can maintain at once. Suitable for a firmware update or another
// bulk transfer, and best used only for as long as it is needed.
ConnectionPriorityThroughput

// ConnectionPriorityBalanced balances communication speed against power
// usage.
ConnectionPriorityBalanced

// ConnectionPriorityPowerSaving optimizes for power usage and for the number
// of simultaneous connections, at the cost of communication speed.
ConnectionPriorityPowerSaving
)

// String returns a lowercase name for the priority, for use in logs.
func (p ConnectionPriority) String() string {
switch p {
case ConnectionPriorityThroughput:
return "throughput"
case ConnectionPriorityBalanced:
return "balanced"
case ConnectionPriorityPowerSaving:
return "power-saving"
default:
return "unspecified"
}
}

// ConnectionParams are used when connecting to a peripherals or when changing
// the parameters of an active connection.
type ConnectionParams struct {
Expand All @@ -612,6 +667,19 @@ type ConnectionParams struct {
// communication, the connection is considered lost. If no timeout is
// specified, the timeout will be unchanged.
Timeout Duration

// Priority is a coarse alternative to the fields above, for platforms that
// do not accept explicit connection parameters.
//
// The two are never mixed: a platform that can program the controller uses
// the explicit fields and ignores Priority, and a platform that only accepts
// presets uses Priority and ignores the explicit fields. Setting both is
// therefore the portable way to make a request, and is what a caller that
// runs on more than one platform should do.
//
// If Priority is unset, a platform that only accepts presets leaves the
// connection unchanged.
Priority ConnectionPriority
}

type PHY int
Expand Down
35 changes: 35 additions & 0 deletions gap_connparams_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package bluetooth

import "testing"

// The zero value has to stay ConnectionPriorityUnspecified, so that an unset
// Priority means "leave the connection alone" like every other field in
// ConnectionParams. Reordering the constants would silently change what an
// empty ConnectionParams asks for.
func TestConnectionPriorityZeroValue(t *testing.T) {
var priority ConnectionPriority
if priority != ConnectionPriorityUnspecified {
t.Errorf("zero value = %d, want ConnectionPriorityUnspecified", priority)
}
if got := (ConnectionParams{}).Priority; got != ConnectionPriorityUnspecified {
t.Errorf("ConnectionParams{}.Priority = %s, want unspecified", got)
}
}

func TestConnectionPriorityString(t *testing.T) {
tests := []struct {
priority ConnectionPriority
want string
}{
{ConnectionPriorityUnspecified, "unspecified"},
{ConnectionPriorityThroughput, "throughput"},
{ConnectionPriorityBalanced, "balanced"},
{ConnectionPriorityPowerSaving, "power-saving"},
{ConnectionPriority(99), "unspecified"},
}
for _, test := range tests {
if got := test.priority.String(); got != test.want {
t.Errorf("ConnectionPriority(%d).String() = %q, want %q", test.priority, got, test.want)
}
}
}
Loading