diff --git a/gattc_darwin.go b/gattc_darwin.go index 664e92ed..7271220e 100644 --- a/gattc_darwin.go +++ b/gattc_darwin.go @@ -9,8 +9,8 @@ import ( ) var ( - errCannotSendWriteWithoutResponse = errors.New("bluetooth: cannot send write without response (buffer full)") - errTimeoutEnableNotifications = errors.New("timeout on EnableNotifications") + errWriteWithoutResponseTimeout = errors.New("bluetooth: write without response timed out waiting for buffer space") + errTimeoutEnableNotifications = errors.New("timeout on EnableNotifications") ) var ( @@ -243,13 +243,21 @@ func (c DeviceCharacteristic) Write(p []byte) (n int, err error) { // WriteWithoutResponse replaces the characteristic value with a new value. The // call will return before all data has been written. A limited number of such // writes can be in flight at any given time. -// If the client is not ready to send write without response requests at this time (e.g. because the internal buffer is full), an error is returned. +// If the peripheral's buffer is full, this method polls +// CanSendWriteWithoutResponse every 15ms (one BLE connection interval) until +// ready, with a 10-second timeout. func (c DeviceCharacteristic) WriteWithoutResponse(p []byte) (int, error) { - if !c.service.device.prph.CanSendWriteWithoutResponse() { - return 0, errCannotSendWriteWithoutResponse + dev := c.service.device + + deadline := time.Now().Add(10 * time.Second) + for !dev.prph.CanSendWriteWithoutResponse() { + if time.Now().After(deadline) { + return 0, errWriteWithoutResponseTimeout + } + time.Sleep(15 * time.Millisecond) } - c.service.device.prph.WriteCharacteristic(p, c.characteristic, false) + dev.prph.WriteCharacteristic(p, c.characteristic, false) return len(p), nil }