code: func (c *Client) ReadMultiple(handles []uint16) ([]byte, error) {
  	// Should request to read two or more values.
  	if len(handles) < 2 || len(handles)*2 > c.l2c.TxMTU()-1 {
  		return nil, ErrInvalidArgument
  	}
  
  	// Acquire and reuse the txBuf, and release it after usage.
  	txBuf := <-c.chTxBuf
  	defer func() { c.chTxBuf <- txBuf }()
  
  	req := ReadMultipleRequest(txBuf[:1+len(handles)*2])
  	req.SetAttributeOpcode()
  	p := req.SetOfHandles()
  	for _, h := range handles {
  		binary.LittleEndian.PutUint16(p, h)
  		p = p[2:]
  	}
  
  	b, err := c.sendReq(req)
  	if err != nil {
  		return nil, err
  	}
  
  	// Convert and validate the response.
  	rsp := ReadMultipleResponse(b)
  	switch {
  	case rsp[0] == ErrorResponseCode && len(rsp) == 5:
  		return nil, ble.ATTError(rsp[4])
  	case rsp[0] == ErrorResponseCode && len(rsp) != 5:
  		fallthrough
  	case rsp[0] != rsp.AttributeOpcode():
  		fallthrough
  	case len(rsp) < 1:
  		return nil, ErrInvalidResponse
  	}
  	return rsp.SetOfValues(), nil
  }
docs: // ReadMultiple requests the server to read two or more values of a set of
  // attributes and return their values in a Read Multiple Response.
  // Only values that have a known fixed size can be read, with the exception of
  // the last value that can have a variable length. The knowledge of whether
  // attributes have a known fixed size is defined in a higher layer specification.
  // [Vol 3, Part F, 3.4.4.7 & 3.4.4.8]