+
+/**
+ * Reopen serial port.
+ */
+static struct KFile *ser_reopen(struct KFile *fd)
+{
+ KFileSerial *fds = KFILESERIAL(fd);
+
+ ser_close(fd);
+ ser_open(fds, fds->ser->unit);
+ return (KFile *)fds;
+}
+
+/**
+ * Init serial driver for \a unit.
+ */
+void ser_init(struct KFileSerial *fds, unsigned int unit)
+{
+ memset(fds, 0, sizeof(*fds));
+
+ DB(fds->fd._type = KFT_SERIAL);
+ fds->fd.reopen = ser_reopen;
+ fds->fd.close = ser_close;
+ fds->fd.read = ser_read;
+ fds->fd.write = ser_write;
+ fds->fd.flush = ser_flush;
+ fds->fd.error = ser_error;
+ fds->fd.clearerr = ser_clearerr;
+ ser_open(fds, unit);
+}
+
+
+/**
+ * Read data from SPI bus.
+ * Since we are master, we have to trigger slave by sending
+ * fake chars on the bus.
+ */
+static size_t spimaster_read(struct KFile *fd, void *buf, size_t size)
+{
+ KFileSerial *fd_spi = KFILESERIAL(fd);
+
+ ser_flush(&fd_spi->fd);
+ ser_purgeRx(fd_spi);
+
+ for (size_t i = 0; i < size; i++)
+ ser_putchar(0, fd_spi->ser);
+
+ return ser_read(&fd_spi->fd, buf, size);
+}
+
+/**
+ * Write data to SPI bus.
+ */
+static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
+{
+ KFileSerial *fd_spi = KFILESERIAL(fd);
+
+ ser_purgeRx(fd_spi);
+
+ return ser_write(&fd_spi->fd, buf, size);
+}
+
+
+/**
+ * Init SPI serial driver \a unit in master mode.
+ *
+ * This interface implements the SPI master protocol over a serial SPI
+ * driver. This is needed because normal serial driver send/receive data
+ * at the same time. SPI slaves like memories and other peripherals
+ * first receive and *then* send response back instead.
+ * To achieve this, when we are master and we are *sending*,
+ * we have to discard all incoming data. Then, when we want to
+ * receive, we must write fake data to SPI to trigger slave devices.
+ */
+void spimaster_init(KFileSerial *fds, unsigned int unit)
+{
+ ser_init(fds, unit);
+ fds->fd.read = spimaster_read;
+ fds->fd.write = spimaster_write;
+}
+
+