blob: 74f8aa355f1b9df97fc41de454b40c521277dfc8 [file] [log] [blame]
package evt
import (
"bytes"
"encoding/binary"
"errors"
"github.com/paypal/gatt/linux/util"
)
type EventHandler interface {
HandleEvent([]byte) error
}
type HandlerFunc func(b []byte) error
func (f HandlerFunc) HandleEvent(b []byte) error {
return f(b)
}
type Evt struct {
evtHandlers map[int]EventHandler
}
func NewEvt() *Evt {
return &Evt{
evtHandlers: map[int]EventHandler{},
}
}
func (e *Evt) HandleEvent(c int, h EventHandler) {
e.evtHandlers[c] = h
}
func (e *Evt) Dispatch(b []byte) error {
h := &EventHeader{}
if err := h.Unmarshal(b); err != nil {
return err
}
b = b[2:] // Skip Event Header (uint8 + uint8)
if f, found := e.evtHandlers[h.code]; found {
e.trace("> HCI Event: %s (0x%02X) plen %d: [ % X ])\n", h.code, uint8(h.code), h.plen, b)
return f.HandleEvent(b)
}
e.trace("> HCI Event: no handler for %s (0x%02X)\n", h.code, uint8(h.code))
return nil
}
func (e *Evt) trace(fmt string, v ...interface{}) {}
const (
InquiryComplete = 0x01 // Inquiry Complete
InquiryResult = 0x02 // Inquiry Result
ConnectionComplete = 0x03 // Connection Complete
ConnectionRequest = 0x04 // Connection Request
DisconnectionComplete = 0x05 // Disconnection Complete
AuthenticationComplete = 0x06 // Authentication
RemoteNameReqComplete = 0x07 // Remote Name Request Complete
EncryptionChange = 0x08 // Encryption Change
ChangeConnectionLinkKeyComplete = 0x09 // Change Conection Link Key Complete
MasterLinkKeyComplete = 0x0A // Master Link Keye Complete
ReadRemoteSupportedFeaturesComplete = 0x0B // Read Remote Supported Features Complete
ReadRemoteVersionInformationComplete = 0x0C // Read Remote Version Information Complete
QoSSetupComplete = 0x0D // QoSSetupComplete
CommandComplete = 0x0E // Command Complete
CommandStatus = 0x0F // Command status
HardwareError = 0x10 // Hardware Error
FlushOccurred = 0x11 // Flush Occured
RoleChange = 0x12 // Role Change
NumberOfCompletedPkts = 0x13 // Number Of Completed Packets
ModeChange = 0x14 // Mode Change
ReturnLinkKeys = 0x15 // Return Link Keys
PinCodeRequest = 0x16 // PIN Code Request
LinkKeyRequest = 0x17 // Link Key Request
LinkKeyNotification = 0x18 // Link Key Notification
LoopbackCommand = 0x19 // Loopback Command
DataBufferOverflow = 0x1A // Data Buffer Overflow
MaxSlotsChange = 0x1B // Max Slots Change
ReadClockOffsetComplete = 0x1C // Read Clock Offset Complete
ConnectionPtypeChanged = 0x1D // Connection Packet Type Changed
QoSViolation = 0x1E // QoS Violation
PageScanRepetitionModeChange = 0x20 // Page Scan Repetition Mode Change
FlowSpecificationComplete = 0x21 // Flow Specification
InquiryResultWithRssi = 0x22 // Inquery Result with RSSI
ReadRemoteExtendedFeaturesComplete = 0x23 // Read Remote Extended Features Complete
SyncConnectionComplete = 0x2C // Synchronous Connection Complete
SyncConnectionChanged = 0x2D // Synchronous Connection Changed
SniffSubrating = 0x2E // Sniff Subrating
ExtendedInquiryResult = 0x2F // Extended Inquiry Result
EncryptionKeyRefreshComplete = 0x30 // Encryption Key Refresh Complete
IOCapabilityRequest = 0x31 // IO Capability Request
IOCapabilityResponse = 0x32 // IO Capability Changed
UserConfirmationRequest = 0x33 // User Confirmation Request
UserPasskeyRequest = 0x34 // User Passkey Request
RemoteOOBDataRequest = 0x35 // Remote OOB Data
SimplePairingComplete = 0x36 // Simple Pairing Complete
LinkSupervisionTimeoutChanged = 0x38 // Link Supervision Timeout Changed
EnhancedFlushComplete = 0x39 // Enhanced Flush Complete
UserPasskeyNotify = 0x3B // User Passkey Notification
KeypressNotify = 0x3C // Keypass Notification
RemoteHostFeaturesNotify = 0x3D // Remote Host Supported Features Notification
LEMeta = 0x3E // LE Meta
PhysicalLinkComplete = 0x40 // Physical Link Complete
ChannelSelected = 0x41 // Channel Selected
DisconnectionPhysicalLinkComplete = 0x42 // Disconnection Physical Link Complete
PhysicalLinkLossEarlyWarning = 0x43 // Physical Link Loss Early Warning
PhysicalLinkRecovery = 0x44 // Physical Link Recovery
LogicalLinkComplete = 0x45 // Logical Link Complete
DisconnectionLogicalLinkComplete = 0x46 // Disconnection Logical Link Complete
FlowSpecModifyComplete = 0x47 // Flow Spec Modify Complete
NumberOfCompletedBlocks = 0x48 // Number Of Completed Data Blocks
AMPStartTest = 0x49 // AMP Start Test
AMPTestEnd = 0x4A // AMP Test End
AMPReceiverReport = 0x4b // AMP Receiver Report
AMPStatusChange = 0x4D // AMP status Change
TriggeredClockCapture = 0x4e // Triggered Clock Capture
SynchronizationTrainComplete = 0x4F // Synchronization Train Complete
SynchronizationTrainReceived = 0x50 // Synchronization Train Received
ConnectionlessSlaveBroadcastReceive = 0x51 // Connectionless Slave Broadcast Receive
ConnectionlessSlaveBroadcastTimeout = 0x52 // Connectionless Slave Broadcast Timeout
TruncatedPageComplete = 0x53 // Truncated Page Complete
SlavePageResponseTimeout = 0x54 // Slave Page Response Timeout
ConnectionlessSlaveBroadcastChannelMapChange = 0x55 // Connectionless Slave Broadcast Channel Map Change
InquiryResponseNotification = 0x56 // Inquiry Response Notification
AuthenticatedPayloadTimeoutExpired = 0x57 // Authenticated Payload Timeout Expired
)
type LEEventCode int
const (
LEConnectionComplete LEEventCode = 0x01 // LE Connection Complete
LEAdvertisingReport = 0x02 // LE Advertising Report
LEConnectionUpdateComplete = 0x03 // LE Connection Update Complete
LEReadRemoteUsedFeaturesComplete = 0x04 // LE Read Remote Used Features Complete
LELTKRequest = 0x05 // LE LTK Request
LERemoteConnectionParameterRequest = 0x06 // LE Remote Connection Parameter Request
)
type EventHeader struct {
code int
plen uint8
}
func (h *EventHeader) Unmarshal(b []byte) error {
if len(b) < 2 {
return errors.New("malformed header")
}
h.code = int(b[0])
h.plen = b[1]
if uint8(len(b)) != 2+h.plen {
return errors.New("wrong length")
}
return nil
}
var o = util.Order
// Event Parameters
type InquiryCompleteEP struct {
Status uint8
}
type InquiryResultEP struct {
NumResponses uint8
BDAddr [][6]byte
PageScanRepetitionMode []uint8
Reserved1 []byte
Reserved2 []byte
ClassOfDevice [][3]byte
ClockOffset []uint16
}
type ConnectionCompleteEP struct {
Status uint8
ConnectionHandle uint16
BDAddr [6]byte
LinkType uint8
EncryptionEnabled uint8
}
type ConnectionRequestEP struct {
BDAddr [6]byte
ClassofDevice [3]byte
LinkType uint8
}
type DisconnectionCompleteEP struct {
Status uint8
ConnectionHandle uint16
Reason uint8
}
func (e *DisconnectionCompleteEP) Unmarshal(b []byte) error {
buf := bytes.NewBuffer(b)
binary.Read(buf, binary.LittleEndian, &e.Status)
binary.Read(buf, binary.LittleEndian, &e.ConnectionHandle)
return binary.Read(buf, binary.LittleEndian, &e.Reason)
}
type CommandCompleteEP struct {
NumHCICommandPackets uint8
CommandOPCode uint16
ReturnParameters []byte
}
func (e *CommandCompleteEP) Unmarshal(b []byte) error {
buf := bytes.NewBuffer(b)
if err := binary.Read(buf, binary.LittleEndian, &e.NumHCICommandPackets); err != nil {
return err
}
if err := binary.Read(buf, binary.LittleEndian, &e.CommandOPCode); err != nil {
return err
}
e.ReturnParameters = buf.Bytes()
return nil
}
type CommandStatusEP struct {
Status uint8
NumHCICommandPackets uint8
CommandOpcode uint16
}
func (e *CommandStatusEP) Unmarshal(b []byte) error {
buf := bytes.NewBuffer(b)
binary.Read(buf, binary.LittleEndian, &e.Status)
binary.Read(buf, binary.LittleEndian, &e.NumHCICommandPackets)
return binary.Read(buf, binary.LittleEndian, &e.CommandOpcode)
}
type NumOfCompletedPkt struct {
ConnectionHandle uint16
NumOfCompletedPkts uint16
}
type NumberOfCompletedPktsEP struct {
NumberOfHandles uint8
Packets []NumOfCompletedPkt
}
func (e *NumberOfCompletedPktsEP) Unmarshal(b []byte) error {
e.NumberOfHandles = b[0]
n := int(e.NumberOfHandles)
buf := bytes.NewBuffer(b[1:])
e.Packets = make([]NumOfCompletedPkt, n)
for i := 0; i < n; i++ {
binary.Read(buf, binary.LittleEndian, &e.Packets[i].ConnectionHandle)
binary.Read(buf, binary.LittleEndian, &e.Packets[i].NumOfCompletedPkts)
e.Packets[i].ConnectionHandle &= 0xfff
}
return nil
}
// LE Meta Subevents
type LEConnectionCompleteEP struct {
SubeventCode uint8
Status uint8
ConnectionHandle uint16
Role uint8
PeerAddressType uint8
PeerAddress [6]byte
ConnInterval uint16
ConnLatency uint16
SupervisionTimeout uint16
MasterClockAccuracy uint8
}
func (e *LEConnectionCompleteEP) Unmarshal(b []byte) error {
e.SubeventCode = o.Uint8(b[0:])
e.Status = o.Uint8(b[1:])
e.ConnectionHandle = o.Uint16(b[2:])
e.Role = o.Uint8(b[4:])
e.PeerAddressType = o.Uint8(b[5:])
e.PeerAddress = o.MAC(b[6:])
e.ConnInterval = o.Uint16(b[12:])
e.ConnLatency = o.Uint16(b[14:])
e.SupervisionTimeout = o.Uint16(b[16:])
e.MasterClockAccuracy = o.Uint8(b[17:])
return nil
}
type LEAdvertisingReportEP struct {
SubeventCode uint8
NumReports uint8
EventType []uint8
AddressType []uint8
Address [][6]byte
Length []uint8
Data [][]byte
RSSI []int8
}
func (e *LEAdvertisingReportEP) Unmarshal(b []byte) error {
e.SubeventCode = o.Uint8(b)
b = b[1:]
e.NumReports = o.Uint8(b)
b = b[1:]
n := int(e.NumReports)
e.EventType = make([]uint8, n)
e.AddressType = make([]uint8, n)
e.Address = make([][6]byte, n)
e.Length = make([]uint8, n)
e.Data = make([][]byte, n)
e.RSSI = make([]int8, n)
for i := 0; i < n; i++ {
e.EventType[i] = o.Uint8(b)
b = b[1:]
}
for i := 0; i < n; i++ {
e.AddressType[i] = o.Uint8(b)
b = b[1:]
}
for i := 0; i < n; i++ {
e.Address[i] = o.MAC(b)
b = b[6:]
}
for i := 0; i < n; i++ {
e.Length[i] = o.Uint8(b)
b = b[1:]
}
for i := 0; i < n; i++ {
e.Data[i] = make([]byte, e.Length[i])
copy(e.Data[i], b)
b = b[e.Length[i]:]
}
for i := 0; i < n; i++ {
e.RSSI[i] = o.Int8(b)
b = b[1:]
}
return nil
}
type LEConnectionUpdateCompleteEP struct {
SubeventCode uint8
Status uint8
ConnectionHandle uint16
ConnInterval uint16
ConnLatency uint16
SupervisionTimeout uint16
}
func (e *LEConnectionUpdateCompleteEP) Unmarshal(b []byte) error {
return binary.Read(bytes.NewBuffer(b), binary.LittleEndian, e)
}
type LEReadRemoteUsedFeaturesCompleteEP struct {
SubeventCode uint8
Status uint8
ConnectionHandle uint16
LEFeatures uint64
}
func (e *LEReadRemoteUsedFeaturesCompleteEP) Unmarshal(b []byte) error {
return binary.Read(bytes.NewBuffer(b), binary.LittleEndian, e)
}
type LELTKRequestEP struct {
SubeventCode uint8
ConnectionHandle uint16
RandomNumber uint64
EncryptionDiversifier uint16
}
func (e *LELTKRequestEP) Unmarshal(b []byte) error {
return binary.Read(bytes.NewBuffer(b), binary.LittleEndian, e)
}
type LERemoteConnectionParameterRequestEP struct {
SubeventCode uint8
ConnectionHandle uint16
IntervalMin uint16
IntervalMax uint16
Latency uint16
Timeout uint16
}
func (e *LERemoteConnectionParameterRequestEP) Unmarshal(b []byte) error {
return binary.Read(bytes.NewBuffer(b), binary.LittleEndian, e)
}