00001 /* 00002 * Copyright (c) 2005, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 * 00031 * @(#)$Id: serial-line.c,v 1.4 2010/02/23 18:26:26 adamdunkels Exp $ 00032 */ 00033 #include "dev/serial-line.h" 00034 #include <string.h> /* for memcpy() */ 00035 00036 #include "lib/ringbuf.h" 00037 00038 #ifdef SERIAL_LINE_CONF_BUFSIZE 00039 #define BUFSIZE SERIAL_LINE_CONF_BUFSIZE 00040 #else /* SERIAL_LINE_CONF_BUFSIZE */ 00041 #define BUFSIZE 128 00042 #endif /* SERIAL_LINE_CONF_BUFSIZE */ 00043 00044 #if (BUFSIZE & (BUFSIZE - 1)) != 0 00045 #error SERIAL_LINE_CONF_BUFSIZE must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...). 00046 #error Change SERIAL_LINE_CONF_BUFSIZE in contiki-conf.h. 00047 #endif 00048 00049 #define IGNORE_CHAR(c) (c == 0x0d) 00050 #define END 0x0a 00051 00052 static struct ringbuf rxbuf; 00053 static uint8_t rxbuf_data[BUFSIZE]; 00054 00055 PROCESS(serial_line_process, "Serial driver"); 00056 00057 process_event_t serial_line_event_message; 00058 00059 /*---------------------------------------------------------------------------*/ 00060 int 00061 serial_line_input_byte(unsigned char c) 00062 { 00063 static uint8_t overflow = 0; /* Buffer overflow: ignore until END */ 00064 00065 if(IGNORE_CHAR(c)) { 00066 return 0; 00067 } 00068 00069 if(!overflow) { 00070 /* Add character */ 00071 if(ringbuf_put(&rxbuf, c) == 0) { 00072 /* Buffer overflow: ignore the rest of the line */ 00073 overflow = 1; 00074 } 00075 } else { 00076 /* Buffer overflowed: 00077 * Only (try to) add terminator characters, otherwise skip */ 00078 if(c == END && ringbuf_put(&rxbuf, c) != 0) { 00079 overflow = 0; 00080 } 00081 } 00082 00083 /* Wake up consumer process */ 00084 process_poll(&serial_line_process); 00085 return 1; 00086 } 00087 /*---------------------------------------------------------------------------*/ 00088 PROCESS_THREAD(serial_line_process, ev, data) 00089 { 00090 static char buf[BUFSIZE]; 00091 static int ptr; 00092 00093 PROCESS_BEGIN(); 00094 00095 serial_line_event_message = process_alloc_event(); 00096 ptr = 0; 00097 00098 while(1) { 00099 /* Fill application buffer until newline or empty */ 00100 int c = ringbuf_get(&rxbuf); 00101 00102 if(c == -1) { 00103 /* Buffer empty, wait for poll */ 00104 PROCESS_YIELD(); 00105 } else { 00106 if(c != END) { 00107 if(ptr < BUFSIZE-1) { 00108 buf[ptr++] = (uint8_t)c; 00109 } else { 00110 /* Ignore character (wait for EOL) */ 00111 } 00112 } else { 00113 /* Terminate */ 00114 buf[ptr++] = (uint8_t)'\0'; 00115 00116 /* Broadcast event */ 00117 process_post(PROCESS_BROADCAST, serial_line_event_message, buf); 00118 00119 /* Wait until all processes have handled the serial line event */ 00120 if(PROCESS_ERR_OK == 00121 process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL)) { 00122 PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_CONTINUE); 00123 } 00124 ptr = 0; 00125 } 00126 } 00127 } 00128 00129 PROCESS_END(); 00130 } 00131 /*---------------------------------------------------------------------------*/ 00132 void 00133 serial_line_init(void) 00134 { 00135 ringbuf_init(&rxbuf, rxbuf_data, sizeof(rxbuf_data)); 00136 process_start(&serial_line_process, NULL); 00137 } 00138 /*---------------------------------------------------------------------------*/