From: arighi Date: Mon, 20 Sep 2010 15:27:37 +0000 (+0000) Subject: usb-serial: export usb-serial interface via KFile X-Git-Tag: 2.6.0~158 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=5aee4c8b76fe3aefc7f530de322a6b0f5faffcc1;p=bertos.git usb-serial: export usb-serial interface via KFile TODO: - properly implement error handling - support more distinct usb-serial channels git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4243 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/bertos/drv/usb_serial.c b/bertos/drv/usb_serial.c index e3054bbd..cdc4b63f 100644 --- a/bertos/drv/usb_serial.c +++ b/bertos/drv/usb_serial.c @@ -150,11 +150,11 @@ static usb_descriptor_header_t *usb_serial_config[] = 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[] = { @@ -165,31 +165,146 @@ 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); +} diff --git a/bertos/drv/usb_serial.h b/bertos/drv/usb_serial.h index d27f7a98..0406cebf 100644 --- a/bertos/drv/usb_serial.h +++ b/bertos/drv/usb_serial.h @@ -42,9 +42,35 @@ #ifndef USB_SERIAL_H #define USB_SERIAL_H -ssize_t usb_serial_read(void *buf, ssize_t size); -ssize_t usb_serial_write(const void *buf, ssize_t size); +#include -int usb_serial_init(void); +typedef uint32_t usbser_status_t; + +typedef struct USBSerial +{ + /** KFile structure implementation **/ + KFile fd; + /** Logical port number */ + unsigned int unit; +#ifdef _DEBUG + /** Used for debugging only */ + bool is_open; +#endif + /** Holds the status flags. Set to 0 when no errors have occurred. */ + usbser_status_t status; +} USBSerial; + +/** + * ID for usb-serial. + */ +#define KFT_USB_SERIAL MAKE_ID('U', 'S', 'B', 'S') + +INLINE USBSerial *USB_SERIAL_CAST(KFile *fd) +{ + ASSERT(fd->_type == KFT_USB_SERIAL); + return (USBSerial *)fd; +} + +int usb_serial_init(struct USBSerial *fds, int unit); #endif /* USB_SERIAL_H */