docs: def transfer(self, address, messages):
          """Transfer `messages` to the specified I2C `address`. Modifies the
          `messages` array with the results of any read transactions.
  
          Args:
              address (int): I2C address.
              messages (list): list of I2C.Message messages.
  
          Raises:
              I2CError: if an I/O or OS error occurs.
              TypeError: if `messages` type is not list.
              ValueError: if `messages` length is zero, or if message data is not valid bytes.
  
          """
          if not isinstance(messages, list):
              raise TypeError("Invalid messages type, should be list of I2C.Message.")
          elif len(messages) == 0:
              raise ValueError("Invalid messages data, should be non-zero length.")
  
          # Convert I2C.Message messages to _CI2CMessage messages
          cmessages = (_CI2CMessage * len(messages))()
          for i in range(len(messages)):
              # Convert I2C.Message data to bytes
              if isinstance(messages[i].data, bytes):
                  data = messages[i].data
              elif isinstance(messages[i].data, bytearray):
                  data = bytes(messages[i].data)
              elif isinstance(messages[i].data, list):
                  data = bytes(bytearray(messages[i].data))
  
              cmessages[i].addr = address
              cmessages[i].flags = messages[i].flags | (I2C._I2C_M_RD if messages[i].read else 0)
              cmessages[i].len = len(data)
              cmessages[i].buf = ctypes.cast(ctypes.create_string_buffer(data, len(data)), ctypes.POINTER(ctypes.c_ubyte))
  
          # Prepare transfer structure
          i2c_xfer = _CI2CIocTransfer()
          i2c_xfer.nmsgs = len(cmessages)
          i2c_xfer.msgs = cmessages
  
          # Transfer
          try:
              fcntl.ioctl(self._fd, I2C._I2C_IOC_RDWR, i2c_xfer, False)
          except IOError as e:
              raise I2CError(e.errno, "I2C transfer: " + e.strerror)
  
          # Update any read I2C.Message messages
          for i in range(len(messages)):
              if messages[i].read:
                  data = [cmessages[i].buf[j] for j in range(cmessages[i].len)]
                  # Convert read data to type used in I2C.Message messages
                  if isinstance(messages[i].data, list):
                      messages[i].data = data
                  elif isinstance(messages[i].data, bytearray):
                      messages[i].data = bytearray(data)
                  elif isinstance(messages[i].data, bytes):
                      messages[i].data = bytes(bytearray(data))