]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Updated Printf library to new way of not requiring explicit wiring of any interfaces...
authorklueska <klueska>
Thu, 12 Jun 2008 12:33:47 +0000 (12:33 +0000)
committerklueska <klueska>
Thu, 12 Jun 2008 12:33:47 +0000 (12:33 +0000)
tos/lib/printf/2_0_2/PrintfC.nc [new file with mode: 0644]
tos/lib/printf/2_0_2/PrintfFlush.nc [new file with mode: 0644]
tos/lib/printf/2_0_2/PrintfP.nc [new file with mode: 0644]
tos/lib/printf/2_0_2/avr_stdio.h [new file with mode: 0644]
tos/lib/printf/2_0_2/printf.h [new file with mode: 0644]
tos/lib/printf/MainC.nc [new file with mode: 0644]
tos/lib/printf/PrintfC.nc
tos/lib/printf/PrintfP.nc
tos/lib/printf/printf.h

diff --git a/tos/lib/printf/2_0_2/PrintfC.nc b/tos/lib/printf/2_0_2/PrintfC.nc
new file mode 100644 (file)
index 0000000..a9a8b73
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * "Copyright (c) 2006 Washington University in St. Louis.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL WASHINGTON UNIVERSITY IN ST. LOUIS BE LIABLE TO ANY PARTY
+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF WASHINGTON
+ * UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * WASHINGTON UNIVERSITY IN ST. LOUIS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS."
+ */
+
+/**
+ * This is the PrintfC component.  It provides the printf service for printing
+ * data over the serial interface using the standard c-style printf command.  
+ * It must be started via the SplitControl interface it provides.  Data
+ * printed using printf are buffered and only sent over the serial line after
+ * making a call to PrintfFlush.flush().  This buffer has a maximum size of 
+ * 250 bytes at present.  After calling start on this component, printf
+ * statements can be made anywhere throughout your code, so long as you include
+ * the "printf.h" header file in every file you wish to use it.  Standard
+ * practice is to start the printf service in the main application, and set up 
+ * a timer to periodically flush the printf buffer (500ms should do).  In future
+ * versions, user defined buffer sizes as well as well as automatic flushing at 
+ * user defined intervals will be supported.  
+ *
+ * @author Kevin Klues (klueska@cs.wustl.edu)
+ * @version $Revision$
+ * @date $Date$
+ */
+
+#include "printf.h"
+
+configuration PrintfC {
+  provides {
+       interface SplitControl as PrintfControl;
+       interface PrintfFlush;
+  }
+}
+implementation {
+  components SerialActiveMessageC;
+  components new SerialAMSenderC(AM_PRINTF_MSG);
+  components PrintfP;
+
+  PrintfControl = PrintfP;
+  PrintfFlush = PrintfP;
+  
+  PrintfP.SerialControl -> SerialActiveMessageC;
+  PrintfP.AMSend -> SerialAMSenderC;
+  PrintfP.Packet -> SerialAMSenderC;
+}
+
diff --git a/tos/lib/printf/2_0_2/PrintfFlush.nc b/tos/lib/printf/2_0_2/PrintfFlush.nc
new file mode 100644 (file)
index 0000000..64b247f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * "Copyright (c) 2006 Washington University in St. Louis.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL WASHINGTON UNIVERSITY IN ST. LOUIS BE LIABLE TO ANY PARTY
+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF WASHINGTON
+ * UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * WASHINGTON UNIVERSITY IN ST. LOUIS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS."
+ */
+
+/**
+ *
+ * @author Kevin Klues (klueska@cs.wustl.edu)
+ * @version $Revision$
+ * @date $Date$
+ */
+#include "printf.h"
+interface PrintfFlush
+{
+  command error_t flush();
+  event void flushDone(error_t error);
+}
diff --git a/tos/lib/printf/2_0_2/PrintfP.nc b/tos/lib/printf/2_0_2/PrintfP.nc
new file mode 100644 (file)
index 0000000..5f4ae23
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * "Copyright (c) 2006 Washington University in St. Louis.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL WASHINGTON UNIVERSITY IN ST. LOUIS BE LIABLE TO ANY PARTY
+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF WASHINGTON
+ * UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * WASHINGTON UNIVERSITY IN ST. LOUIS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS."
+ */
+
+/**
+ * This is the PrintfP component.  It provides the printf service for printing
+ * data over the serial interface using the standard c-style printf command.  
+ * It must be started via the SplitControl interface it provides.  Data
+ * printed using printf are buffered and only sent over the serial line after
+ * making a call to PrintfFlush.flush().  This buffer has a maximum size of 
+ * 250 bytes at present.  After calling start on this component, printf
+ * statements can be made anywhere throughout your code, so long as you include
+ * the "printf.h" header file in every file you wish to use it.  Standard
+ * practice is to start the printf service in the main application, and set up 
+ * a timer to periodically flush the printf buffer (500ms should do).  In future
+ * versions, user defined buffer sizes as well as well as automatic flushing at 
+ * user defined intervals will be supported.  
+ *
+ * The printf service is currently only available for msp430 based motes 
+ * (i.e. telos, eyes) and atmega128 based motes (i.e. mica2, micaz).  On the
+ * atmega platforms, avr-libc version 1.4 or above mus tbe used.
+ * 
+ *
+ * @author Kevin Klues (klueska@cs.wustl.edu)
+ * @version $Revision$
+ * @date $Date$
+ */
+
+#include "printf.h"
+
+#ifdef _H_atmega128hardware_H
+static int uart_putchar(char c, FILE *stream);
+static FILE atm128_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
+#endif
+
+module PrintfP {
+  provides {
+    interface SplitControl as PrintfControl;
+    interface PrintfFlush;
+  }
+  uses {
+    interface SplitControl as SerialControl;
+    interface AMSend;
+    interface Packet;
+  }
+}
+implementation {
+  
+  enum {
+    S_STARTED,
+    S_STOPPED,
+    S_FLUSHING,
+  };
+
+  message_t printfMsg;
+  nx_uint8_t buffer[PRINTF_BUFFER_SIZE];
+  norace nx_uint8_t* next_byte;
+  uint8_t state = S_STOPPED;
+  uint32_t bytes_left_to_flush;
+  uint8_t length_to_send;
+  
+  task void retrySend() {
+    if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS)
+      post retrySend();
+  }
+  
+  void sendNext() {
+    printf_msg_t* m = (printf_msg_t*)call Packet.getPayload(&printfMsg, sizeof(printf_msg_t));
+    length_to_send = (bytes_left_to_flush < sizeof(printf_msg_t)) ? bytes_left_to_flush : sizeof(printf_msg_t);
+    memset(m->buffer, 0, sizeof(printf_msg_t));
+    memcpy(m->buffer, (nx_uint8_t*)next_byte, length_to_send);
+    if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS)
+      post retrySend();  
+    else {
+      bytes_left_to_flush -= length_to_send;
+      next_byte += length_to_send;
+    }
+  }
+
+  command error_t PrintfControl.start() {
+    if(state == S_STOPPED)
+      return call SerialControl.start();
+    return FAIL;
+  }
+  
+  command error_t PrintfControl.stop() {
+    if(state == S_STARTED)
+      return call SerialControl.stop();
+    return FAIL;
+  }
+
+  event void SerialControl.startDone(error_t error) {
+    if(error != SUCCESS) {
+      signal PrintfControl.startDone(error);
+      return;
+    }
+#ifdef _H_atmega128hardware_H
+    stdout = &atm128_stdout;
+#endif
+    atomic {
+      memset(buffer, 0, sizeof(buffer));
+      next_byte = buffer;
+      bytes_left_to_flush = 0; 
+      length_to_send = 0;
+      state = S_STARTED;
+    }
+    signal PrintfControl.startDone(error); 
+  }
+
+  event void SerialControl.stopDone(error_t error) {
+    if(error != SUCCESS) {
+      signal PrintfControl.stopDone(error);
+      return;
+    }
+    atomic state = S_STOPPED;
+    signal PrintfControl.stopDone(error); 
+  }
+  
+  command error_t PrintfFlush.flush() {
+    atomic {
+      if(state == S_STARTED && (next_byte > buffer)) {
+        state = S_FLUSHING;
+        bytes_left_to_flush = next_byte - buffer;
+        next_byte = buffer;
+      }
+      else return FAIL;
+    }
+    sendNext();
+    return SUCCESS;
+  }
+    
+  event void AMSend.sendDone(message_t* msg, error_t error) {    
+    if(error == SUCCESS) {
+      if(bytes_left_to_flush > 0)
+        sendNext();
+      else {
+        next_byte = buffer;
+        bytes_left_to_flush = 0; 
+        length_to_send = 0;
+        atomic state = S_STARTED;
+      signal PrintfFlush.flushDone(error);
+    }
+  }
+  else post retrySend();
+  }
+  
+#ifdef _H_msp430hardware_h
+  int putchar(int c) __attribute__((noinline)) @C() @spontaneous() {
+#endif
+#ifdef _H_atmega128hardware_H
+  int uart_putchar(char c, FILE *stream) __attribute__((noinline)) @C() @spontaneous() {
+#endif
+    atomic {
+      if(state == S_STARTED && ((next_byte-buffer) < PRINTF_BUFFER_SIZE)) {
+        *(next_byte++) = c;
+        return 0;
+      }
+      else return -1;
+    }
+  }
+}
diff --git a/tos/lib/printf/2_0_2/avr_stdio.h b/tos/lib/printf/2_0_2/avr_stdio.h
new file mode 100644 (file)
index 0000000..8d1808d
--- /dev/null
@@ -0,0 +1,1094 @@
+/* Copyright (c) 2002, 2005, Joerg Wunsch
+   All rights reserved.
+
+   Portions of documentation Copyright (c) 1990, 1991, 1993
+   The Regents of the University of California.
+
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+
+   * Neither the name of the copyright holders nor the names of
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+  $Id$
+*/
+
+#ifndef _STDIO_H_
+#define        _STDIO_H_ 1
+
+#ifndef __ASSEMBLER__
+
+#include <inttypes.h>
+#include <stdarg.h>
+
+#define __need_NULL
+#define __need_size_t
+#include <stddef.h>
+
+/** \defgroup avr_stdio <stdio.h>: Standard IO facilities
+    \code #include <stdio.h> \endcode
+
+    <h3>Introduction to the Standard IO facilities</h3>
+
+    This file declares the standard IO facilities that are implemented
+    in \c avr-libc.  Due to the nature of the underlying hardware,
+    only a limited subset of standard IO is implemented.  There is no
+    actual file implementation available, so only device IO can be
+    performed.  Since there's no operating system, the application
+    needs to provide enough details about their devices in order to
+    make them usable by the standard IO facilities.
+
+    Due to space constraints, some functionality has not been
+    implemented at all (like some of the \c printf conversions that
+    have been left out).  Nevertheless, potential users of this
+    implementation should be warned: the \c printf and \c scanf families of functions, although
+    usually associated with presumably simple things like the
+    famous "Hello, world!" program, are actually fairly complex
+    which causes their inclusion to eat up a fair amount of code space.
+    Also, they are not fast due to the nature of interpreting the
+    format string at run-time.  Whenever possible, resorting to the
+    (sometimes non-standard) predetermined conversion facilities that are
+    offered by avr-libc will usually cost much less in terms of speed
+    and code size.
+
+    <h3>Tunable options for code size vs. feature set</h3>
+
+    In order to allow programmers a code size vs. functionality tradeoff,
+    the function vfprintf() which is the heart of the printf family can be
+    selected in different flavours using linker options.  See the
+    documentation of vfprintf() for a detailed description.  The same
+    applies to vfscanf() and the \c scanf family of functions.
+
+    <h3>Outline of the chosen API</h3>
+
+    The standard streams \c stdin, \c stdout, and \c stderr are
+    provided, but contrary to the C standard, since avr-libc has no
+    knowledge about applicable devices, these streams are not already
+    pre-initialized at application startup.  Also, since there is no
+    notion of "file" whatsoever to avr-libc, there is no function
+    \c fopen() that could be used to associate a stream to some device.
+    (See \ref stdio_note1 "note 1".)  Instead, the function \c fdevopen()
+    is provided to associate a stream to a device, where the device
+    needs to provide a function to send a character, to receive a
+    character, or both.  There is no differentiation between "text" and
+    "binary" streams inside avr-libc.  Character \c \\n is sent
+    literally down to the device's \c put() function.  If the device
+    requires a carriage return (\c \\r) character to be sent before
+    the linefeed, its \c put() routine must implement this (see
+    \ref stdio_note2 "note 2").
+
+    As an alternative method to fdevopen(), the macro
+    fdev_setup_stream() might be used to setup a user-supplied FILE
+    structure.
+
+    It should be noted that the automatic conversion of a newline
+    character into a carriage return - newline sequence breaks binary
+    transfers.  If binary transfers are desired, no automatic
+    conversion should be performed, but instead any string that aims
+    to issue a CR-LF sequence must use <tt>"\r\n"</tt> explicitly.
+
+    For convenience, the first call to \c fdevopen() that opens a
+    stream for reading will cause the resulting stream to be aliased
+    to \c stdin.  Likewise, the first call to \c fdevopen() that opens
+    a stream for writing will cause the resulting stream to be aliased
+    to both, \c stdout, and \c stderr.  Thus, if the open was done
+    with both, read and write intent, all three standard streams will
+    be identical.  Note that these aliases are indistinguishable from
+    each other, thus calling \c fclose() on such a stream will also
+    effectively close all of its aliases (\ref stdio_note3 "note 3").
+
+    It is possible to tie additional user data to a stream, using
+    fdev_set_udata().  The backend put and get functions can then
+    extract this user data using fdev_get_udata(), and act
+    appropriately.  For example, a single put function could be used
+    to talk to two different UARTs that way, or the put and get
+    functions could keep internal state between calls there.
+
+    <h3>Format strings in flash ROM</h3>
+
+    All the \c printf and \c scanf family functions come in two flavours: the
+    standard name, where the format string is expected to be in
+    SRAM, as well as a version with the suffix "_P" where the format
+    string is expected to reside in the flash ROM.  The macro
+    \c PSTR (explained in \ref avr_pgmspace) becomes very handy
+    for declaring these format strings.
+
+    \anchor stdio_without_malloc
+    <h3>Running stdio without malloc()</h3>
+
+    By default, fdevopen() as well as the floating-point versions of
+    the printf and scanf family require malloc().  As this is often
+    not desired in the limited environment of a microcontroller, an
+    alternative option is provided to run completely without malloc().
+
+    The macro fdev_setup_stream() is provided to prepare a
+    user-supplied FILE buffer for operation with stdio.  If
+    floating-point operation is desired, a user-supplied buffer can as
+    well be passed for the internal buffering for the floating-point
+    numbers (and processing of \%[ scanf data).
+
+    <h4>Example</h4>
+
+    \code
+    #include <stdio.h>
+
+    static int uart_putchar(char c, FILE *stream);
+
+    static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
+                                             _FDEV_SETUP_WRITE);
+
+    static int
+    uart_putchar(char c, FILE *stream)
+    {
+
+      if (c == '\n')
+        uart_putchar('\r', stream);
+      loop_until_bit_is_set(UCSRA, UDRE);
+      UDR = c;
+      return 0;
+    }
+
+    int
+    main(void)
+    {
+      init_uart();
+      stdout = &mystdout;
+      printf("Hello, world!\n");
+
+      return 0;
+    }
+    \endcode
+
+    This example uses the initializer form FDEV_SETUP_STREAM() rather
+    than the function-like fdev_setup_stream(), so all data
+    initialization happens during C start-up.
+
+    If streams initialized that way are no longer needed, they can be
+    destroyed by first calling the macro fdev_close(), and then
+    destroying the object itself.  No call to fclose() should be
+    issued for these streams.  While calling fclose() itself is
+    harmless, it will cause an undefined reference to free() and thus
+    cause the linker to link the malloc module into the application.
+
+    <h3>Notes</h3>
+
+    \anchor stdio_note1 \par Note 1:
+    It might have been possible to implement a device abstraction that
+    is compatible with \c fopen() but since this would have required
+    to parse a string, and to take all the information needed either
+    out of this string, or out of an additional table that would need to be
+    provided by the application, this approach was not taken.
+
+    \anchor stdio_note2 \par Note 2:
+    This basically follows the Unix approach: if a device such as a
+    terminal needs special handling, it is in the domain of the
+    terminal device driver to provide this functionality.  Thus, a
+    simple function suitable as \c put() for \c fdevopen() that talks
+    to a UART interface might look like this:
+
+    \code
+    int
+    uart_putchar(char c, FILE *stream)
+    {
+
+      if (c == '\n')
+        uart_putchar('\r');
+      loop_until_bit_is_set(UCSRA, UDRE);
+      UDR = c;
+      return 0;
+    }
+    \endcode
+
+    \anchor stdio_note3 \par Note 3:
+    This implementation has been chosen because the cost of maintaining
+    an alias is considerably smaller than the cost of maintaining full
+    copies of each stream.  Yet, providing an implementation that offers
+    the complete set of standard streams was deemed to be useful.  Not
+    only that writing \c printf() instead of <tt>fprintf(mystream, ...)</tt>
+    saves typing work, but since avr-gcc needs to resort to pass all
+    arguments of variadic functions on the stack (as opposed to passing
+    them in registers for functions that take a fixed number of
+    parameters), the ability to pass one parameter less by implying
+    \c stdin will also save some execution time.
+*/
+
+#if !defined(__DOXYGEN__)
+
+/*
+ * This is an internal structure of the library that is subject to be
+ * changed without warnings at any time.  Please do *never* reference
+ * elements of it beyond by using the official interfaces provided.
+ */
+struct __file {
+       char    *buf;           /* buffer pointer */
+       unsigned char unget;    /* ungetc() buffer */
+       uint8_t flags;          /* flags, see below */
+#define __SRD  0x0001          /* OK to read */
+#define __SWR  0x0002          /* OK to write */
+#define __SSTR 0x0004          /* this is an sprintf/snprintf string */
+#define __SPGM 0x0008          /* fmt string is in progmem */
+#define __SERR 0x0010          /* found error */
+#define __SEOF 0x0020          /* found EOF */
+#define __SUNGET 0x040         /* ungetc() happened */
+#define __SMALLOC 0x80         /* handle is malloc()ed */
+#if 0
+/* possible future extensions, will require uint16_t flags */
+#define __SRW  0x0100          /* open for reading & writing */
+#define __SLBF 0x0200          /* line buffered */
+#define __SNBF 0x0400          /* unbuffered */
+#define __SMBF 0x0800          /* buf is from malloc */
+#endif
+       int     size;           /* size of buffer */
+       int     len;            /* characters read or written so far */
+       int     (*put)(char, struct __file *);  /* function to write one char to device */
+       int     (*get)(struct __file *);        /* function to read one char from device */
+       void    *udata;         /* User defined and accessible data. */
+};
+
+#endif /* not __DOXYGEN__ */
+
+/*@{*/
+/**
+   \c FILE is the opaque structure that is passed around between the
+   various standard IO functions.
+*/
+#define FILE   struct __file
+
+/**
+   Stream that will be used as an input stream by the simplified
+   functions that don't take a \c stream argument.
+
+   The first stream opened with read intent using \c fdevopen()
+   will be assigned to \c stdin.
+*/
+#define stdin (__iob[0])
+
+/**
+   Stream that will be used as an output stream by the simplified
+   functions that don't take a \c stream argument.
+
+   The first stream opened with write intent using \c fdevopen()
+   will be assigned to both, \c stdin, and \c stderr.
+*/
+#define stdout (__iob[1])
+
+/**
+   Stream destined for error output.  Unless specifically assigned,
+   identical to \c stdout.
+
+   If \c stderr should point to another stream, the result of
+   another \c fdevopen() must be explicitly assigned to it without
+   closing the previous \c stderr (since this would also close
+   \c stdout).
+*/
+#define stderr (__iob[2])
+
+/**
+   \c EOF declares the value that is returned by various standard IO
+   functions in case of an error.  Since the AVR platform (currently)
+   doesn't contain an abstraction for actual files, its origin as
+   "end of file" is somewhat meaningless here.
+*/
+#define EOF    (-1)
+
+/** This macro inserts a pointer to user defined data into a FILE
+    stream object.
+
+    The user data can be useful for tracking state in the put and get
+    functions supplied to the fdevopen() function. */
+#define fdev_set_udata(stream, u) do { (stream)->udata = u; } while(0)
+
+/** This macro retrieves a pointer to user defined data from a FILE
+    stream object. */
+#define fdev_get_udata(stream) ((stream)->udata)
+
+#if defined(__DOXYGEN__)
+/**
+   \brief Setup a user-supplied buffer as an stdio stream
+
+   This macro takes a user-supplied buffer \c stream, and sets it up
+   as a stream that is valid for stdio operations, similar to one that
+   has been obtained dynamically from fdevopen(). The buffer to setup
+   must be of type FILE.
+
+   The arguments \c put and \c get are identical to those that need to
+   be passed to fdevopen().
+
+   The \c rwflag argument can take one of the values _FDEV_SETUP_READ,
+   _FDEV_SETUP_WRITE, or _FDEV_SETUP_RW, for read, write, or read/write
+   intent, respectively.
+
+   \note No assignments to the standard streams will be performed by
+   fdev_setup_stream().  If standard streams are to be used, these
+   need to be assigned by the user.  See also under
+   \ref stdio_without_malloc "Running stdio without malloc()".
+ */
+#define fdev_setup_stream(stream, put, get, rwflag)
+#else  /* !DOXYGEN */
+#define fdev_setup_stream(stream, p, g, f) \
+       do { \
+               (stream)->put = p; \
+               (stream)->get = g; \
+               (stream)->flags = f; \
+               (stream)->udata = 0; \
+       } while(0)
+#endif /* DOXYGEN */
+
+#define _FDEV_SETUP_READ  __SRD        /**< fdev_setup_stream() with read intent */
+#define _FDEV_SETUP_WRITE __SWR        /**< fdev_setup_stream() with write intent */
+#define _FDEV_SETUP_RW    (__SRD|__SWR)        /**< fdev_setup_stream() with read/write intent */
+
+/**
+ * Return code for an error condition during device read.
+ *
+ * To be used in the get function of fdevopen().
+ */
+#define _FDEV_ERR (-1)
+
+/**
+ * Return code for an end-of-file condition during device read.
+ *
+ * To be used in the get function of fdevopen().
+ */
+#define _FDEV_EOF (-2)
+
+#if defined(__DOXYGEN__)
+/**
+   \brief Initializer for a user-supplied stdio stream
+
+   This macro acts similar to fdev_setup_stream(), but it is to be
+   used as the initializer of a variable of type FILE.
+
+   The remaining arguments are to be used as explained in
+   fdev_setup_stream().
+ */
+#define FDEV_SETUP_STREAM(put, get, rwflag)
+#else  /* !DOXYGEN */
+#define FDEV_SETUP_STREAM(p, g, f) \
+       { \
+               .put = p, \
+               .get = g, \
+               .flags = f, \
+               .udata = 0, \
+       }
+#endif /* DOXYGEN */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(__DOXYGEN__)
+/*
+ * Doxygen documentation can be found in fdevopen.c.
+ */
+
+extern struct __file *__iob[];
+
+#if defined(__STDIO_FDEVOPEN_COMPAT_12)
+/*
+ * Declare prototype for the discontinued version of fdevopen() that
+ * has been in use up to avr-libc 1.2.x.  The new implementation has
+ * some backwards compatibility with the old version.
+ */
+extern FILE *fdevopen(int (*__put)(char), int (*__get)(void),
+                      int __opts __attribute__((unused)));
+#else  /* !defined(__STDIO_FDEVOPEN_COMPAT_12) */
+/* New prototype for avr-libc 1.4 and above. */
+extern FILE *fdevopen(int (*__put)(char, FILE*), int (*__get)(FILE*));
+#endif /* defined(__STDIO_FDEVOPEN_COMPAT_12) */
+
+#endif /* not __DOXYGEN__ */
+
+/**
+   This function closes \c stream, and disallows and further
+   IO to and from it.
+
+   When using fdevopen() to setup the stream, a call to fclose() is
+   needed in order to free the internal resources allocated.
+
+   If the stream has been set up using fdev_setup_stream() or
+   FDEV_SETUP_STREAM(), use fdev_close() instead.
+
+   It currently always returns 0 (for success).
+*/
+extern int     fclose(FILE *__stream);
+
+/**
+   This macro frees up any library resources that might be associated
+   with \c stream.  It should be called if \c stream is no longer
+   needed, right before the application is going to destroy the
+   \c stream object itself.
+
+   (Currently, this macro evaluates to nothing, but this might change
+   in future versions of the library.)
+*/
+#if defined(__DOXYGEN__)
+# define fdev_close()
+#else
+# define fdev_close() ((void)0)
+#endif
+
+/**
+   \c vfprintf is the central facility of the \c printf family of
+   functions.  It outputs values to \c stream under control of a
+   format string passed in \c fmt.  The actual values to print are
+   passed as a variable argument list \c ap.
+
+   \c vfprintf returns the number of characters written to \c stream,
+   or \c EOF in case of an error.  Currently, this will only happen
+   if \c stream has not been opened with write intent.
+
+   The format string is composed of zero or more directives: ordinary
+   characters (not \c %), which are copied unchanged to the output
+   stream; and conversion specifications, each of which results in
+   fetching zero or more subsequent arguments.  Each conversion
+   specification is introduced by the \c % character.  The arguments must
+   properly correspond (after type promotion) with the conversion
+   specifier.  After the \c %, the following appear in sequence:
+
+   - Zero or more of the following flags:
+      <ul>
+      <li> \c # The value should be converted to an "alternate form".  For
+            c, d, i, s, and u conversions, this option has no effect.
+            For o conversions, the precision of the number is
+            increased to force the first character of the output
+            string to a zero (except if a zero value is printed with
+            an explicit precision of zero).  For x and X conversions,
+            a non-zero result has the string `0x' (or `0X' for X
+            conversions) prepended to it.</li>
+      <li> \c 0 (zero) Zero padding.  For all conversions, the converted
+            value is padded on the left with zeros rather than blanks.
+            If a precision is given with a numeric conversion (d, i,
+            o, u, i, x, and X), the 0 flag is ignored.</li>
+      <li> \c - A negative field width flag; the converted value is to be
+            left adjusted on the field boundary.  The converted value
+            is padded on the right with blanks, rather than on the
+            left with blanks or zeros.  A - overrides a 0 if both are
+            given.</li>
+      <li> ' ' (space) A blank should be left before a positive number
+            produced by a signed conversion (d, or i).</li>
+      <li> \c + A sign must always be placed before a number produced by a
+            signed conversion.  A + overrides a space if both are
+            used.</li>
+      </ul>
+      
+   -   An optional decimal digit string specifying a minimum field width.
+       If the converted value has fewer characters than the field width, it
+       will be padded with spaces on the left (or right, if the left-adjust­
+       ment flag has been given) to fill out the field width.
+   -   An optional precision, in the form of a period . followed by an
+       optional digit string.  If the digit string is omitted, the
+       precision is taken as zero.  This gives the minimum number of
+       digits to appear for d, i, o, u, x, and X conversions, or the
+       maximum number of characters to be printed from a string for \c s
+       conversions.
+   -   An optional \c l length modifier, that specifies that the
+       argument for the d, i, o, u, x, or X conversion is a \c "long int"
+       rather than \c int.
+   -   A character that specifies the type of conversion to be applied.
+
+   The conversion specifiers and their meanings are:
+
+   - \c diouxX The int (or appropriate variant) argument is converted
+           to signed decimal (d and i), unsigned octal (o), unsigned
+           decimal (u), or unsigned hexadecimal (x and X) notation.
+           The letters "abcdef" are used for x conversions; the
+           letters "ABCDEF" are used for X conversions.  The
+           precision, if any, gives the minimum number of digits that
+           must appear; if the converted value requires fewer digits,
+           it is padded on the left with zeros.
+   - \c p  The <tt>void *</tt> argument is taken as an unsigned integer,
+           and converted similarly as a <tt>%\#x</tt> command would do.
+   - \c c  The \c int argument is converted to an \c "unsigned char", and the
+           resulting character is written.
+   - \c s  The \c "char *" argument is expected to be a pointer to an array
+           of character type (pointer to a string).  Characters from
+           the array are written up to (but not including) a
+           terminating NUL character; if a precision is specified, no
+           more than the number specified are written.  If a precision
+           is given, no null character need be present; if the
+           precision is not specified, or is greater than the size of
+           the array, the array must contain a terminating NUL
+           character.
+   - \c %  A \c % is written.  No argument is converted.  The complete
+           conversion specification is "%%".
+   - \c eE The double argument is rounded and converted in the format
+           \c "[-]d.ddde±dd" where there is one digit before the
+           decimal-point character and the number of digits after it
+           is equal to the precision; if the precision is missing, it
+           is taken as 6; if the precision is zero, no decimal-point
+           character appears.  An \e E conversion uses the letter \c 'E'
+           (rather than \c 'e') to introduce the exponent.  The exponent
+           always contains two digits; if the value is zero,
+           the exponent is 00.
+   - \c fF The double argument is rounded and converted to decimal notation
+           in the format \c "[-]ddd.ddd", where the number of digits after the
+           decimal-point character is equal to the precision specification.
+           If the precision is missing, it is taken as 6; if the precision
+           is explicitly zero, no decimal-point character appears.  If a
+           decimal point appears, at least one digit appears before it.
+   - \c gG The double argument is converted in style \c f or \c e (or
+           \c F or \c E for \c G conversions).  The precision
+           specifies the number of significant digits.  If the
+           precision is missing, 6 digits are given; if the precision
+           is zero, it is treated as 1.  Style \c e is used if the
+           exponent from its conversion is less than -4 or greater
+           than or equal to the precision.  Trailing zeros are removed
+           from the fractional part of the result; a decimal point
+           appears only if it is followed by at least one digit.
+   - \c S  Similar to the \c s format, except the pointer is expected to
+           point to a program-memory (ROM) string instead of a RAM string.
+
+   In no case does a non-existent or small field width cause truncation of a
+   numeric field; if the result of a conversion is wider than the field
+   width, the field is expanded to contain the conversion result.
+
+   Since the full implementation of all the mentioned features becomes
+   fairly large, three different flavours of vfprintf() can be
+   selected using linker options.  The default vfprintf() implements
+   all the mentioned functionality except floating point conversions.
+   A minimized version of vfprintf() is available that only implements
+   the very basic integer and string conversion facilities, but none
+   of the additional options that can be specified using conversion
+   flags (these flags are parsed correctly from the format
+   specification, but then simply ignored).  This version can be
+   requested using the following \ref gcc_minusW "compiler options":
+
+   \code
+   -Wl,-u,vfprintf -lprintf_min
+   \endcode
+
+   If the full functionality including the floating point conversions
+   is required, the following options should be used:
+
+   \code
+   -Wl,-u,vfprintf -lprintf_flt -lm
+   \endcode
+
+   \par Limitations:
+   - The specified width and precision can be at most 127.
+   - For floating-point conversions, trailing digits will be lost if
+     a number close to DBL_MAX is converted with a precision > 0.
+
+ */
+
+extern int     vfprintf(FILE *__stream, const char *__fmt, va_list __ap);
+
+/**
+   Variant of \c vfprintf() that uses a \c fmt string that resides
+   in program memory.
+*/
+extern int     vfprintf_P(FILE *__stream, const char *__fmt, va_list __ap);
+
+/**
+   The function \c fputc sends the character \c c (though given as type
+   \c int) to \c stream.  It returns the character, or \c EOF in case
+   an error occurred.
+*/
+extern int     fputc(int __c, FILE *__stream);
+
+#if !defined(__DOXYGEN__)
+
+/* putc() function implementation, required by standard */
+extern int     putc(int __c, FILE *__stream);
+
+/* putchar() function implementation, required by standard */
+extern int     putchar(int __c);
+
+#endif /* not __DOXYGEN__ */
+
+/**
+   The macro \c putc used to be a "fast" macro implementation with a
+   functionality identical to fputc().  For space constraints, in
+   \c avr-libc, it is just an alias for \c fputc.
+*/
+#define putc(__c, __stream) fputc(__c, __stream)
+
+/**
+   The macro \c putchar sends character \c c to \c stdout.
+*/
+#define putchar(__c) fputc(__c, stdout)
+
+/**
+   The function \c printf performs formatted output to stream
+   \c stderr.  See \c vfprintf() for details.
+*/
+extern int     printf(const char *__fmt, ...);
+
+/**
+   Variant of \c printf() that uses a \c fmt string that resides
+   in program memory.
+*/
+extern int     printf_P(const char *__fmt, ...);
+
+/**
+   The function \c vprintf performs formatted output to stream
+   \c stdout, taking a variable argument list as in vfprintf().
+
+   See vfprintf() for details.
+*/
+extern int     vprintf(const char *__fmt, va_list __ap);
+
+/**
+   Variant of \c printf() that sends the formatted characters
+   to string \c s.
+*/
+extern int     sprintf(char *__s, const char *__fmt, ...);
+
+/**
+   Variant of \c sprintf() that uses a \c fmt string that resides
+   in program memory.
+*/
+extern int     sprintf_P(char *__s, const char *__fmt, ...);
+
+/**
+   Like \c sprintf(), but instead of assuming \c s to be of infinite
+   size, no more than \c n characters (including the trailing NUL
+   character) will be converted to \c s.
+
+   Returns the number of characters that would have been written to
+   \c s if there were enough space.
+*/
+extern int     snprintf(char *__s, size_t __n, const char *__fmt, ...);
+
+/**
+   Variant of \c snprintf() that uses a \c fmt string that resides
+   in program memory.
+*/
+extern int     snprintf_P(char *__s, size_t __n, const char *__fmt, ...);
+
+/**
+   Like \c sprintf() but takes a variable argument list for the
+   arguments.
+*/
+extern int     vsprintf(char *__s, const char *__fmt, va_list ap);
+
+/**
+   Variant of \c vsprintf() that uses a \c fmt string that resides
+   in program memory.
+*/
+extern int     vsprintf_P(char *__s, const char *__fmt, va_list ap);
+
+/**
+   Like \c vsprintf(), but instead of assuming \c s to be of infinite
+   size, no more than \c n characters (including the trailing NUL
+   character) will be converted to \c s.
+
+   Returns the number of characters that would have been written to
+   \c s if there were enough space.
+*/
+extern int     vsnprintf(char *__s, size_t __n, const char *__fmt, va_list ap);
+
+/**
+   Variant of \c vsnprintf() that uses a \c fmt string that resides
+   in program memory.
+*/
+extern int     vsnprintf_P(char *__s, size_t __n, const char *__fmt, va_list ap);
+/**
+   The function \c fprintf performs formatted output to \c stream.
+   See \c vfprintf() for details.
+*/
+extern int     fprintf(FILE *__stream, const char *__fmt, ...);
+
+/**
+   Variant of \c fprintf() that uses a \c fmt string that resides
+   in program memory.
+*/
+extern int     fprintf_P(FILE *__stream, const char *__fmt, ...);
+
+/**
+   Write the string pointed to by \c str to stream \c stream.
+
+   Returns 0 on success and EOF on error.
+*/
+extern int     fputs(const char *__str, FILE *__stream);
+
+/**
+   Variant of fputs() where \c str resides in program memory.
+*/
+extern int     fputs_P(const char *__str, FILE *__stream);
+
+/**
+   Write the string pointed to by \c str, and a trailing newline
+   character, to \c stdout.
+*/
+extern int     puts(const char *__str);
+
+/**
+   Variant of puts() where \c str resides in program memory.
+*/
+extern int     puts_P(const char *__str);
+
+/**
+   Write \c nmemb objects, \c size bytes each, to \c stream.
+   The first byte of the first object is referenced by \c ptr.
+
+   Returns the number of objects successfully written, i. e.
+   \c nmemb unless an output error occured.
+ */
+extern size_t  fwrite(const void *__ptr, size_t __size, size_t __nmemb,
+                      FILE *__stream);
+
+/**
+   The function \c fgetc reads a character from \c stream.  It returns
+   the character, or \c EOF in case end-of-file was encountered or an
+   error occurred.  The routines feof() or ferror() must be used to
+   distinguish between both situations.
+*/
+extern int     fgetc(FILE *__stream);
+
+#if !defined(__DOXYGEN__)
+
+/* getc() function implementation, required by standard */
+extern int     getc(FILE *__stream);
+
+/* getchar() function implementation, required by standard */
+extern int     getchar(void);
+
+#endif /* not __DOXYGEN__ */
+
+/**
+   The macro \c getc used to be a "fast" macro implementation with a
+   functionality identical to fgetc().  For space constraints, in
+   \c avr-libc, it is just an alias for \c fgetc.
+*/
+#define getc(__stream) fgetc(__stream)
+
+/**
+   The macro \c getchar reads a character from \c stdin.  Return
+   values and error handling is identical to fgetc().
+*/
+#define getchar() fgetc(stdin)
+
+/**
+   The ungetc() function pushes the character \c c (converted to an
+   unsigned char) back onto the input stream pointed to by \c stream.
+   The pushed-back character will be returned by a subsequent read on
+   the stream.
+
+   Currently, only a single character can be pushed back onto the
+   stream.
+   
+   The ungetc() function returns the character pushed back after the
+   conversion, or \c EOF if the operation fails.  If the value of the
+   argument \c c character equals \c EOF, the operation will fail and
+   the stream will remain unchanged.
+*/
+extern int     ungetc(int __c, FILE *__stream);
+
+/**
+   Read at most <tt>size - 1</tt> bytes from \c stream, until a
+   newline character was encountered, and store the characters in the
+   buffer pointed to by \c str.  Unless an error was encountered while
+   reading, the string will then be terminated with a \c NUL
+   character.
+
+   If an error was encountered, the function returns NULL and sets the
+   error flag of \c stream, which can be tested using ferror().
+   Otherwise, a pointer to the string will be returned.  */
+extern char    *fgets(char *__str, int __size, FILE *__stream);
+
+/**
+   Similar to fgets() except that it will operate on stream \c stdin,
+   and the trailing newline (if any) will not be stored in the string.
+   It is the caller's responsibility to provide enough storage to hold
+   the characters read.  */
+extern char    *gets(char *__str);
+
+/**
+   Read \c nmemb objects, \c size bytes each, from \c stream,
+   to the buffer pointed to by \c ptr.
+
+   Returns the number of objects successfully read, i. e.
+   \c nmemb unless an input error occured or end-of-file was
+   encountered.  feof() and ferror() must be used to distinguish
+   between these two conditions.
+ */
+extern size_t  fread(void *__ptr, size_t __size, size_t __nmemb,
+                     FILE *__stream);
+
+/**
+   Clear the error and end-of-file flags of \c stream.
+ */
+extern void    clearerr(FILE *__stream);
+
+#if !defined(__DOXYGEN__)
+/* fast inlined version of clearerr() */
+#define clearerror(s) do { (s)->flags &= ~(__SERR | __SEOF); } while(0)
+#endif /* !defined(__DOXYGEN__) */
+
+/**
+   Test the end-of-file flag of \c stream.  This flag can only be cleared
+   by a call to clearerr().
+ */
+extern int     feof(FILE *__stream);
+
+#if !defined(__DOXYGEN__)
+/* fast inlined version of feof() */
+#define feof(s) ((s)->flags & __SEOF)
+#endif /* !defined(__DOXYGEN__) */
+
+/**
+   Test the error flag of \c stream.  This flag can only be cleared
+   by a call to clearerr().
+ */
+extern int     ferror(FILE *__stream);
+
+#if !defined(__DOXYGEN__)
+/* fast inlined version of ferror() */
+#define ferror(s) ((s)->flags & __SERR)
+#endif /* !defined(__DOXYGEN__) */
+
+/**
+   Formatted input.  This function is the heart of the \c scanf
+   family of functions.
+
+   Characters are read from \c stream and processed in a way
+   described by \c fmt.  Conversion results will be assigned to the
+   parameters passed via \c ap.
+
+   The format string \c fmt is scanned for conversion specifications.
+   Anything that doesn't comprise a conversion specification is taken
+   as text that is matched literally against the input.  White space
+   in the format string will match any white space in the data
+   (including none), all other characters match only itself.
+   Processing is aborted as soon as the data and format string no
+   longer match, or there is an error or end-of-file condition on
+   \c stream.
+
+   Most conversions skip leading white space before starting the
+   actual conversion.
+
+   Conversions are introduced with the character \b %.  Possible
+   options can follow the \b %:
+
+   - a \c * indicating that the conversion should be performed but
+     the conversion result is to be discarded; no parameters will
+     be processed from \c ap,
+   - the character \c h indicating that the argument is a pointer
+     to <tt>short int</tt> (rather than <tt>int</tt>),
+   - the character \c l indicating that the argument is a pointer
+     to <tt>long int</tt> (rather than <tt>int</tt>, for integer
+     type conversions), or a pointer to \c double (for floating
+     point conversions).
+
+   In addition, a maximal field width may be specified as a nonzero
+   positive decimal integer, which will restrict the conversion to at
+   most this many characters from the input stream.  This field width
+   is limited to at most 127 characters which is also the default
+   value (except for the <tt>%c</tt> conversion that defaults to 1).
+
+   The following conversion flags are supported:
+
+   - \c % Matches a literal \c % character.  This is not a conversion.
+   - \c d Matches an optionally signed decimal integer; the next
+     pointer must be a pointer to \c int.
+   - \c i Matches an optionally signed integer; the next pointer must
+     be a pointer to \c int.  The integer is read in base 16 if it
+     begins with \b 0x or \b 0X, in base 8 if it begins with \b 0, and
+     in base 10 otherwise.  Only characters that correspond to the
+     base are used.
+   - \c o Matches an octal integer; the next pointer must be a pointer to
+     <tt>unsigned int</tt>.
+   - \c u Matches an optionally signed decimal integer; the next
+     pointer must be a pointer to <tt>unsigned int</tt>.
+   - \c x Matches an optionally signed hexadecimal integer; the next
+     pointer must be a pointer to <tt>unsigned int</tt>.
+   - \c f Matches an optionally signed floating-point number; the next
+     pointer must be a pointer to \c float.
+   - <tt>e, g, E, G</tt> Equivalent to \c f.
+   - \c s
+     Matches a sequence of non-white-space characters; the next pointer
+     must be a pointer to \c char, and the array must be large enough to
+     accept all the sequence and the terminating \c NUL character.  The
+     input string stops at white space or at the maximum field width,
+     whichever occurs first.
+   - \c c
+     Matches a sequence of width count characters (default 1); the next
+     pointer must be a pointer to \c char, and there must be enough room
+     for all the characters (no terminating \c NUL is added).  The usual
+     skip of leading white space is suppressed.  To skip white space
+     first, use an explicit space in the format.
+   - \c [
+     Matches a nonempty sequence of characters from the specified set
+     of accepted characters; the next pointer must be a pointer to \c
+     char, and there must be enough room for all the characters in the
+     string, plus a terminating \c NUL character.  The usual skip of
+     leading white space is suppressed.  The string is to be made up
+     of characters in (or not in) a particular set; the set is defined
+     by the characters between the open bracket \c [ character and a
+     close bracket \c ] character.  The set excludes those characters
+     if the first character after the open bracket is a circumflex
+     \c ^.  To include a close bracket in the set, make it the first
+     character after the open bracket or the circumflex; any other
+     position will end the set.  The hyphen character \c - is also
+     special; when placed between two other characters, it adds all
+     intervening characters to the set.  To include a hyphen, make it
+     the last character before the final close bracket.  For instance,
+     <tt>[^]0-9-]</tt> means the set of <em>everything except close
+     bracket, zero through nine, and hyphen</em>.  The string ends
+     with the appearance of a character not in the (or, with a
+     circumflex, in) set or when the field width runs out.
+   - \c p
+     Matches a pointer value (as printed by <tt>%p</tt> in printf()); the
+     next pointer must be a pointer to \c void.
+   - \c n
+     Nothing is expected; instead, the number of characters consumed
+     thus far from the input is stored through the next pointer, which
+     must be a pointer to \c int.  This is not a conversion, although it
+     can be suppressed with the \c * flag.
+
+     These functions return the number of input items assigned, which
+     can be fewer than provided for, or even zero, in the event of a
+     matching failure.  Zero indicates that, while there was input
+     available, no conversions were assigned; typically this is due
+     to an invalid input character, such as an alphabetic character
+     for a <tt>%d</tt> conversion.  The value \c EOF is returned if an input
+     failure occurs before any conversion such as an end-of-file
+     occurs.  If an error or end-of-file occurs after conversion has
+     begun, the number of conversions which were successfully
+     completed is returned.
+
+     By default, all the conversions described above are available
+     except the floating-point conversions, and the <tt>\%[</tt> conversion.
+     These conversions will be available in the extended version
+     provided by the library \c libscanf_flt.a.  Note that either of
+     these conversions requires the availability of a buffer that
+     needs to be obtained at run-time using malloc().  If this buffer
+     cannot be obtained, the operation is aborted, returning the
+     value \c EOF.  To link a program against the extended version,
+     use the following compiler flags in the link stage:
+
+     \code
+     -Wl,-u,vfscanf -lscanf_flt -lm
+     \endcode
+
+     A third version is available for environments that are tight
+     on space.  This version is provided in the library
+     \c libscanf_min.a, and can be requested using the following
+     options in the link stage:
+
+     \code
+     -Wl,-u,vfscanf -lscanf_min -lm
+     \endcode
+
+     In addition to the restrictions of the standard version, this
+     version implements no field width specification, no conversion
+     assignment suppression flag (\c *), no <tt>%n</tt> specification, and
+     no general format character matching at all.  All characters in
+     \c fmt that do not comprise a conversion specification will
+     simply be ignored, including white space (that is normally used
+     to consume \e any amount of white space in the input stream).
+     However, the usual skip of initial white space in the formats
+     that support it is implemented.
+*/
+extern int     vfscanf(FILE *__stream, const char *__fmt, va_list __ap);
+
+/**
+   Variant of vfscanf() using a \c fmt string in program memory.
+ */
+extern int     vfscanf_P(FILE *__stream, const char *__fmt, va_list __ap);
+
+/**
+   The function \c fscanf performs formatted input, reading the
+   input data from \c stream.
+
+   See vfscanf() for details.
+ */
+extern int     fscanf(FILE *__stream, const char *__fmt, ...);
+
+/**
+   Variant of fscanf() using a \c fmt string in program memory.
+ */
+extern int     fscanf_P(FILE *__stream, const char *__fmt, ...);
+
+/**
+   The function \c scanf performs formatted input from stream \c stdin.
+
+   See vfscanf() for details.
+ */
+extern int     scanf(const char *__fmt, ...);
+
+/**
+   Variant of scanf() where \c fmt resides in program memory.
+ */
+extern int     scanf_P(const char *__fmt, ...);
+
+/**
+   The function \c vscanf performs formatted input from stream
+   \c stdin, taking a variable argument list as in vfscanf().
+
+   See vfscanf() for details.
+*/
+extern int     vscanf(const char *__fmt, va_list __ap);
+
+/**
+   The function \c sscanf performs formatted input, reading the
+   input data from the buffer pointed to by \c buf.
+
+   See vfscanf() for details.
+ */
+extern int     sscanf(const char *__buf, const char *__fmt, ...);
+
+/**
+   Variant of sscanf() using a \c fmt string in program memory.
+ */
+extern int     sscanf_P(const char *__buf, const char *__fmt, ...);
+
+#if defined(__DOXYGEN__)
+/**
+   Flush \c stream.
+
+   This is a null operation provided for source-code compatibility
+   only, as the standard IO implementation currently does not perform
+   any buffering.
+ */
+extern int     fflush(FILE *stream);
+#else
+static __inline__ int fflush(FILE *stream __attribute__((unused)))
+{
+       return 0;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*@}*/
+
+/*
+ * The following constants are currently not used by avr-libc's
+ * stdio subsystem.  They are defined here since the gcc build
+ * environment expects them to be here.
+ */
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+#endif /* __ASSEMBLER */
+
+#endif /* _STDLIB_H_ */
diff --git a/tos/lib/printf/2_0_2/printf.h b/tos/lib/printf/2_0_2/printf.h
new file mode 100644 (file)
index 0000000..fcaee28
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * "Copyright (c) 2006 Washington University in St. Louis.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL WASHINGTON UNIVERSITY IN ST. LOUIS BE LIABLE TO ANY PARTY
+ * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
+ * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF WASHINGTON
+ * UNIVERSITY IN ST. LOUIS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * WASHINGTON UNIVERSITY IN ST. LOUIS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND WASHINGTON UNIVERSITY IN ST. LOUIS HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
+ * MODIFICATIONS."
+ */
+
+/**
+ *
+ * @author Kevin Klues (klueska@cs.wustl.edu)
+ * @version $Revision$
+ * @date $Date$
+ */
+
+#ifndef PRINTF_H
+#define PRINTF_H
+
+#ifndef PRINTF_BUFFER_SIZE
+#define PRINTF_BUFFER_SIZE  250
+#endif
+
+#ifdef _H_msp430hardware_h
+  #include <stdio.h>
+#endif
+#ifdef _H_atmega128hardware_H
+  #include "avr_stdio.h"
+#endif
+#include "message.h"
+
+typedef nx_struct printf_msg {
+  nx_uint8_t buffer[TOSH_DATA_LENGTH];
+} printf_msg_t;
+
+enum {
+  AM_PRINTF_MSG = 100,
+};
+
+#endif //PRINTF_H
+
diff --git a/tos/lib/printf/MainC.nc b/tos/lib/printf/MainC.nc
new file mode 100644 (file)
index 0000000..7c805fe
--- /dev/null
@@ -0,0 +1,61 @@
+// $Id$
+
+/*                                                                      tab:4
+ * "Copyright (c) 2000-2003 The Regents of the University  of California.  
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2003 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE     
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
+ * 94704.  Attention:  Intel License Inquiry.
+ *
+ * Date last modified:  $Id$
+ */
+
+/**
+ * MainC is the system interface the TinyOS boot sequence. It wires the
+ * boot sequence implementation to the scheduler and hardware resources.
+ *
+ * @author Philip Levis
+ * @author Kevin Klues
+ * @date   August 6 2005
+ */
+
+#include "hardware.h"
+
+configuration MainC {
+  provides interface Boot;
+  uses interface Init as SoftwareInit;
+}
+implementation {
+  components PlatformC, RealMainP, TinySchedulerC;
+  components PrintfC;
+
+  RealMainP.Scheduler -> TinySchedulerC;
+  RealMainP.PlatformInit -> PlatformC;
+  PrintfC.MainBoot -> RealMainP;
+
+  // Export the SoftwareInit and Booted for applications
+  SoftwareInit = RealMainP.SoftwareInit;
+  Boot = PrintfC;
+}
+
index a9a8b7383dcf87eb90a03ceecdc2b74eb9cc4371..94dc3d52604678a36558c60a6eea46ce96e1dde6 100644 (file)
  * @version $Revision$
  * @date $Date$
  */
-
 #include "printf.h"
 
 configuration PrintfC {
   provides {
-       interface SplitControl as PrintfControl;
-       interface PrintfFlush;
+    interface Boot;
   }
+  uses interface Boot as MainBoot @exactlyonce();
 }
 implementation {
   components SerialActiveMessageC;
   components new SerialAMSenderC(AM_PRINTF_MSG);
-  components PrintfP;
+  components new PrintfQueueC(uint8_t, PRINTF_BUFFER_SIZE) as QueueC;
 
-  PrintfControl = PrintfP;
-  PrintfFlush = PrintfP;
+  components PrintfP;
+  components LedsC;
+  
+  MainBoot = PrintfP.MainBoot;
+  Boot = PrintfP.Boot;
   
   PrintfP.SerialControl -> SerialActiveMessageC;
+  PrintfP.Queue -> QueueC;
   PrintfP.AMSend -> SerialAMSenderC;
   PrintfP.Packet -> SerialAMSenderC;
+  PrintfP.Leds -> LedsC;
 }
 
index 5f4ae23110d7587cd358de7dd79c4e229f2a6be4..78595a8db9f19189352fdad01fa28be6717729d6 100644 (file)
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
  * MODIFICATIONS."
  */
+ /*
+ * Copyright (c) 2007 Stanford University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Stanford University nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL STANFORD
+ * UNIVERSITY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 /**
  * This is the PrintfP component.  It provides the printf service for printing
  * (i.e. telos, eyes) and atmega128 based motes (i.e. mica2, micaz).  On the
  * atmega platforms, avr-libc version 1.4 or above mus tbe used.
  * 
- *
- * @author Kevin Klues (klueska@cs.wustl.edu)
- * @version $Revision$
- * @date $Date$
+ */
+/**
+ * @author Kevin Klues <klueska@cs.stanford.edu>
+ * @date September 18, 2007
  */
 
 #include "printf.h"
@@ -53,95 +85,68 @@ static FILE atm128_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WR
 
 module PrintfP {
   provides {
-    interface SplitControl as PrintfControl;
-    interface PrintfFlush;
+    interface Boot;
   }
   uses {
+    interface Boot as MainBoot;
     interface SplitControl as SerialControl;
+    interface PrintfQueue<uint8_t> as Queue;
+
     interface AMSend;
     interface Packet;
+    interface Leds;
   }
 }
 implementation {
   
   enum {
-    S_STARTED,
     S_STOPPED,
+    S_STARTED,
     S_FLUSHING,
   };
 
   message_t printfMsg;
-  nx_uint8_t buffer[PRINTF_BUFFER_SIZE];
-  norace nx_uint8_t* next_byte;
   uint8_t state = S_STOPPED;
-  uint32_t bytes_left_to_flush;
-  uint8_t length_to_send;
-  
-  task void retrySend() {
-    if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS)
-      post retrySend();
-  }
   
-  void sendNext() {
-    printf_msg_t* m = (printf_msg_t*)call Packet.getPayload(&printfMsg, sizeof(printf_msg_t));
-    length_to_send = (bytes_left_to_flush < sizeof(printf_msg_t)) ? bytes_left_to_flush : sizeof(printf_msg_t);
-    memset(m->buffer, 0, sizeof(printf_msg_t));
-    memcpy(m->buffer, (nx_uint8_t*)next_byte, length_to_send);
-    if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS)
-      post retrySend();  
-    else {
-      bytes_left_to_flush -= length_to_send;
-      next_byte += length_to_send;
-    }
-  }
-
-  command error_t PrintfControl.start() {
-    if(state == S_STOPPED)
-      return call SerialControl.start();
-    return FAIL;
-  }
-  
-  command error_t PrintfControl.stop() {
-    if(state == S_STARTED)
-      return call SerialControl.stop();
-    return FAIL;
+  event void MainBoot.booted() {
+    call SerialControl.start();
   }
 
   event void SerialControl.startDone(error_t error) {
-    if(error != SUCCESS) {
-      signal PrintfControl.startDone(error);
-      return;
-    }
 #ifdef _H_atmega128hardware_H
     stdout = &atm128_stdout;
 #endif
-    atomic {
-      memset(buffer, 0, sizeof(buffer));
-      next_byte = buffer;
-      bytes_left_to_flush = 0; 
-      length_to_send = 0;
-      state = S_STARTED;
-    }
-    signal PrintfControl.startDone(error); 
+    atomic state = S_STARTED;
+    signal Boot.booted();
   }
 
   event void SerialControl.stopDone(error_t error) {
-    if(error != SUCCESS) {
-      signal PrintfControl.stopDone(error);
-      return;
-    }
     atomic state = S_STOPPED;
-    signal PrintfControl.stopDone(error); 
   }
   
-  command error_t PrintfFlush.flush() {
+  task void retrySend() {
+    if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS)
+      post retrySend();
+  }
+  
+  void sendNext() {
+    int i;
+    printf_msg_t* m = (printf_msg_t*)call Packet.getPayload(&printfMsg, sizeof(printf_msg_t));
+    uint16_t length_to_send = (call Queue.size() < sizeof(printf_msg_t)) ? call Queue.size() : sizeof(printf_msg_t);
+    memset(m->buffer, 0, sizeof(printf_msg_t));
+    for(i=0; i<length_to_send; i++)
+      m->buffer[i] = call Queue.dequeue();
+    if(call AMSend.send(AM_BROADCAST_ADDR, &printfMsg, sizeof(printf_msg_t)) != SUCCESS)
+      post retrySend();  
+  }
+  
+  int printfflush() @C() @spontaneous() {
     atomic {
-      if(state == S_STARTED && (next_byte > buffer)) {
-        state = S_FLUSHING;
-        bytes_left_to_flush = next_byte - buffer;
-        next_byte = buffer;
-      }
-      else return FAIL;
+      if(state == S_FLUSHING)
+        return SUCCESS;
+      if(call Queue.empty())
+        return FAIL;
+      state = S_FLUSHING;
     }
     sendNext();
     return SUCCESS;
@@ -149,17 +154,11 @@ implementation {
     
   event void AMSend.sendDone(message_t* msg, error_t error) {    
     if(error == SUCCESS) {
-      if(bytes_left_to_flush > 0)
+      if(call Queue.size() > 0)
         sendNext();
-      else {
-        next_byte = buffer;
-        bytes_left_to_flush = 0; 
-        length_to_send = 0;
-        atomic state = S_STARTED;
-      signal PrintfFlush.flushDone(error);
+      else state = S_STARTED;
     }
-  }
-  else post retrySend();
+    else post retrySend();
   }
   
 #ifdef _H_msp430hardware_h
@@ -168,11 +167,13 @@ implementation {
 #ifdef _H_atmega128hardware_H
   int uart_putchar(char c, FILE *stream) __attribute__((noinline)) @C() @spontaneous() {
 #endif
+    if((state == S_STARTED) && (call Queue.size() >= 5*sizeof(printf_msg_t))) {
+      state = S_FLUSHING;
+      sendNext();
+    }
     atomic {
-      if(state == S_STARTED && ((next_byte-buffer) < PRINTF_BUFFER_SIZE)) {
-        *(next_byte++) = c;
+      if(call Queue.enqueue(c) == SUCCESS)
         return 0;
-      }
       else return -1;
     }
   }
index fcaee28001588785522711cf4ffa5400bacee993..835e40e0a7eeb8ea219fbb0bb569a21cb41bfb96 100644 (file)
 #define PRINTF_H
 
 #ifndef PRINTF_BUFFER_SIZE
-#define PRINTF_BUFFER_SIZE  250
+#define PRINTF_BUFFER_SIZE 250 
+#endif
+
+#if PRINTF_BUFFER_SIZE > 255
+  #define PrintfQueueC BigQueueC
+  #define PrintfQueue  BigQueue
+#else
+  #define PrintfQueueC QueueC
+  #define PrintfQueue  Queue
 #endif
 
 #ifdef _H_msp430hardware_h