BeRTOS
usbser.c
Go to the documentation of this file.
00001 
00039 #include "usbser.h"
00040 
00041 #include "cfg/cfg_usbser.h"
00042 
00043 #define LOG_LEVEL  USB_SERIAL_LOG_LEVEL
00044 #define LOG_FORMAT USB_SERIAL_LOG_FORMAT
00045 
00046 #include <cfg/log.h>
00047 #include <cfg/debug.h>
00048 #include <cfg/macros.h>
00049 
00050 #include <cfg/compiler.h>
00051 #include <cfg/module.h>
00052 
00053 #include <cpu/irq.h> /* IRQ_DISABLE / IRQ_ENABLE */
00054 #include <cpu/power.h> /* cpu_relax() */
00055 
00056 #include <drv/usb.h>
00057 #include <drv/usb_endpoint.h>
00058 
00059 #include <string.h> /* memcpy() */
00060 
00061 
00062 #define USB_SERIAL_INTERFACES   1
00063 #define USB_SERIAL_ENDPOINTS    3
00064 
00065 #define USB_STRING_MANUFACTURER 1
00066 #define USB_STRING_PRODUCT  2
00067 #define USB_STRING_SERIAL   3
00068 
00069 static UsbDeviceDesc usb_serial_device_descriptor =
00070 {
00071     .bLength = sizeof(usb_serial_device_descriptor),
00072     .bDescriptorType = USB_DT_DEVICE,
00073     .bcdUSB = 0x110,
00074     .bDeviceClass = USB_CLASS_COMM,
00075     .bDeviceSubClass = 0,
00076     .bDeviceProtocol = 0,
00077     .idVendor = USB_SERIAL_VENDOR_ID,
00078     .idProduct = USB_SERIAL_PRODUCT_ID,
00079     .bcdDevice = 0,
00080     .iManufacturer = USB_STRING_MANUFACTURER,
00081     .iProduct = USB_STRING_PRODUCT,
00082     .iSerialNumber = USB_STRING_SERIAL,
00083     .bNumConfigurations = 1,
00084 };
00085 
00086 static const UsbConfigDesc usb_serial_config_descriptor =
00087 {
00088     .bLength = sizeof(usb_serial_config_descriptor),
00089     .bDescriptorType = USB_DT_CONFIG,
00090     .bNumInterfaces = USB_SERIAL_INTERFACES,
00091     .bConfigurationValue = 1,
00092     .iConfiguration = 0,
00093     .bmAttributes = USB_CONFIG_ATT_ONE,
00094     .bMaxPower = 50, /* 100 mA */
00095 };
00096 
00097 static const UsbInterfaceDesc usb_serial_interface_descriptor =
00098 {
00099     .bLength = sizeof(usb_serial_interface_descriptor),
00100     .bDescriptorType = USB_DT_INTERFACE,
00101     .bInterfaceNumber = 0,
00102     .bAlternateSetting = 0,
00103     .bNumEndpoints = USB_SERIAL_ENDPOINTS,
00104     .bInterfaceClass = 0xff,
00105     .bInterfaceSubClass = 0,
00106     .bInterfaceProtocol = 0,
00107     .iInterface = 0,
00108 };
00109 
00110 static const UsbEndpointDesc usb_serial_ep_report_descriptor =
00111 {
00112     .bLength = sizeof(usb_serial_ep_report_descriptor),
00113     .bDescriptorType = USB_DT_ENDPOINT,
00114     .bEndpointAddress = USB_DIR_IN | USB_SERIAL_EP_REPORT,
00115     .bmAttributes = USB_ENDPOINT_XFER_INT,
00116     .wMaxPacketSize = usb_cpu_to_le16((uint16_t)8),
00117     .bInterval = 1,
00118 };
00119 
00120 static const UsbEndpointDesc usb_serial_ep_in_descriptor =
00121 {
00122     .bLength = sizeof(usb_serial_ep_in_descriptor),
00123     .bDescriptorType = USB_DT_ENDPOINT,
00124     .bEndpointAddress = USB_DIR_IN | USB_SERIAL_EP_IN,
00125     .bmAttributes = USB_ENDPOINT_XFER_BULK,
00126     .wMaxPacketSize = usb_cpu_to_le16((uint16_t)64),
00127     .bInterval = 0,
00128 };
00129 
00130 static const UsbEndpointDesc usb_serial_ep_out_descriptor =
00131 {
00132     .bLength = sizeof(usb_serial_ep_in_descriptor),
00133     .bDescriptorType = USB_DT_ENDPOINT,
00134     .bEndpointAddress = USB_DIR_OUT | USB_SERIAL_EP_OUT,
00135     .bmAttributes = USB_ENDPOINT_XFER_BULK,
00136     .wMaxPacketSize = usb_cpu_to_le16((uint16_t)64),
00137     .bInterval = 0,
00138 };
00139 
00140 static const UsbDescHeader *usb_serial_config[] =
00141 {
00142     (const UsbDescHeader *)&usb_serial_config_descriptor,
00143     (const UsbDescHeader *)&usb_serial_interface_descriptor,
00144     (const UsbDescHeader *)&usb_serial_ep_report_descriptor,
00145     (const UsbDescHeader *)&usb_serial_ep_in_descriptor,
00146     (const UsbDescHeader *)&usb_serial_ep_out_descriptor,
00147     NULL,
00148 };
00149 
00150 static const DEFINE_USB_STRING(language_str, "\x09\x04"); // Language ID: en_US
00151 static const DEFINE_USB_STRING(manufacturer_str,
00152         USB_STRING("B", "e", "R", "T", "O", "S"));
00153 static const DEFINE_USB_STRING(product_str,
00154         USB_STRING("U", "S", "B", "-", "s", "e", "r", "i", "a", "l"));
00155 static const DEFINE_USB_STRING(serial_str,
00156         USB_STRING("0", "0", "1"));
00157 
00158 static const UsbStringDesc *usb_serial_strings[] =
00159 {
00160     (const UsbStringDesc *)&language_str,
00161     (const UsbStringDesc *)&manufacturer_str,
00162     (const UsbStringDesc *)&product_str,
00163     (const UsbStringDesc *)&serial_str,
00164     NULL,
00165 };
00166 
00167 /* Global usb-serial descriptor that identifies the usb-serial device */
00168 static UsbDevice usb_serial = {
00169     .device = &usb_serial_device_descriptor,
00170     .config = usb_serial_config,
00171     .strings = usb_serial_strings,
00172 };
00173 
00174 /* Low-level usb-serial device initialization */
00175 static int usb_serial_hw_init(void)
00176 {
00177 #if CONFIG_KERN
00178     MOD_CHECK(proc);
00179 #endif
00180     if (usb_deviceRegister(&usb_serial) < 0)
00181         return -1;
00182     LOG_INFO("usb-serial: registered new USB interface driver\n");
00183     return 0;
00184 }
00185 
00191 static size_t usb_serial_write(struct KFile *fd,
00192             const void *buf, size_t size)
00193 {
00194     DB(USBSerial *fds = USB_SERIAL_CAST(fd));
00195 
00196     /* Silent compiler warnings if _DEBUG is not enabled */
00197     (void)fd;
00198     ASSERT(fds->is_open);
00199     return usb_endpointWrite(usb_serial_ep_in_descriptor.bEndpointAddress,
00200                 buf, size);
00201 }
00202 
00208 static size_t usb_serial_read(struct KFile *fd, void *buf, size_t size)
00209 {
00210     DB(USBSerial *fds = USB_SERIAL_CAST(fd));
00211 
00212     /* Silent compiler warnings if _DEBUG is not enabled */
00213     (void)fd;
00214     ASSERT(fds->is_open);
00215     return usb_endpointRead(usb_serial_ep_out_descriptor.bEndpointAddress,
00216                 buf, size);
00217 }
00218 
00224 static int usb_serial_error(struct KFile *fd)
00225 {
00226     USBSerial *fds = USB_SERIAL_CAST(fd);
00227     return fds->status;
00228 }
00229 
00235 static void usb_serial_clearerr(struct KFile *fd)
00236 {
00237     USBSerial *fds = USB_SERIAL_CAST(fd);
00238     fds->status = 0;
00239 }
00240 
00244 static int usb_serial_close(struct KFile *fd)
00245 {
00246     DB(USBSerial *fds = USB_SERIAL_CAST(fd));
00247 
00248     /* Silent compiler warnings if _DEBUG is not enabled */
00249     (void)fd;
00250     ASSERT(fds->is_open);
00251     DB(fds->is_open = false);
00252     return 0;
00253 }
00254 
00261 static int usb_serial_open(struct USBSerial *fds, int unit)
00262 {
00263     unit = unit;
00264     ASSERT(!fds->is_open);
00265     /* TODO: only a single usb-serial unit is supported for now */
00266     ASSERT(unit == 0);
00267 
00268     /* Initialize usb-serial driver */
00269     if (usb_serial_hw_init() < 0)
00270         return -1;
00271     /* Clear error flags */
00272     fds->status = 0;
00273     DB(fds->is_open = true);
00274 
00275     return 0;
00276 }
00277 
00281 static struct KFile *usb_serial_reopen(struct KFile *fd)
00282 {
00283     USBSerial *fds = USB_SERIAL_CAST(fd);
00284 
00285     usb_serial_close(fd);
00286     usb_serial_open(fds, fds->unit);
00287     return 0;
00288 }
00289 
00295 int usbser_init(struct USBSerial *fds, int unit)
00296 {
00297     memset(fds, 0, sizeof(*fds));
00298 
00299     DB(fds->fd._type = KFT_USB_SERIAL);
00300     fds->fd.reopen = usb_serial_reopen;
00301     fds->fd.close = usb_serial_close;
00302     fds->fd.read = usb_serial_read;
00303     fds->fd.write = usb_serial_write;
00304     /* TODO: properly implement error handling. */
00305     fds->fd.error = usb_serial_error;
00306     fds->fd.clearerr = usb_serial_clearerr;
00307 
00308     return usb_serial_open(fds, unit);
00309 }