code: func (c *Client) PrepareWrite(handle uint16, offset uint16, value []byte) (uint16, uint16, []byte, error) {
  	if len(value) > c.l2c.TxMTU()-5 {
  		return 0, 0, nil, ErrInvalidArgument
  	}
  
  	// Acquire and reuse the txBuf, and release it after usage.
  	txBuf := <-c.chTxBuf
  	defer func() { c.chTxBuf <- txBuf }()
  
  	req := PrepareWriteRequest(txBuf[:5+len(value)])
  	req.SetAttributeOpcode()
  	req.SetAttributeHandle(handle)
  	req.SetValueOffset(offset)
  
  	b, err := c.sendReq(req)
  	if err != nil {
  		return 0, 0, nil, err
  	}
  
  	// Convert and validate the response.
  	rsp := PrepareWriteResponse(b)
  	switch {
  	case rsp[0] == ErrorResponseCode && len(rsp) == 5:
  		return 0, 0, nil, ble.ATTError(rsp[4])
  	case rsp[0] == ErrorResponseCode && len(rsp) != 5:
  		fallthrough
  	case rsp[0] != rsp.AttributeOpcode():
  		fallthrough
  	case len(rsp) < 5:
  		return 0, 0, nil, ErrInvalidResponse
  	}
  	return rsp.AttributeHandle(), rsp.ValueOffset(), rsp.PartAttributeValue(), nil
  }
docs: // PrepareWrite requests the server to prepare to write the value of an attribute.
  // The server will respond to this request with a Prepare Write Response, so that
  // the Client can verify that the value was received correctly.
  // [Vol 3, Part F, 3.4.6.1 & 3.4.6.2]