Commit 5c64eb90 authored by Jeff Lassahn's avatar Jeff Lassahn
Browse files

Avoid receiving invalid command response on device stop.

parent ad9bd85c
......@@ -295,7 +295,11 @@ func (h *HCI) sktLoop() {
for {
n, err := h.skt.Read(b)
if n == 0 || err != nil {
h.err = fmt.Errorf("skt: %s", err)
if err == io.EOF {
h.err = err //callers depend on detecting io.EOF, don't wrap it.
} else {
h.err = fmt.Errorf("skt: %s", err)
p := make([]byte, n)
......@@ -119,14 +119,21 @@ func open(fd, id int) (*Socket, error) {
func (s *Socket) Read(p []byte) (int, error) {
n, err := unix.Read(s.fd, p)
// Close always sends a dummy command to wake up Read
// bad things happen to the HCI state machines if they receive
// a reply from that command, so make sure no data is returned
// on a closed socket.
// note that if Write and Close are called concurrently it's
// indeterminate which replies get through.
select {
case <-s.closed:
return 0, io.EOF
defer s.rmu.Unlock()
n, err := unix.Read(s.fd, p)
return n, errors.Wrap(err, "can't read hci socket")
......@@ -139,7 +146,7 @@ func (s *Socket) Write(p []byte) (int, error) {
func (s *Socket) Close() error {
s.Write([]byte{0x01, 0x09, 0x10, 0x00})
s.Write([]byte{0x01, 0x09, 0x10, 0x00}) // no-op command to wake up the Read call if it's blocked
defer s.rmu.Unlock()
return errors.Wrap(unix.Close(s.fd), "can't close hci socket")
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