static DEFINE_USB_STRING(language_str, "\x09\x04"); // Language ID: en_US
static DEFINE_USB_STRING(manufacturer_str,
- USB_STRING("B", "e", "R", "T", "O", "S"));
+ USB_STRING("B", "e", "R", "T", "O", "S"));
static DEFINE_USB_STRING(product_str,
- USB_STRING("U", "S", "B", "-", "s", "e", "r", "i", "a", "l"));
+ USB_STRING("U", "S", "B", "-", "s", "e", "r", "i", "a", "l"));
static DEFINE_USB_STRING(serial_str,
- USB_STRING("0", "0", "1"));
+ USB_STRING("0", "0", "1"));
static usb_string_descriptor_t *usb_serial_strings[] =
{
NULL,
};
+/* Global usb-serial descriptor that identifies the usb-serial device */
static struct usb_device usb_serial = {
.device = &usb_serial_device_descriptor,
.config = usb_serial_config,
.strings = usb_serial_strings,
};
-ssize_t usb_serial_read(void *buffer, ssize_t size)
+/* Low-level usb-serial device initialization */
+static int usb_serial_hw_init(void)
{
- return usb_ep_read(usb_serial_ep_out_descriptor.bEndpointAddress,
- buffer, size);
+#if CONFIG_KERN
+ MOD_CHECK(proc);
+#endif
+ if (usb_device_register(&usb_serial) < 0)
+ return -1;
+ LOG_INFO("usb-serial: registered new USB interface driver\n");
+ return 0;
}
-ssize_t usb_serial_write(const void *buffer, ssize_t size)
+/**
+ * \brief Write a buffer to a usb-serial port.
+ *
+ * \return number of bytes actually written.
+ */
+static size_t usb_serial_write(struct KFile *fd,
+ const void *buf, size_t size)
{
+ DB(USBSerial *fds = USB_SERIAL_CAST(fd));
+
+ /* Silent compiler warnings if _DEBUG is not enabled */
+ (void)fd;
+ ASSERT(fds->is_open);
return usb_ep_write(usb_serial_ep_in_descriptor.bEndpointAddress,
- buffer, size);
+ buf, size);
}
-int usb_serial_init(void)
+/**
+ * Read at most \a size bytes from a usb-serial port and put them in \a buf
+ *
+ * \return number of bytes actually read.
+ */
+static size_t usb_serial_read(struct KFile *fd, void *buf, size_t size)
{
-#if CONFIG_KERN
- MOD_CHECK(proc);
-#endif
- if (usb_device_register(&usb_serial) < 0)
+ DB(USBSerial *fds = USB_SERIAL_CAST(fd));
+
+ /* Silent compiler warnings if _DEBUG is not enabled */
+ (void)fd;
+ ASSERT(fds->is_open);
+ return usb_ep_read(usb_serial_ep_out_descriptor.bEndpointAddress,
+ buf, size);
+}
+
+/**
+ * Return the status of a usb-serial port.
+ *
+ * \todo properly implement usb-serial error handling.
+ */
+static int usb_serial_error(struct KFile *fd)
+{
+ USBSerial *fds = USB_SERIAL_CAST(fd);
+ return fds->status;
+}
+
+/**
+ * Clear the status of a usb-serial port.
+ *
+ * \todo properly implement usb-serial error handling.
+ */
+static void usb_serial_clearerr(struct KFile *fd)
+{
+ USBSerial *fds = USB_SERIAL_CAST(fd);
+ fds->status = 0;
+}
+
+/**
+ * Close an USB serial port.
+ */
+static int usb_serial_close(struct KFile *fd)
+{
+ DB(USBSerial *fds = USB_SERIAL_CAST(fd));
+
+ /* Silent compiler warnings if _DEBUG is not enabled */
+ (void)fd;
+ ASSERT(fds->is_open);
+ DB(fds->is_open = false);
+ return 0;
+}
+
+/**
+ * Initialize an USB serial port.
+ *
+ * \param fd KFile Serial struct interface.
+ * \param unit Serial unit to open.
+ */
+static int usb_serial_open(struct USBSerial *fds, int unit)
+{
+ unit = unit;
+ ASSERT(!fds->is_open);
+ /* TODO: only a single usb-serial unit is supported for now */
+ ASSERT(unit == 0);
+
+ /* Initialize usb-serial driver */
+ if (usb_serial_hw_init() < 0)
return -1;
- LOG_INFO("usb-serial: registered new USB interface driver\n");
+ /* Clear error flags */
+ fds->status = 0;
+ DB(fds->is_open = true);
+
+ return 0;
+}
+
+/**
+ * Reopen a usb-serial port.
+ */
+static struct KFile *usb_serial_reopen(struct KFile *fd)
+{
+ USBSerial *fds = USB_SERIAL_CAST(fd);
+
+ usb_serial_close(fd);
+ usb_serial_open(fds, fds->unit);
return 0;
}
+
+/**
+ * Init serial driver for a usb-serial port \a unit.
+ *
+ * \return 0 if OK, a negative value in case of error.
+ */
+int usb_serial_init(struct USBSerial *fds, int unit)
+{
+ memset(fds, 0, sizeof(*fds));
+
+ DB(fds->fd._type = KFT_USB_SERIAL);
+ fds->fd.reopen = usb_serial_reopen;
+ fds->fd.close = usb_serial_close;
+ fds->fd.read = usb_serial_read;
+ fds->fd.write = usb_serial_write;
+ /* TODO: properly implement error handling. */
+ fds->fd.error = usb_serial_error;
+ fds->fd.clearerr = usb_serial_clearerr;
+
+ return usb_serial_open(fds, unit);
+}