Skip to content

Commit 22ba2f5

Browse files
committed
u2fhid: Write as many bytes as possible
To be more efficient multiple u2fhid packets are written simultaneously if possible
1 parent 2b90fad commit 22ba2f5

File tree

1 file changed

+35
-23
lines changed

1 file changed

+35
-23
lines changed

communication/u2fhid/u2fhid.go

+35-23
Original file line numberDiff line numberDiff line change
@@ -95,44 +95,56 @@ func (communication *Communication) sendFrame(msg string) error {
9595
if dataLen == 0 {
9696
return nil
9797
}
98-
send := func(header []byte, readFrom *bytes.Buffer) error {
99-
buf := newBuffer()
100-
buf.Write(header)
101-
buf.Write(readFrom.Next(writeReportSize - buf.Len()))
102-
for buf.Len() < writeReportSize {
103-
buf.WriteByte(0xee)
104-
}
105-
x := buf.Bytes() // needs to be in a var: https://github.com/golang/go/issues/14210#issuecomment-346402945
106-
_, err := communication.device.Write(x)
107-
return errp.WithMessage(errp.WithStack(err), "Failed to send message")
98+
99+
outLen := 64
100+
// 57 payload bytes fit in first frame, 59 in rest
101+
if dataLen > 57 {
102+
contLen := dataLen - 57
103+
outLen += ((contLen + 59 - 1) / 59) * 64
108104
}
105+
109106
readBuffer := bytes.NewBufferString(msg)
107+
out := newBuffer()
108+
out.Grow(outLen)
109+
110110
// init frame
111-
header := newBuffer()
112-
if err := binary.Write(header, binary.BigEndian, cid); err != nil {
111+
if err := binary.Write(out, binary.BigEndian, cid); err != nil {
113112
return errp.WithStack(err)
114113
}
115-
if err := binary.Write(header, binary.BigEndian, communication.cmd); err != nil {
114+
if err := binary.Write(out, binary.BigEndian, communication.cmd); err != nil {
116115
return errp.WithStack(err)
117116
}
118-
if err := binary.Write(header, binary.BigEndian, uint16(dataLen&0xFFFF)); err != nil {
117+
if err := binary.Write(out, binary.BigEndian, uint16(dataLen&0xFFFF)); err != nil {
119118
return errp.WithStack(err)
120119
}
121-
if err := send(header.Bytes(), readBuffer); err != nil {
122-
return err
123-
}
120+
// init frame has a 7 byte header
121+
out.Write(readBuffer.Next(writeReportSize - 7))
122+
123+
// cont frames
124124
for seq := 0; readBuffer.Len() > 0; seq++ {
125-
// cont frame
126-
header = newBuffer()
127-
if err := binary.Write(header, binary.BigEndian, cid); err != nil {
125+
if err := binary.Write(out, binary.BigEndian, cid); err != nil {
128126
return errp.WithStack(err)
129127
}
130-
if err := binary.Write(header, binary.BigEndian, uint8(seq)); err != nil {
128+
if err := binary.Write(out, binary.BigEndian, uint8(seq)); err != nil {
131129
return errp.WithStack(err)
132130
}
133-
if err := send(header.Bytes(), readBuffer); err != nil {
134-
return err
131+
// cont frame has a 5 byte header
132+
out.Write(readBuffer.Next(writeReportSize - 5))
133+
}
134+
135+
// Make out buffer multiple of 64 bytes
136+
for i := out.Len() % 64; i < writeReportSize; i++ {
137+
out.WriteByte(0xEE)
138+
}
139+
140+
// Write out packets, write as many bytes as possible in each iteration
141+
for out.Len() > 0 {
142+
x := out.Bytes() // needs to be in a var: https://github.com/golang/go/issues/14210#issuecomment-346402945
143+
n, err := communication.device.Write(x)
144+
if err != nil {
145+
return errp.WithMessage(errp.WithStack(err), "Failed to send message")
135146
}
147+
out.Next(n)
136148
}
137149
return nil
138150
}

0 commit comments

Comments
 (0)