Skip to content
Merged
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
2 changes: 1 addition & 1 deletion linux/att/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func (r *DB) idx(h int) int {
if h < int(r.base) {
return tooSmall
}
if int(h) >= int(r.base)+len(r.attrs) {
if h >= int(r.base)+len(r.attrs) {
return tooLarge
}
return h - int(r.base)
Expand Down
2 changes: 1 addition & 1 deletion linux/att/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ func (s *Server) handleFindByTypeValueRequest(r FindByTypeValueRequest) []byte {

for _, a := range s.db.subrange(r.StartingHandle(), r.EndingHandle()) {
v, starth, endh := a.v, a.h, a.endh
if !(ble.UUID(a.typ).Equal(ble.UUID16(r.AttributeType()))) {
if !a.typ.Equal(ble.UUID16(r.AttributeType())) {
continue
}
if v == nil {
Expand Down
46 changes: 29 additions & 17 deletions linux/hci/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ type Conn struct {
txMTU int
rxMPS int

// leFrame is set to be true when the LE Credit based flow control is used.
leFrame bool

// Signaling MTUs are The maximum size of command information that the
// L2CAP layer entity is capable of accepting.
// A L2CAP implementations supporting LE-U should support at least 23 bytes.
Expand All @@ -47,23 +44,25 @@ type Conn struct {
sigRxMTU int
sigTxMTU int

// sigID is used to match responses with signaling requests.
// The requesting device sets this field and the responding device uses the
// same value in its response. Within each signalling channel a different
// Identifier shall be used for each successive command. [Vol 3, Part A, 4]
sigID uint8

sigSent chan []byte
smpSent chan []byte
// smpSent chan []byte

chInPkt chan packet
chInPDU chan pdu

chDone chan struct{}
// Host to Controller Data Flow Control pkt-based Data flow control for LE-U [Vol 2, Part E, 4.1.1]
// chSentBufs tracks the HCI buffer occupied by this connection.
txBuffer *Client

chDone chan struct{}
// sigID is used to match responses with signaling requests.
// The requesting device sets this field and the responding device uses the
// same value in its response. Within each signalling channel a different
// Identifier shall be used for each successive command. [Vol 3, Part A, 4]
sigID uint8

// leFrame is set to be true when the LE Credit based flow control is used.
leFrame bool
}

func newConn(h *HCI, param evt.LEConnectionComplete) *Conn {
Expand Down Expand Up @@ -94,7 +93,7 @@ func newConn(h *HCI, param evt.LEConnectionComplete) *Conn {
if err != io.EOF {
// TODO: wrap and pass the error up.
// err := errors.Wrap(err, "recombine failed")
logger.Error("recombine failed: ", "err", err)
_ = logger.Error("recombine failed: ", "err", err)
}
close(c.chInPDU)
return
Expand Down Expand Up @@ -140,7 +139,7 @@ func (c *Conn) Read(sdu []byte) (n int, err error) {
buf.Write(data)
for buf.Len() < slen {
p := <-c.chInPDU
buf.Write(pdu(p).payload())
buf.Write(p.payload())
}
return slen, nil
}
Expand Down Expand Up @@ -205,10 +204,23 @@ func (c *Conn) writePDU(pdu []byte) (int, error) {
}

// Prepare the Headers
binary.Write(pkt, binary.LittleEndian, uint8(pktTypeACLData)) // HCI Header: pkt Type
binary.Write(pkt, binary.LittleEndian, uint16(c.param.ConnectionHandle()|(flags<<8))) // ACL Header: handle and flags
binary.Write(pkt, binary.LittleEndian, uint16(flen)) // ACL Header: data len
binary.Write(pkt, binary.LittleEndian, pdu[:flen]) // Append payload

// HCI Header: pkt Type
if err := binary.Write(pkt, binary.LittleEndian, pktTypeACLData); err != nil {
return 0, err
}
// ACL Header: handle and flags
if err := binary.Write(pkt, binary.LittleEndian, c.param.ConnectionHandle()|(flags<<8)); err != nil {
return 0, err
}
// ACL Header: data len
if err := binary.Write(pkt, binary.LittleEndian, uint16(flen)); err != nil {
return 0, err
}
// Append payload
if err := binary.Write(pkt, binary.LittleEndian, pdu[:flen]); err != nil {
return 0, err
}

// Flush the pkt to HCI
select {
Expand Down
4 changes: 2 additions & 2 deletions linux/hci/hci.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ func (h *HCI) sktLoop() {
// Some bluetooth devices may append vendor specific packets at the last,
// in this case, simply ignore them.
if strings.HasPrefix(err.Error(), "unsupported vendor packet:") {
logger.Error("skt: %v", err)
_ = logger.Error("skt: %v", err)
} else {
h.err = fmt.Errorf("skt: %v", err)
return
Expand Down Expand Up @@ -317,7 +317,7 @@ func (h *HCI) handleACL(b []byte) error {
c, ok := h.conns[handle]
h.muConns.Unlock()
if !ok {
logger.Warn("invalid connection handle on ACL packet", "handle", handle)
_ = logger.Warn("invalid connection handle on ACL packet", "handle", handle)
return nil
}
c.chInPkt <- b
Expand Down
61 changes: 46 additions & 15 deletions linux/hci/signal.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// Signal ...
type Signal interface {
Code() int
Marshal() []byte
Marshal() ([]byte, error)
Unmarshal([]byte) error
}

Expand All @@ -26,15 +26,30 @@ func (s sigCmd) data() []byte { return s[4 : 4+s.len()] }

// Signal ...
func (c *Conn) Signal(req Signal, rsp Signal) error {
data := req.Marshal()
data, err := req.Marshal()
if err != nil {
return err
}
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, uint16(4+len(data)))
binary.Write(buf, binary.LittleEndian, uint16(cidLESignal))
if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(data))); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, cidLESignal); err != nil {
return err
}

binary.Write(buf, binary.LittleEndian, uint8(req.Code()))
binary.Write(buf, binary.LittleEndian, uint8(c.sigID))
binary.Write(buf, binary.LittleEndian, uint16(len(data)))
binary.Write(buf, binary.LittleEndian, data)
if err := binary.Write(buf, binary.LittleEndian, uint8(req.Code())); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, uint8(c.sigID)); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, uint16(len(data))); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, data); err != nil {
return err
}

c.sigSent = make(chan []byte)
defer close(c.sigSent)
Expand Down Expand Up @@ -63,13 +78,26 @@ func (c *Conn) Signal(req Signal, rsp Signal) error {
}

func (c *Conn) sendResponse(code uint8, id uint8, r Signal) (int, error) {
data := r.Marshal()
data, err := r.Marshal()
if err != nil {
return 0, err
}
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, uint16(4+len(data)))
binary.Write(buf, binary.LittleEndian, uint16(cidLESignal))
binary.Write(buf, binary.LittleEndian, uint8(code))
binary.Write(buf, binary.LittleEndian, uint8(id))
binary.Write(buf, binary.LittleEndian, uint16(len(data)))
if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(data))); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, cidLESignal); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, code); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, id); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, uint16(len(data))); err != nil {
return 0, err
}
if err := binary.Write(buf, binary.LittleEndian, data); err != nil {
return 0, err
}
Expand All @@ -85,13 +113,16 @@ func (c *Conn) handleSignal(p pdu) error {
// command in the L2CAP packet. If only Responses are recognized, the packet
// shall be silently discarded. [Vol3, Part A, 4.1]
if p.dlen() > c.sigRxMTU {
c.sendResponse(
_, err := c.sendResponse(
SignalCommandReject,
sigCmd(p.payload()).id(),
&CommandReject{
Reason: 0x0001, // Signaling MTU exceeded.
Data: []byte{uint8(c.sigRxMTU), uint8(c.sigRxMTU >> 8)}, // Actual MTUsig.
})
if err != nil {
_ = logger.Error("send repsonse", fmt.Sprintf("%v", err))
}
return nil
}

Expand Down
64 changes: 40 additions & 24 deletions linux/hci/signal_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ type CommandReject struct {
func (s CommandReject) Code() int { return 0x01 }

// Marshal serializes the command parameters into binary form.
func (s *CommandReject) Marshal() []byte {
func (s *CommandReject) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand All @@ -42,10 +44,12 @@ type DisconnectRequest struct {
func (s DisconnectRequest) Code() int { return 0x06 }

// Marshal serializes the command parameters into binary form.
func (s *DisconnectRequest) Marshal() []byte {
func (s *DisconnectRequest) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand All @@ -66,10 +70,12 @@ type DisconnectResponse struct {
func (s DisconnectResponse) Code() int { return 0x07 }

// Marshal serializes the command parameters into binary form.
func (s *DisconnectResponse) Marshal() []byte {
func (s *DisconnectResponse) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand All @@ -92,10 +98,12 @@ type ConnectionParameterUpdateRequest struct {
func (s ConnectionParameterUpdateRequest) Code() int { return 0x12 }

// Marshal serializes the command parameters into binary form.
func (s *ConnectionParameterUpdateRequest) Marshal() []byte {
func (s *ConnectionParameterUpdateRequest) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand All @@ -115,10 +123,12 @@ type ConnectionParameterUpdateResponse struct {
func (s ConnectionParameterUpdateResponse) Code() int { return 0x13 }

// Marshal serializes the command parameters into binary form.
func (s *ConnectionParameterUpdateResponse) Marshal() []byte {
func (s *ConnectionParameterUpdateResponse) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand All @@ -142,10 +152,12 @@ type LECreditBasedConnectionRequest struct {
func (s LECreditBasedConnectionRequest) Code() int { return 0x14 }

// Marshal serializes the command parameters into binary form.
func (s *LECreditBasedConnectionRequest) Marshal() []byte {
func (s *LECreditBasedConnectionRequest) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand All @@ -169,10 +181,12 @@ type LECreditBasedConnectionResponse struct {
func (s LECreditBasedConnectionResponse) Code() int { return 0x15 }

// Marshal serializes the command parameters into binary form.
func (s *LECreditBasedConnectionResponse) Marshal() []byte {
func (s *LECreditBasedConnectionResponse) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand All @@ -193,10 +207,12 @@ type LEFlowControlCredit struct {
func (s LEFlowControlCredit) Code() int { return 0x16 }

// Marshal serializes the command parameters into binary form.
func (s *LEFlowControlCredit) Marshal() []byte {
func (s *LEFlowControlCredit) Marshal() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, s)
return buf.Bytes()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

// Unmarshal de-serializes the binary data and stores the result in the receiver.
Expand Down
12 changes: 9 additions & 3 deletions linux/hci/smp.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ const (

func (c *Conn) sendSMP(p pdu) error {
buf := bytes.NewBuffer(make([]byte, 0))
binary.Write(buf, binary.LittleEndian, uint16(4+len(p)))
binary.Write(buf, binary.LittleEndian, cidSMP)
binary.Write(buf, binary.LittleEndian, p)
if err := binary.Write(buf, binary.LittleEndian, uint16(4+len(p))); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, cidSMP); err != nil {
return err
}
if err := binary.Write(buf, binary.LittleEndian, p); err != nil {
return err
}
_, err := c.writePDU(buf.Bytes())
logger.Debug("smp", "send", fmt.Sprintf("[%X]", buf.Bytes()))
return err
Expand Down
10 changes: 4 additions & 6 deletions uuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,13 @@ func Contains(s []UUID, u UUID) bool {

// Reverse returns a reversed copy of u.
func Reverse(u []byte) []byte {
// Special-case 16 bit UUIDS for speed.
l := len(u)
if l == 2 {
return []byte{u[1], u[0]}
}
b := make([]byte, l)
for i := 0; i < l/2+1; i++ {
b[i], b[l-i-1] = u[l-i-1], u[i]

for i := 0; i < l; i++ {
b[l-i-1] = u[i]
}

return b
}

Expand Down
Loading