diff --git a/client.go b/client.go index 8b2214c8..d1959868 100644 --- a/client.go +++ b/client.go @@ -40,6 +40,9 @@ type Client interface { // WriteCharacteristic writes a characteristic value to a server. [Vol 3, Part G, 4.9.3] WriteCharacteristic(c *Characteristic, value []byte, noRsp bool) error + // WriteLongCharacteristic writes a characteristic value that is longer than the MTU to a server. [Vol 3, Part F, 3.4.6] + WriteLongCharacteristic(c *Characteristic, value []byte) error + // ReadDescriptor reads a characteristic descriptor from a server. [Vol 3, Part G, 4.12.1] ReadDescriptor(d *Descriptor) ([]byte, error) diff --git a/darwin/client.go b/darwin/client.go index ef2f979b..591f5463 100644 --- a/darwin/client.go +++ b/darwin/client.go @@ -256,6 +256,11 @@ func (cln *Client) WriteCharacteristic(c *ble.Characteristic, b []byte, noRsp bo return nil } +// WriteLongCharacteristic writes a characteristic value that is longer than the MTU to a server. [Vol 3, Part F, 3.4.6] +func (cln *Client) WriteLongCharacteristic(c *ble.Characteristic, b []byte) error { + panic("not implemented") +} + // ReadDescriptor reads a characteristic descriptor from a server. [Vol 3, Part G, 4.12.1] func (cln *Client) ReadDescriptor(d *ble.Descriptor) ([]byte, error) { cbdsc, err := cln.pc.findCbDsc(d) diff --git a/linux/att/client.go b/linux/att/client.go index ad624020..01c50c58 100644 --- a/linux/att/client.go +++ b/linux/att/client.go @@ -422,6 +422,7 @@ func (c *Client) PrepareWrite(handle uint16, offset uint16, value []byte) (uint1 req.SetAttributeOpcode() req.SetAttributeHandle(handle) req.SetValueOffset(offset) + req.SetPartAttributeValue(value) b, err := c.sendReq(req) if err != nil { @@ -452,7 +453,7 @@ func (c *Client) ExecuteWrite(flags uint8) error { txBuf := <-c.chTxBuf defer func() { c.chTxBuf <- txBuf }() - req := ExecuteWriteRequest(txBuf[:1]) + req := ExecuteWriteRequest(txBuf[:2]) req.SetAttributeOpcode() req.SetFlags(flags) diff --git a/linux/gatt/client.go b/linux/gatt/client.go index ef29ff56..7382cda7 100644 --- a/linux/gatt/client.go +++ b/linux/gatt/client.go @@ -252,6 +252,26 @@ func (p *Client) WriteCharacteristic(c *ble.Characteristic, v []byte, noRsp bool return p.ac.Write(c.ValueHandle, v) } +// WriteLongCharacteristic writes a characteristic value that is longer than the MTU to a server. [Vol 3, Part F, 3.4.6] +func (p *Client) WriteLongCharacteristic(c *ble.Characteristic, v []byte) error { + p.Lock() + defer p.Unlock() + + offset := 0 + prepareWriteLength := 0 + + for offset < len(v) { + prepareWriteLength = MinInt( len(v) - offset, p.conn.TxMTU()-5 ) + value := v[offset:offset+prepareWriteLength] + if _, _, _, err := p.ac.PrepareWrite(c.ValueHandle, uint16(offset), value ); err != nil { + return err + } + offset += prepareWriteLength + } + + return p.ac.ExecuteWrite(0x01) // flags: 0x00=cancel all, 0x01=write all +} + // ReadDescriptor reads a characteristic descriptor from a server. [Vol 3, Part G, 4.12.1] func (p *Client) ReadDescriptor(d *ble.Descriptor) ([]byte, error) { p.Lock() @@ -401,3 +421,10 @@ type sub struct { nHandler ble.NotificationHandler iHandler ble.NotificationHandler } + +func MinInt( a int, b int) int { + if a < b { + return a + } + return b +} \ No newline at end of file