Index: partition.h
===================================================================
--- partition.h	(.../sd-reader_release_20060808)	(Revision 106)
+++ partition.h	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #ifndef PARTITION_H
 #define PARTITION_H
 
Index: sd_raw.c
===================================================================
--- sd_raw.c	(.../sd-reader_release_20060808)	(Revision 106)
+++ sd_raw.c	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #include <avr/io.h>
 
 #include "sd_raw.h"
Index: uart.h
===================================================================
--- uart.h	(.../sd-reader_release_20060808)	(Revision 106)
+++ uart.h	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #ifndef UART_H
 #define UART_H
 
Index: fat16.c
===================================================================
--- fat16.c	(.../sd-reader_release_20060808)	(Revision 106)
+++ fat16.c	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #include "partition.h"
 #include "fat16.h"
 #include "fat16_config.h"
@@ -158,6 +163,12 @@
     uint8_t byte_count;
 };
 
+struct fat16_usage_count_callback_arg
+{
+    uint16_t cluster_count;
+    uint8_t buffer_size;
+};
+
 static uint8_t fat16_read_header(struct fat16_fs_struct* fs);
 static uint8_t fat16_read_root_dir_entry(const struct fat16_fs_struct* fs, uint16_t entry_num, struct fat16_dir_entry_struct* dir_entry);
 static uint8_t fat16_read_sub_dir_entry(const struct fat16_fs_struct* fs, uint16_t entry_num, const struct fat16_dir_entry_struct* parent, struct fat16_dir_entry_struct* dir_entry);
@@ -169,6 +180,8 @@
 static uint8_t fat16_free_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num);
 static uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_entry_struct* dir_entry);
 
+static uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p);
+
 /**
  * \ingroup fat16_fs
  * Opens a FAT16 filesystem.
@@ -1679,3 +1692,70 @@
 #endif
 }
 
+/**
+ * \ingroup fat16_fs
+ * Returns the amount of total storage capacity of the filesystem in bytes.
+ *
+ * \param[in] fs The filesystem on which to operate.
+ * \returns 0 on failure, the filesystem size in bytes otherwise.
+ */
+uint32_t fat16_get_fs_size(const struct fat16_fs_struct* fs)
+{
+    if(!fs)
+        return 0;
+
+    return fs->header.fat_size / 2 * fs->header.cluster_size;
+}
+
+/**
+ * \ingroup fat16_fs
+ * Returns the amount of free storage capacity on the filesystem in bytes.
+ *
+ * \note As the FAT16 filesystem is cluster based, this function does not
+ *       return continuous values but multiples of the cluster size.
+ *
+ * \param[in] fs The filesystem on which to operate.
+ * \returns 0 on failure, the free filesystem space in bytes otherwise.
+ */
+uint32_t fat16_get_fs_free(const struct fat16_fs_struct* fs)
+{
+    if(!fs)
+        return 0;
+
+    uint8_t fat[8];
+    struct fat16_usage_count_callback_arg count_arg;
+    count_arg.cluster_count = 0;
+    count_arg.buffer_size = sizeof(fat);
+
+    if(!fs->partition->device_read_interval(fs->header.fat_offset,
+                                            fat,
+                                            sizeof(fat),
+                                            fs->header.fat_size,
+                                            fat16_get_fs_free_callback,
+                                            &count_arg
+                                           )
+      )
+        return 0;
+
+    return (uint32_t) count_arg.cluster_count * fs->header.cluster_size;
+}
+
+/**
+ * \ingroup fat16_fs
+ * Callback function used for counting free clusters.
+ */
+uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p)
+{
+    struct fat16_usage_count_callback_arg* count_arg = (struct fat16_usage_count_callback_arg*) p;
+
+    for(uint8_t i = 0; i < count_arg->buffer_size; i += 2)
+    {
+        if((((uint16_t) buffer[1] << 8) | ((uint16_t) buffer[0] << 0)) == FAT16_CLUSTER_FREE)
+            ++(count_arg->cluster_count);
+
+        buffer += 2;
+    }
+
+    return 1;
+}
+
Index: main.c
===================================================================
--- main.c	(.../sd-reader_release_20060808)	(Revision 106)
+++ main.c	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -45,9 +50,27 @@
  * The software is written in pure standard ANSI-C. Sure, it might not be the
  * smallest or the fastest one, but I think it is quite flexible.
  *
- * I implemented a simple command prompt which is accessible via the UART. With commands
- * similiar to Unix you can browse different directories, read and write files,
- * create new ones and delete them again, and browse different directories.
+ * I implemented a simple command prompt which is accessible via the UART at 9600 Baud. With
+ * commands similiar to the Unix shell you can browse different directories, read and write
+ * files, create new ones and delete them again. Not all commands are available in all
+ * software configurations.
+ * - <tt>cat \<file\></tt>\n
+ *   Writes a hexdump of \<file\> to the terminal.
+ * - <tt>cd \<directory\></tt>\n
+ *   Changes current working directory to \<directory\>.
+ * - <tt>disk</tt>\n
+ *   Shows FAT16 filesystem capacity and free storage.
+ * - <tt>ls</tt>\n
+ *   Shows the content of the current directory.
+ * - <tt>rm \<file\></tt>\n
+ *   Deletes \<file\>.
+ * - <tt>sync</tt>\n
+ *   Ensures all buffered data is written to the card.
+ * - <tt>touch \<file\></tt>\n
+ *   Creates \<file\>.
+ * - <tt>write \<file\> \<offset\></tt>\n
+ *   Writes text to \<file\>, starting from \<offset\>. The text is read
+ *   from the UART, line by line. Finish with an empty line.
  *
  * \htmlonly
  * <p>
@@ -77,12 +100,12 @@
  *     </tr>
  *     <tr>
  *         <td>FAT16 (read-only)</td>
- *         <td align="right">3596</td>
+ *         <td align="right">3888</td>
  *         <td align="right">0</td>
  *     </tr>
  *     <tr>
  *         <td>FAT16 (read-write)</td>
- *         <td align="right">6628</td>
+ *         <td align="right">6920</td>
  *         <td align="right">0</td>
  *     </tr>
  * </table>
@@ -306,6 +329,10 @@
 
             fat16_close_file(fd);
         }
+        else if(strcmp_P(command, PSTR("disk")) == 0)
+        {
+            printf_P(PSTR("disk total: %ld free: %ld\n"), fat16_get_fs_size(fs), fat16_get_fs_free(fs));
+        }
 #if FAT16_WRITE_SUPPORT
         else if(strncmp_P(command, PSTR("rm "), 3) == 0)
         {
@@ -417,19 +444,34 @@
     while(read_length < buffer_length - 1)
     {
         uint8_t c = uart_getc();
-        uart_putc(c);
 
-        if(c != '\n')
+        if(c == 0x08 || c == 0x7f)
         {
-            buffer[read_length] = c;
+            if(read_length < 1)
+                continue;
+
+            --read_length;
+            buffer[read_length] = '\0';
+
+            uart_putc(0x08);
+            uart_putc(' ');
+            uart_putc(0x08);
+
+            continue;
         }
-        else
+
+        uart_putc(c);
+
+        if(c == '\n')
         {
             buffer[read_length] = '\0';
             break;
         }
-        
-        ++read_length;
+        else
+        {
+            buffer[read_length] = c;
+            ++read_length;
+        }
     }
 
     return read_length;
Index: sd_raw.h
===================================================================
--- sd_raw.h	(.../sd-reader_release_20060808)	(Revision 106)
+++ sd_raw.h	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #ifndef SD_RAW_H
 #define SD_RAW_H
 
Index: ChangeLog
===================================================================
--- ChangeLog	(.../sd-reader_release_20060808)	(Revision 106)
+++ ChangeLog	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,11 @@
 
+2006-08-16 sd-reader
+	* Provide FAT16 capacity and usage information.
+	* Implement the backspace key in the mini shell.
+	* Enter idle mode when waiting for uart activity.
+	* Make the Card Select pin MCU dependent as well.
+	* Add mini shell commands to documentation.
+
 2006-08-08 sd-reader
 	* Thanks go to Torsten Seeboth for his ongoing efforts
 	  to test changes, fix regressions and give suggestions.
@@ -20,5 +27,5 @@
 	* Fix speed regressions.
 
 2006-03-16 sd-reader
-	* Initial releaseA.
+	* Initial release.
 
Index: fat16.h
===================================================================
--- fat16.h	(.../sd-reader_release_20060808)	(Revision 106)
+++ fat16.h	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #ifndef FAT16_H
 #define FAT16_H
 
@@ -88,6 +93,9 @@
 
 uint8_t fat16_get_dir_entry_of_path(struct fat16_fs_struct* fs, const char* path, struct fat16_dir_entry_struct* dir_entry);
 
+uint32_t fat16_get_fs_size(const struct fat16_fs_struct* fs);
+uint32_t fat16_get_fs_free(const struct fat16_fs_struct* fs);
+
 /**
  * @}
  */
Index: partition.c
===================================================================
--- partition.c	(.../sd-reader_release_20060808)	(Revision 106)
+++ partition.c	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #include "partition.h"
 
 #include <stdlib.h>
Index: sd_raw_config.h
===================================================================
--- sd_raw_config.h	(.../sd-reader_release_20060808)	(Revision 106)
+++ sd_raw_config.h	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #ifndef SD_RAW_CONFIG_H
 #define SD_RAW_CONFIG_H
 
@@ -43,8 +48,6 @@
 #define SD_RAW_SAVE_RAM 1
 
 /* defines for customisation of sd/mmc port access */
-#define configure_pin_available() DDRC &= ~(1 << DDC4)
-#define configure_pin_locked() DDRC &= ~(1 << DDC5)
 #if defined(__AVR_ATmega8__) || \
     defined(__AVR_ATmega48__) || \
     defined(__AVR_ATmega88__) || \
@@ -53,28 +56,37 @@
     #define configure_pin_sck() DDRB |= (1 << DDB5)
     #define configure_pin_ss() DDRB |= (1 << DDB2)
     #define configure_pin_miso() DDRB &= ~(1 << DDB4)
+
+    #define select_card() PORTB &= ~(1 << PB2)
+    #define unselect_card() PORTB |= (1 << PB2)
 #elif defined(__AVR_ATmega16__) || \
       defined(__AVR_ATmega32__)
     #define configure_pin_mosi() DDRB |= (1 << DDB5)
     #define configure_pin_sck() DDRB |= (1 << DDB7)
     #define configure_pin_ss() DDRB |= (1 << DDB4)
     #define configure_pin_miso() DDRB &= ~(1 << DDB6)
+
+    #define select_card() PORTB &= ~(1 << PB4)
+    #define unselect_card() PORTB |= (1 << PB4)
 #elif defined(__AVR_ATmega64__) || \
       defined(__AVR_ATmega128__)
     #define configure_pin_mosi() DDRB |= (1 << DDB2)
     #define configure_pin_sck() DDRB |= (1 << DDB1)
     #define configure_pin_ss() DDRB |= (1 << DDB0)
     #define configure_pin_miso() DDRB &= ~(1 << DDB3)
+
+    #define select_card() PORTB &= ~(1 << PB0)
+    #define unselect_card() PORTB |= (1 << PB0)
 #else
     #error "no sd/mmc pin mapping available!"
 #endif
 
+#define configure_pin_available() DDRC &= ~(1 << DDC4)
+#define configure_pin_locked() DDRC &= ~(1 << DDC5)
+
 #define get_pin_available() ((PINC >> PC4) & 0x01)
 #define get_pin_locked() ((PINC >> PC5) & 0x01)
 
-#define select_card() PORTB &= ~(1 << PB2)
-#define unselect_card() PORTB |= (1 << PB2)
-
 /**
  * @}
  */
Index: fat16_config.h
===================================================================
--- fat16_config.h	(.../sd-reader_release_20060808)	(Revision 106)
+++ fat16_config.h	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,4 +1,9 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #ifndef FAT16_CONFIG_H
 #define FAT16_CONFIG_G
 
Index: uart.c
===================================================================
--- uart.c	(.../sd-reader_release_20060808)	(Revision 106)
+++ uart.c	(.../sd-reader_release_20060816)	(Revision 106)
@@ -1,7 +1,14 @@
 
+/* This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
 #include <stdio.h>
+#include <avr/interrupt.h>
 #include <avr/io.h>
 #include <avr/sfr_defs.h>
+#include <avr/sleep.h>
 
 #include "uart.h"
 
@@ -18,6 +25,7 @@
 #define UCSRB UCSR0B
 #define RXEN RXEN0
 #define TXEN TXEN0
+#define RXCIE RXCIE0
 
 #define UCSRC UCSR0C
 #define URSEL 
@@ -28,8 +36,27 @@
 #define UCSRC_SELECT (1 << URSEL)
 #endif
 
+#ifndef USART_RXC_vect
+#if defined(UART0_RX_vect)
+#define USART_RXC_vect UART0_RX_vect
+#elif defined(UART_RX_vect)
+#define USART_RXC_vect UART_RX_vect
+#elif defined(USART0_RX_vect)
+#define USART_RXC_vect USART0_RX_vect
+#elif defined(USART_RX_vect)
+#define USART_RXC_vect USART_RX_vect
+#elif defined(USART0_RXC_vect)
+#define USART_RXC_vect USART0_RXC_vect
+#elif defined(USART_RXC_vect)
+#define USART_RXC_vect USART_RXC_vect
+#else
+#error "Uart receive complete interrupt not defined!"
+#endif
+#endif
+
 #define BAUD 9600UL
 #define UBRRVAL (F_CPU/(BAUD*16)-1)
+#define USE_SLEEP 1
 
 static int _uart_putc(char c, FILE* stream);
 static int _uart_getc(FILE* stream);
@@ -44,7 +71,12 @@
     /* set frame format: 8 bit, no parity, 1 bit */
     UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);
     /* enable serial receiver and transmitter */
+#if !USE_SLEEP
     UCSRB = (1 << RXEN) | (1 << TXEN);
+#else
+    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
+    sei();
+#endif
 }
 
 void uart_connect_stdio()
@@ -56,8 +88,10 @@
 {
     if(c == '\n')
         uart_putc('\r');
+
     /* wait until transmit buffer is empty */
-    loop_until_bit_is_set(UCSRA, UDRE);
+    while(!(UCSRA & (1 << UDRE)));
+
     /* send next byte */
     UDR = c;
 }
@@ -86,7 +120,21 @@
 uint8_t uart_getc()
 {
     /* wait until receive buffer is full */
-    loop_until_bit_is_set(UCSRA, RXC);
+#if USE_SLEEP
+    set_sleep_mode(SLEEP_MODE_IDLE);
+    cli();
+    while(!(UCSRA & (1 << RXC)))
+    {
+        sleep_enable();
+        sei();
+        sleep_cpu();
+        cli();
+        sleep_disable();
+    }
+    sei();
+#else
+    while(!(UCSRA & (1 << RXC)));
+#endif
 
     uint8_t b = UDR;
     if(b == '\r')
@@ -100,4 +148,5 @@
     return uart_getc();
 }
 
+EMPTY_INTERRUPT(USART_RXC_vect)
 
