+/**
+ * Copy \a size bytes from buffer \a _buf to
+ * eeprom.
+ * \note Writes are verified and if buffer content
+ * is not matching we retry 5 times max.
+ */
+static size_t eeprom_writeVerify(struct KFile *_fd, const void *_buf, size_t size)
+{
+ Eeprom *fd = EEPROM_CAST(_fd);
+ int retries = 5;
+ size_t wr_len;
+
+ while (retries--)
+ {
+ wr_len = eeprom_writeRaw(_fd, _buf, size);
+ /* rewind to verify what we have just written */
+ kfile_seek(_fd, -(kfile_off_t)wr_len, KSM_SEEK_CUR);
+ if (wr_len == size
+ && eeprom_verify(fd, _buf, wr_len))
+ {
+ /* Forward to go after what we have written*/
+ kfile_seek(_fd, wr_len, KSM_SEEK_CUR);
+ return wr_len;
+ }
+ }
+ return wr_len;
+}
+
+
+/**
+ * Copy \a size bytes
+ * from eeprom to RAM to buffer \a _buf.
+ *
+ * \return the number of bytes read.
+ */
+static size_t eeprom_read(struct KFile *_fd, void *_buf, size_t size)
+{
+ Eeprom *fd = EEPROM_CAST(_fd);
+ uint8_t addr_buf[2];
+ uint8_t addr_len;
+ size_t rd_len = 0;
+ uint8_t *buf = (uint8_t *)_buf;
+
+ STATIC_ASSERT(countof(addr_buf) <= sizeof(e2addr_t));
+
+ /* clamp size to memory limit (otherwise may roll back) */
+ ASSERT(_fd->seek_pos + size <= (kfile_off_t)_fd->size);
+ size = MIN((kfile_off_t)size, _fd->size - _fd->seek_pos);
+
+ e2dev_addr_t dev_addr;
+ if (mem_info[fd->type].has_dev_addr)
+ {
+ dev_addr = fd->addr;
+ addr_len = 2;
+ addr_buf[0] = (fd->fd.seek_pos >> 8) & 0xFF;
+ addr_buf[1] = (fd->fd.seek_pos & 0xFF);
+ }
+ else
+ {
+ dev_addr = (e2dev_addr_t)((fd->fd.seek_pos >> 8) & 0x07);
+ addr_len = 1;
+ addr_buf[0] = (fd->fd.seek_pos & 0xFF);
+ }
+
+
+ if (!(twi_start_w(EEPROM_ADDR(dev_addr))
+ && twi_send(addr_buf, addr_len)
+ && twi_start_r(EEPROM_ADDR(dev_addr))))
+ {