initial commit
This commit is contained in:
@@ -0,0 +1,421 @@
|
||||
// Map of Arduino pins to avr bit, ddr, port, pin
|
||||
// Credit Paul Stoffregen for idea
|
||||
#ifndef ArduinoPins_h
|
||||
#define ArduinoPins_h
|
||||
|
||||
#define PIN_BITNUM(pin) (PIN##pin##_BITNUM)
|
||||
#define PIN_PORTREG(pin) (PIN##pin##_PORTREG)
|
||||
#define PIN_DDRREG(pin) (PIN##pin##_DDRREG)
|
||||
#define PIN_PINREG(pin) (PIN##pin##_PINREG)
|
||||
#ifndef _BV
|
||||
#define _BV(n) (1 << (n))
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
// Mega Arduino
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
#define SDA_PIN 20
|
||||
#define SCL_PIN 21
|
||||
|
||||
// SPI port
|
||||
#define SS_PIN 53
|
||||
#define MOSI_PIN 51
|
||||
#define MISO_PIN 50
|
||||
#define SCK_PIN 52
|
||||
|
||||
// bit number for all digital pins
|
||||
#define PIN0_BITNUM 0
|
||||
#define PIN1_BITNUM 1
|
||||
#define PIN2_BITNUM 4
|
||||
#define PIN3_BITNUM 5
|
||||
#define PIN4_BITNUM 5
|
||||
#define PIN5_BITNUM 3
|
||||
#define PIN6_BITNUM 3
|
||||
#define PIN7_BITNUM 4
|
||||
#define PIN8_BITNUM 5
|
||||
#define PIN9_BITNUM 6
|
||||
#define PIN10_BITNUM 4
|
||||
#define PIN11_BITNUM 5
|
||||
#define PIN12_BITNUM 6
|
||||
#define PIN13_BITNUM 7
|
||||
#define PIN14_BITNUM 1
|
||||
#define PIN15_BITNUM 0
|
||||
#define PIN16_BITNUM 1
|
||||
#define PIN17_BITNUM 0
|
||||
#define PIN18_BITNUM 3
|
||||
#define PIN19_BITNUM 2
|
||||
#define PIN20_BITNUM 1
|
||||
#define PIN21_BITNUM 0
|
||||
#define PIN22_BITNUM 0
|
||||
#define PIN23_BITNUM 1
|
||||
#define PIN24_BITNUM 2
|
||||
#define PIN25_BITNUM 3
|
||||
#define PIN26_BITNUM 4
|
||||
#define PIN27_BITNUM 5
|
||||
#define PIN28_BITNUM 6
|
||||
#define PIN29_BITNUM 7
|
||||
#define PIN30_BITNUM 7
|
||||
#define PIN31_BITNUM 6
|
||||
#define PIN32_BITNUM 5
|
||||
#define PIN33_BITNUM 4
|
||||
#define PIN34_BITNUM 3
|
||||
#define PIN35_BITNUM 2
|
||||
#define PIN36_BITNUM 1
|
||||
#define PIN37_BITNUM 0
|
||||
#define PIN38_BITNUM 7
|
||||
#define PIN39_BITNUM 2
|
||||
#define PIN40_BITNUM 1
|
||||
#define PIN41_BITNUM 0
|
||||
#define PIN42_BITNUM 7
|
||||
#define PIN43_BITNUM 6
|
||||
#define PIN44_BITNUM 5
|
||||
#define PIN45_BITNUM 4
|
||||
#define PIN46_BITNUM 3
|
||||
#define PIN47_BITNUM 2
|
||||
#define PIN48_BITNUM 1
|
||||
#define PIN49_BITNUM 0
|
||||
#define PIN50_BITNUM 3
|
||||
#define PIN51_BITNUM 2
|
||||
#define PIN52_BITNUM 1
|
||||
#define PIN53_BITNUM 0
|
||||
#define PIN54_BITNUM 0
|
||||
#define PIN55_BITNUM 1
|
||||
#define PIN56_BITNUM 2
|
||||
#define PIN57_BITNUM 3
|
||||
#define PIN58_BITNUM 4
|
||||
#define PIN59_BITNUM 5
|
||||
#define PIN60_BITNUM 6
|
||||
#define PIN61_BITNUM 7
|
||||
#define PIN62_BITNUM 0
|
||||
#define PIN63_BITNUM 1
|
||||
#define PIN64_BITNUM 2
|
||||
#define PIN65_BITNUM 3
|
||||
#define PIN66_BITNUM 4
|
||||
#define PIN67_BITNUM 5
|
||||
#define PIN68_BITNUM 6
|
||||
#define PIN69_BITNUM 7
|
||||
|
||||
// output register for digital pins
|
||||
#define PIN0_PORTREG PORTE
|
||||
#define PIN1_PORTREG PORTE
|
||||
#define PIN2_PORTREG PORTE
|
||||
#define PIN3_PORTREG PORTE
|
||||
#define PIN4_PORTREG PORTG
|
||||
#define PIN5_PORTREG PORTE
|
||||
#define PIN6_PORTREG PORTH
|
||||
#define PIN7_PORTREG PORTH
|
||||
#define PIN8_PORTREG PORTH
|
||||
#define PIN9_PORTREG PORTH
|
||||
#define PIN10_PORTREG PORTB
|
||||
#define PIN11_PORTREG PORTB
|
||||
#define PIN12_PORTREG PORTB
|
||||
#define PIN13_PORTREG PORTB
|
||||
#define PIN14_PORTREG PORTJ
|
||||
#define PIN15_PORTREG PORTJ
|
||||
#define PIN16_PORTREG PORTH
|
||||
#define PIN17_PORTREG PORTH
|
||||
#define PIN18_PORTREG PORTD
|
||||
#define PIN19_PORTREG PORTD
|
||||
#define PIN20_PORTREG PORTD
|
||||
#define PIN21_PORTREG PORTD
|
||||
#define PIN22_PORTREG PORTA
|
||||
#define PIN23_PORTREG PORTA
|
||||
#define PIN24_PORTREG PORTA
|
||||
#define PIN25_PORTREG PORTA
|
||||
#define PIN26_PORTREG PORTA
|
||||
#define PIN27_PORTREG PORTA
|
||||
#define PIN28_PORTREG PORTA
|
||||
#define PIN29_PORTREG PORTA
|
||||
#define PIN30_PORTREG PORTC
|
||||
#define PIN31_PORTREG PORTC
|
||||
#define PIN32_PORTREG PORTC
|
||||
#define PIN33_PORTREG PORTC
|
||||
#define PIN34_PORTREG PORTC
|
||||
#define PIN35_PORTREG PORTC
|
||||
#define PIN36_PORTREG PORTC
|
||||
#define PIN37_PORTREG PORTC
|
||||
#define PIN38_PORTREG PORTD
|
||||
#define PIN39_PORTREG PORTG
|
||||
#define PIN40_PORTREG PORTG
|
||||
#define PIN41_PORTREG PORTG
|
||||
#define PIN42_PORTREG PORTL
|
||||
#define PIN43_PORTREG PORTL
|
||||
#define PIN44_PORTREG PORTL
|
||||
#define PIN45_PORTREG PORTL
|
||||
#define PIN46_PORTREG PORTL
|
||||
#define PIN47_PORTREG PORTL
|
||||
#define PIN48_PORTREG PORTL
|
||||
#define PIN49_PORTREG PORTL
|
||||
#define PIN50_PORTREG PORTB
|
||||
#define PIN51_PORTREG PORTB
|
||||
#define PIN52_PORTREG PORTB
|
||||
#define PIN53_PORTREG PORTB
|
||||
#define PIN54_PORTREG PORTF
|
||||
#define PIN55_PORTREG PORTF
|
||||
#define PIN56_PORTREG PORTF
|
||||
#define PIN57_PORTREG PORTF
|
||||
#define PIN58_PORTREG PORTF
|
||||
#define PIN59_PORTREG PORTF
|
||||
#define PIN60_PORTREG PORTF
|
||||
#define PIN61_PORTREG PORTF
|
||||
#define PIN62_PORTREG PORTK
|
||||
#define PIN63_PORTREG PORTK
|
||||
#define PIN64_PORTREG PORTK
|
||||
#define PIN65_PORTREG PORTK
|
||||
#define PIN66_PORTREG PORTK
|
||||
#define PIN67_PORTREG PORTK
|
||||
#define PIN68_PORTREG PORTK
|
||||
#define PIN69_PORTREG PORTK
|
||||
|
||||
// direction control register for digital pins
|
||||
#define PIN0_DDRREG DDRE
|
||||
#define PIN1_DDRREG DDRE
|
||||
#define PIN2_DDRREG DDRE
|
||||
#define PIN3_DDRREG DDRE
|
||||
#define PIN4_DDRREG DDRG
|
||||
#define PIN5_DDRREG DDRE
|
||||
#define PIN6_DDRREG DDRH
|
||||
#define PIN7_DDRREG DDRH
|
||||
#define PIN8_DDRREG DDRH
|
||||
#define PIN9_DDRREG DDRH
|
||||
#define PIN10_DDRREG DDRB
|
||||
#define PIN11_DDRREG DDRB
|
||||
#define PIN12_DDRREG DDRB
|
||||
#define PIN13_DDRREG DDRB
|
||||
#define PIN14_DDRREG DDRJ
|
||||
#define PIN15_DDRREG DDRJ
|
||||
#define PIN16_DDRREG DDRH
|
||||
#define PIN17_DDRREG DDRH
|
||||
#define PIN18_DDRREG DDRD
|
||||
#define PIN19_DDRREG DDRD
|
||||
#define PIN20_DDRREG DDRD
|
||||
#define PIN21_DDRREG DDRD
|
||||
#define PIN22_DDRREG DDRA
|
||||
#define PIN23_DDRREG DDRA
|
||||
#define PIN24_DDRREG DDRA
|
||||
#define PIN25_DDRREG DDRA
|
||||
#define PIN26_DDRREG DDRA
|
||||
#define PIN27_DDRREG DDRA
|
||||
#define PIN28_DDRREG DDRA
|
||||
#define PIN29_DDRREG DDRA
|
||||
#define PIN30_DDRREG DDRC
|
||||
#define PIN31_DDRREG DDRC
|
||||
#define PIN32_DDRREG DDRC
|
||||
#define PIN33_DDRREG DDRC
|
||||
#define PIN34_DDRREG DDRC
|
||||
#define PIN35_DDRREG DDRC
|
||||
#define PIN36_DDRREG DDRC
|
||||
#define PIN37_DDRREG DDRC
|
||||
#define PIN38_DDRREG DDRD
|
||||
#define PIN39_DDRREG DDRG
|
||||
#define PIN40_DDRREG DDRG
|
||||
#define PIN41_DDRREG DDRG
|
||||
#define PIN42_DDRREG DDRL
|
||||
#define PIN43_DDRREG DDRL
|
||||
#define PIN44_DDRREG DDRL
|
||||
#define PIN45_DDRREG DDRL
|
||||
#define PIN46_DDRREG DDRL
|
||||
#define PIN47_DDRREG DDRL
|
||||
#define PIN48_DDRREG DDRL
|
||||
#define PIN49_DDRREG DDRL
|
||||
#define PIN50_DDRREG DDRB
|
||||
#define PIN51_DDRREG DDRB
|
||||
#define PIN52_DDRREG DDRB
|
||||
#define PIN53_DDRREG DDRB
|
||||
#define PIN54_DDRREG DDRF
|
||||
#define PIN55_DDRREG DDRF
|
||||
#define PIN56_DDRREG DDRF
|
||||
#define PIN57_DDRREG DDRF
|
||||
#define PIN58_DDRREG DDRF
|
||||
#define PIN59_DDRREG DDRF
|
||||
#define PIN60_DDRREG DDRF
|
||||
#define PIN61_DDRREG DDRF
|
||||
#define PIN62_DDRREG DDRK
|
||||
#define PIN63_DDRREG DDRK
|
||||
#define PIN64_DDRREG DDRK
|
||||
#define PIN65_DDRREG DDRK
|
||||
#define PIN66_DDRREG DDRK
|
||||
#define PIN67_DDRREG DDRK
|
||||
#define PIN68_DDRREG DDRK
|
||||
#define PIN69_DDRREG DDRK
|
||||
|
||||
// input register for digital pins
|
||||
#define PIN0_PINREG PINE
|
||||
#define PIN1_PINREG PINE
|
||||
#define PIN2_PINREG PINE
|
||||
#define PIN3_PINREG PINE
|
||||
#define PIN4_PINREG PING
|
||||
#define PIN5_PINREG PINE
|
||||
#define PIN6_PINREG PINH
|
||||
#define PIN7_PINREG PINH
|
||||
#define PIN8_PINREG PINH
|
||||
#define PIN9_PINREG PINH
|
||||
#define PIN10_PINREG PINB
|
||||
#define PIN11_PINREG PINB
|
||||
#define PIN12_PINREG PINB
|
||||
#define PIN13_PINREG PINB
|
||||
#define PIN14_PINREG PINJ
|
||||
#define PIN15_PINREG PINJ
|
||||
#define PIN16_PINREG PINH
|
||||
#define PIN17_PINREG PINH
|
||||
#define PIN18_PINREG PIND
|
||||
#define PIN19_PINREG PIND
|
||||
#define PIN20_PINREG PIND
|
||||
#define PIN21_PINREG PIND
|
||||
#define PIN22_PINREG PINA
|
||||
#define PIN23_PINREG PINA
|
||||
#define PIN24_PINREG PINA
|
||||
#define PIN25_PINREG PINA
|
||||
#define PIN26_PINREG PINA
|
||||
#define PIN27_PINREG PINA
|
||||
#define PIN28_PINREG PINA
|
||||
#define PIN29_PINREG PINA
|
||||
#define PIN30_PINREG PINC
|
||||
#define PIN31_PINREG PINC
|
||||
#define PIN32_PINREG PINC
|
||||
#define PIN33_PINREG PINC
|
||||
#define PIN34_PINREG PINC
|
||||
#define PIN35_PINREG PINC
|
||||
#define PIN36_PINREG PINC
|
||||
#define PIN37_PINREG PINC
|
||||
#define PIN38_PINREG PIND
|
||||
#define PIN39_PINREG PING
|
||||
#define PIN40_PINREG PING
|
||||
#define PIN41_PINREG PING
|
||||
#define PIN42_PINREG PINL
|
||||
#define PIN43_PINREG PINL
|
||||
#define PIN44_PINREG PINL
|
||||
#define PIN45_PINREG PINL
|
||||
#define PIN46_PINREG PINL
|
||||
#define PIN47_PINREG PINL
|
||||
#define PIN48_PINREG PINL
|
||||
#define PIN49_PINREG PINL
|
||||
#define PIN50_PINREG PINB
|
||||
#define PIN51_PINREG PINB
|
||||
#define PIN52_PINREG PINB
|
||||
#define PIN53_PINREG PINB
|
||||
#define PIN54_PINREG PINF
|
||||
#define PIN55_PINREG PINF
|
||||
#define PIN56_PINREG PINF
|
||||
#define PIN57_PINREG PINF
|
||||
#define PIN58_PINREG PINF
|
||||
#define PIN59_PINREG PINF
|
||||
#define PIN60_PINREG PINF
|
||||
#define PIN61_PINREG PINF
|
||||
#define PIN62_PINREG PINK
|
||||
#define PIN63_PINREG PINK
|
||||
#define PIN64_PINREG PINK
|
||||
#define PIN65_PINREG PINK
|
||||
#define PIN66_PINREG PINK
|
||||
#define PIN67_PINREG PINK
|
||||
#define PIN68_PINREG PINK
|
||||
#define PIN69_PINREG PINK
|
||||
|
||||
#elif defined(__AVR_ATmega644P__)
|
||||
// Sanguino
|
||||
|
||||
#error Sanguino not defined
|
||||
|
||||
#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
// 168 and 328 Arduinos
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
#define SDA_PIN 18
|
||||
#define SCL_PIN 19
|
||||
|
||||
// SPI port
|
||||
#define SS_PIN 10
|
||||
#define MOSI_PIN 11
|
||||
#define MISO_PIN 12
|
||||
#define SCK_PIN 13
|
||||
|
||||
// bit number for digital pins
|
||||
#define PIN0_BITNUM 0
|
||||
#define PIN1_BITNUM 1
|
||||
#define PIN2_BITNUM 2
|
||||
#define PIN3_BITNUM 3
|
||||
#define PIN4_BITNUM 4
|
||||
#define PIN5_BITNUM 5
|
||||
#define PIN6_BITNUM 6
|
||||
#define PIN7_BITNUM 7
|
||||
#define PIN8_BITNUM 0
|
||||
#define PIN9_BITNUM 1
|
||||
#define PIN10_BITNUM 2
|
||||
#define PIN11_BITNUM 3
|
||||
#define PIN12_BITNUM 4
|
||||
#define PIN13_BITNUM 5
|
||||
#define PIN14_BITNUM 0
|
||||
#define PIN15_BITNUM 1
|
||||
#define PIN16_BITNUM 2
|
||||
#define PIN17_BITNUM 3
|
||||
#define PIN18_BITNUM 4
|
||||
#define PIN19_BITNUM 5
|
||||
|
||||
// output register for all pins
|
||||
#define PIN0_PORTREG PORTD
|
||||
#define PIN1_PORTREG PORTD
|
||||
#define PIN2_PORTREG PORTD
|
||||
#define PIN3_PORTREG PORTD
|
||||
#define PIN4_PORTREG PORTD
|
||||
#define PIN5_PORTREG PORTD
|
||||
#define PIN6_PORTREG PORTD
|
||||
#define PIN7_PORTREG PORTD
|
||||
#define PIN8_PORTREG PORTB
|
||||
#define PIN9_PORTREG PORTB
|
||||
#define PIN10_PORTREG PORTB
|
||||
#define PIN11_PORTREG PORTB
|
||||
#define PIN12_PORTREG PORTB
|
||||
#define PIN13_PORTREG PORTB
|
||||
#define PIN14_PORTREG PORTC
|
||||
#define PIN15_PORTREG PORTC
|
||||
#define PIN16_PORTREG PORTC
|
||||
#define PIN17_PORTREG PORTC
|
||||
#define PIN18_PORTREG PORTC
|
||||
#define PIN19_PORTREG PORTC
|
||||
|
||||
// direction control register for digital pins
|
||||
#define PIN0_DDRREG DDRD
|
||||
#define PIN1_DDRREG DDRD
|
||||
#define PIN2_DDRREG DDRD
|
||||
#define PIN3_DDRREG DDRD
|
||||
#define PIN4_DDRREG DDRD
|
||||
#define PIN5_DDRREG DDRD
|
||||
#define PIN6_DDRREG DDRD
|
||||
#define PIN7_DDRREG DDRD
|
||||
#define PIN8_DDRREG DDRB
|
||||
#define PIN9_DDRREG DDRB
|
||||
#define PIN10_DDRREG DDRB
|
||||
#define PIN11_DDRREG DDRB
|
||||
#define PIN12_DDRREG DDRB
|
||||
#define PIN13_DDRREG DDRB
|
||||
#define PIN14_DDRREG DDRC
|
||||
#define PIN15_DDRREG DDRC
|
||||
#define PIN16_DDRREG DDRC
|
||||
#define PIN17_DDRREG DDRC
|
||||
#define PIN18_DDRREG DDRC
|
||||
#define PIN19_DDRREG DDRC
|
||||
|
||||
// input register for digital pins
|
||||
#define PIN0_PINREG PIND
|
||||
#define PIN1_PINREG PIND
|
||||
#define PIN2_PINREG PIND
|
||||
#define PIN3_PINREG PIND
|
||||
#define PIN4_PINREG PIND
|
||||
#define PIN5_PINREG PIND
|
||||
#define PIN6_PINREG PIND
|
||||
#define PIN7_PINREG PIND
|
||||
#define PIN8_PINREG PINB
|
||||
#define PIN9_PINREG PINB
|
||||
#define PIN10_PINREG PINB
|
||||
#define PIN11_PINREG PINB
|
||||
#define PIN12_PINREG PINB
|
||||
#define PIN13_PINREG PINB
|
||||
#define PIN14_PINREG PINC
|
||||
#define PIN15_PINREG PINC
|
||||
#define PIN16_PINREG PINC
|
||||
#define PIN17_PINREG PINC
|
||||
#define PIN18_PINREG PINC
|
||||
#define PIN19_PINREG PINC
|
||||
#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
#endif // ArduinoPins_h
|
||||
@@ -0,0 +1,488 @@
|
||||
/* Arduino FatReader Library
|
||||
* Copyright (C) 2009 by William Greiman
|
||||
*
|
||||
* This file is part of the Arduino FatReader Library
|
||||
*
|
||||
* This Library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the Arduino FatReader Library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <string.h>
|
||||
#if ARDUINO < 100
|
||||
#include <WProgram.h>
|
||||
#else // ARDUINO
|
||||
#include <Arduino.h>
|
||||
#endif // ARDUINO
|
||||
#include <FatReader.h>
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Format the name field of the dir_t struct \a dir into the 13 byte array
|
||||
* \a name in the standard 8.3 short name format.
|
||||
*/
|
||||
void dirName(dir_t &dir, char name[]) {
|
||||
uint8_t j = 0;
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
if (dir.name[i] == ' ')
|
||||
continue;
|
||||
if (i == 8)
|
||||
name[j++] = '.';
|
||||
name[j++] = dir.name[i];
|
||||
}
|
||||
name[j] = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Print the name field of a dir_t structure in 8.3 format.
|
||||
* Append a '/' if it is a subdirectory.
|
||||
*
|
||||
*/
|
||||
void printEntryName(dir_t &dir) {
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
if (dir.name[i] == ' ')
|
||||
continue;
|
||||
if (i == 8)
|
||||
Serial.write('.');
|
||||
Serial.write(dir.name[i]);
|
||||
}
|
||||
if (DIR_IS_SUBDIR(dir)) {
|
||||
// indicate subdirectory
|
||||
Serial.write('/');
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief list file in a directory
|
||||
@param flags file flags
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void FatReader::ls(uint8_t flags) {
|
||||
dir_t d;
|
||||
if (isDir())
|
||||
lsR(d, flags, 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// recursive part of ls()
|
||||
void FatReader::lsR(dir_t &d, uint8_t flags, uint8_t indent) {
|
||||
while (readDir(d) > 0) {
|
||||
|
||||
// print any indent spaces
|
||||
for (int8_t i = 0; i < indent; i++) {
|
||||
Serial.write(' ');
|
||||
}
|
||||
printEntryName(d);
|
||||
|
||||
if (DIR_IS_SUBDIR(d)) {
|
||||
Serial.println();
|
||||
// recursive call if LS_R
|
||||
if (flags & LS_R) {
|
||||
FatReader s;
|
||||
if (s.open(*vol_, d)) {
|
||||
s.lsR(d, flags, indent + 2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (flags & LS_FLAG_FRAGMENTED) {
|
||||
uint32_t c = (uint32_t)d.firstClusterHigh << 16;
|
||||
c |= d.firstClusterLow;
|
||||
|
||||
// fragmented if has clusters and not contiguous
|
||||
char f = c && !vol_->chainIsContiguous(c) ? '*' : ' ';
|
||||
Serial.write(' ');
|
||||
Serial.write(f);
|
||||
}
|
||||
if (flags & LS_SIZE) {
|
||||
Serial.write(' ');
|
||||
Serial.print(d.fileSize);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** return the next cluster in a chain */
|
||||
uint32_t FatVolume::nextCluster(uint32_t cluster) {
|
||||
if (!validCluster(cluster)) {
|
||||
return 0;
|
||||
}
|
||||
if (fatType_ == 32) {
|
||||
uint32_t next;
|
||||
uint32_t block = fatStartBlock_ + (cluster >> 7);
|
||||
uint16_t offset = 0X1FF & (cluster << 2);
|
||||
if (!rawRead(block, offset, (uint8_t *)&next, 4)) {
|
||||
return 0;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
if (fatType_ == 16) {
|
||||
uint16_t next;
|
||||
uint32_t block = fatStartBlock_ + (cluster >> 8);
|
||||
uint16_t offset = 0X1FF & (cluster << 1);
|
||||
if (!rawRead(block, offset, (uint8_t *)&next, 2)) {
|
||||
return 0;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Open a file or subdirectory by index.
|
||||
*
|
||||
* \param[in] dir An open FatReader instance for the directory.
|
||||
*
|
||||
* \param[in] index The \a index for a file or subdirectory in the
|
||||
* directory \a dir. \a index is the byte offset divided by 32 of
|
||||
* the directory entry for the file or subdirectory.
|
||||
*
|
||||
* To determine the index for a file open it by name. The index for the
|
||||
* file is then is: (dir.readPosition()/32 -1)
|
||||
*
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
* Reasons for failure include the FAT volume has not been initialized, \a dir
|
||||
* is not a directory, \a name is invalid, the file or subdirectory does not
|
||||
* exist, or an I/O error occurred.
|
||||
*/
|
||||
uint8_t FatReader::open(FatReader &dir, uint16_t index) {
|
||||
dir_t d;
|
||||
|
||||
// position directory file to entry
|
||||
if (!dir.seekSet(32UL * index))
|
||||
return false;
|
||||
|
||||
// read entry
|
||||
if (dir.read(&d, 32) != 32)
|
||||
return false;
|
||||
|
||||
// must be a real file or directory
|
||||
if (!DIR_IS_FILE_OR_SUBDIR(d) || d.name[0] == DIR_NAME_FREE ||
|
||||
d.name[0] == DIR_NAME_DELETED) {
|
||||
return false;
|
||||
}
|
||||
return open(*dir.volume(), d);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Open a file or subdirectory by name.
|
||||
*
|
||||
* \note The file or subdirectory, \a name, must be in the specified
|
||||
* directory, \a dir, and must have a DOS 8.3 name.
|
||||
*
|
||||
* \param[in] dir An open FatReader instance for the directory.
|
||||
*
|
||||
* \param[in] name A valid 8.3 DOS name for a file or subdirectory in the
|
||||
* directory \a dir.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
* Reasons for failure include the FAT volume has not been initialized, \a dir
|
||||
* is not a directory, \a name is invalid, the file or subdirectory does not
|
||||
* exist, or an I/O error occurred.
|
||||
*/
|
||||
uint8_t FatReader::open(FatReader &dir, char *name) {
|
||||
dir_t entry;
|
||||
char dname[13];
|
||||
|
||||
dir.rewind();
|
||||
while (dir.readDir(entry) > 0) {
|
||||
dirName(entry, dname);
|
||||
if (strcasecmp(dname, name))
|
||||
continue;
|
||||
return open(*(dir.vol_), entry);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Open a file or subdirectory by directory structure.
|
||||
*
|
||||
* \param[in] vol The FAT volume that contains the file or subdirectory.
|
||||
*
|
||||
* \param[in] dir The directory structure describing the file or subdirectory.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
* Reasons for failure include the FAT volume, \a vol, has not been initialized,
|
||||
* \a vol is a FAT12 volume or \a dir is not a valid directory entry.
|
||||
*/
|
||||
uint8_t FatReader::open(FatVolume &vol, dir_t &dir) {
|
||||
if (vol.fatType() < 16)
|
||||
return false;
|
||||
if (dir.name[0] == 0 || dir.name[0] == DIR_NAME_DELETED) {
|
||||
return false;
|
||||
}
|
||||
firstCluster_ = (uint32_t)dir.firstClusterHigh << 16;
|
||||
firstCluster_ |= dir.firstClusterLow;
|
||||
if (DIR_IS_FILE(dir)) {
|
||||
type_ = FILE_TYPE_NORMAL;
|
||||
fileSize_ = dir.fileSize;
|
||||
} else if (DIR_IS_SUBDIR(dir)) {
|
||||
type_ = FILE_TYPE_SUBDIR;
|
||||
fileSize_ = vol.chainSize(firstCluster_);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
vol_ = &vol;
|
||||
rewind();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Open a volume's root directory.
|
||||
*
|
||||
* \param[in] vol The FAT volume containing the root directory to be opened.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
* Reasons for failure include the FAT volume has not been initialized
|
||||
* or it a FAT12 volume.
|
||||
*/
|
||||
uint8_t FatReader::openRoot(FatVolume &vol) {
|
||||
if (vol.fatType() == 16) {
|
||||
type_ = FILE_TYPE_ROOT16;
|
||||
firstCluster_ = 0;
|
||||
fileSize_ = 32 * vol.rootDirEntryCount();
|
||||
} else if (vol.fatType() == 32) {
|
||||
type_ = FILE_TYPE_ROOT32;
|
||||
firstCluster_ = vol.rootDirStart();
|
||||
fileSize_ = vol.chainSize(firstCluster_);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
vol_ = &vol;
|
||||
rewind();
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Check for a contiguous file and enable optimized reads if the
|
||||
* file is contiguous.
|
||||
*/
|
||||
void FatReader::optimizeContiguous(void) {
|
||||
if (isOpen() && firstCluster_) {
|
||||
if (vol_->chainIsContiguous(firstCluster_)) {
|
||||
type_ |= FILE_IS_CONTIGUOUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Read data from a file at starting at the current read position.
|
||||
*
|
||||
* \param[out] buf Pointer to the location that will receive the data.
|
||||
*
|
||||
* \param[in] count Maximum number of bytes to read.
|
||||
*
|
||||
* \return For success read() returns the number of bytes read.
|
||||
* A value less than \a count, including zero, will be returned
|
||||
* if end of file is reached.
|
||||
* If an error occurs, read() returns -1. Possible errors include
|
||||
* read() called before a file has been opened, corrupt file system
|
||||
* or an I/O error occurred.
|
||||
*/
|
||||
int16_t FatReader::read(void *buf, uint16_t count) {
|
||||
uint8_t *dst = (uint8_t *)buf;
|
||||
uint16_t nr = 0;
|
||||
int16_t n = 0;
|
||||
while (nr < count && (n = readBlockData(dst, count - nr)) > 0) {
|
||||
if (!seekCur(n))
|
||||
return -1;
|
||||
dst += n;
|
||||
nr += n;
|
||||
}
|
||||
return n < 0 ? -1 : nr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// read maximum amount possible from current physical block
|
||||
int16_t FatReader::readBlockData(uint8_t *dst, uint16_t count) {
|
||||
uint32_t block;
|
||||
uint16_t offset = readPosition_ & 0X1FF;
|
||||
if (count > (512 - offset))
|
||||
count = 512 - offset;
|
||||
if (count > (fileSize_ - readPosition_))
|
||||
count = fileSize_ - readPosition_;
|
||||
if (fileType() == FILE_TYPE_ROOT16) {
|
||||
block = vol_->rootDirStart() + (readPosition_ >> 9);
|
||||
} else {
|
||||
uint8_t bpc = vol_->blocksPerCluster();
|
||||
block = vol_->dataStartBlock() + (readCluster_ - 2) * bpc +
|
||||
((readPosition_ >> 9) & (bpc - 1));
|
||||
}
|
||||
return vol_->rawRead(block, offset, dst, count) ? count : -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Read the next directory entry from a directory file.
|
||||
*
|
||||
* \param[out] dir The dir_t struct that will receive the data.
|
||||
*
|
||||
* \return For success readDir() returns the number of bytes read.
|
||||
* A value of zero will be returned if end of file is reached.
|
||||
* If an error occurs, readDir() returns -1. Possible errors include
|
||||
* readDir() called before a directory has been opened, this is not
|
||||
* a directory file or an I/O error occurred.
|
||||
*/
|
||||
int8_t FatReader::readDir(dir_t &dir) {
|
||||
int8_t n;
|
||||
// if not a directory file return an error
|
||||
if (!isDir())
|
||||
return -1;
|
||||
while ((n = read((uint8_t *)&dir, sizeof(dir_t))) == sizeof(dir_t) &&
|
||||
dir.name[0] != DIR_NAME_FREE) {
|
||||
if (dir.name[0] == DIR_NAME_DELETED || dir.name[0] == '.')
|
||||
continue;
|
||||
if (DIR_IS_FILE(dir) || DIR_IS_SUBDIR(dir))
|
||||
return n;
|
||||
}
|
||||
return n < 0 ? n : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set read position to start of file */
|
||||
void FatReader::rewind(void) {
|
||||
readCluster_ = firstCluster_;
|
||||
readPosition_ = 0;
|
||||
}
|
||||
/**
|
||||
* Set the read position for a file or directory to the current position plus
|
||||
* \a offset.
|
||||
*
|
||||
* \param[in] offset The amount to advance the read position.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
uint8_t FatReader::seekCur(uint32_t offset) {
|
||||
|
||||
uint32_t newPos = readPosition_ + offset;
|
||||
|
||||
// can't position beyond end of file
|
||||
if (newPos > fileSize_)
|
||||
return false;
|
||||
|
||||
// number of clusters forward
|
||||
uint32_t nc = (newPos >> 9) / vol_->blocksPerCluster() -
|
||||
(readPosition_ >> 9) / vol_->blocksPerCluster();
|
||||
|
||||
// set new position - only corrupt file system can cause error now
|
||||
readPosition_ = newPos;
|
||||
|
||||
// no clusters if FAT16 root
|
||||
if (fileType() == FILE_TYPE_ROOT16)
|
||||
return true;
|
||||
|
||||
// don't need to read FAT if contiguous
|
||||
if (isContiguous()) {
|
||||
readCluster_ += nc;
|
||||
return true;
|
||||
}
|
||||
|
||||
// read FAT chain while nc != 0
|
||||
while (nc-- != 0) {
|
||||
if (!(readCluster_ = vol_->nextCluster(readCluster_))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** check for contiguous chain */
|
||||
uint8_t FatVolume::chainIsContiguous(uint32_t cluster) {
|
||||
uint32_t next;
|
||||
while ((next = nextCluster(cluster))) {
|
||||
if (next != (cluster + 1)) {
|
||||
return isEOC(next);
|
||||
}
|
||||
cluster = next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** return the number of bytes in a cluster chain */
|
||||
uint32_t FatVolume::chainSize(uint32_t cluster) {
|
||||
uint32_t size = 0;
|
||||
while ((cluster = nextCluster(cluster))) {
|
||||
size += 512 * blocksPerCluster_;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Initialize a FAT volume.
|
||||
*
|
||||
* \param[in] dev The SD card where the volume is located.
|
||||
*
|
||||
* \param[in] part The partition to be used. Legal values for \a part are
|
||||
* 1-4 to use the corresponding partition on a device formatted with
|
||||
* a MBR, Master Boot Record, or zero if the device is formatted as
|
||||
* a super floppy with the FAT boot sector in block zero.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure. Reasons for
|
||||
* failure include not finding a valid partition, not finding a valid
|
||||
* FAT file system in the specified partition or an I/O error.
|
||||
*/
|
||||
uint8_t FatVolume::init(SdReader &dev, uint8_t part) {
|
||||
uint8_t buf[BPB_COUNT];
|
||||
uint32_t volumeStartBlock = 0;
|
||||
rawDevice_ = &dev;
|
||||
// if part == 0 assume super floppy with FAT boot sector in block zero
|
||||
// if part > 0 assume mbr volume with partition table
|
||||
if (part) {
|
||||
if (part > 4)
|
||||
return false;
|
||||
|
||||
if (!rawRead(volumeStartBlock, PART_OFFSET + 16 * (part - 1), buf, 16)) {
|
||||
return false;
|
||||
}
|
||||
part_t *part = (part_t *)buf;
|
||||
if ((part->boot & 0X7F) != 0 || part->totalSectors < 100 ||
|
||||
part->firstSector == 0) {
|
||||
// not a valid partition
|
||||
return false;
|
||||
}
|
||||
volumeStartBlock = part->firstSector;
|
||||
}
|
||||
if (!rawRead(volumeStartBlock, BPB_OFFSET, buf, BPB_COUNT)) {
|
||||
return false;
|
||||
}
|
||||
bpb_t *bpb = (bpb_t *)buf;
|
||||
if (bpb->bytesPerSector != 512 || bpb->fatCount == 0 ||
|
||||
bpb->reservedSectorCount == 0 || bpb->sectorsPerCluster == 0 ||
|
||||
(bpb->sectorsPerCluster & (bpb->sectorsPerCluster - 1)) != 0) {
|
||||
// not valid FAT volume
|
||||
return false;
|
||||
}
|
||||
fatCount_ = bpb->fatCount;
|
||||
blocksPerCluster_ = bpb->sectorsPerCluster;
|
||||
blocksPerFat_ =
|
||||
bpb->sectorsPerFat16 ? bpb->sectorsPerFat16 : bpb->sectorsPerFat32;
|
||||
rootDirEntryCount_ = bpb->rootDirEntryCount;
|
||||
fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount;
|
||||
rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_;
|
||||
dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511) / 512);
|
||||
totalBlocks_ =
|
||||
bpb->totalSectors16 ? bpb->totalSectors16 : bpb->totalSectors32;
|
||||
clusterCount_ = (totalBlocks_ - (dataStartBlock_ - volumeStartBlock)) /
|
||||
bpb->sectorsPerCluster;
|
||||
if (clusterCount_ < 4085) {
|
||||
fatType_ = 12;
|
||||
} else if (clusterCount_ < 65525) {
|
||||
fatType_ = 16;
|
||||
} else {
|
||||
rootDirStart_ = bpb->fat32RootCluster;
|
||||
fatType_ = 32;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/* Arduino FatReader Library
|
||||
* Copyright (C) 2009 by William Greiman
|
||||
*
|
||||
* This file is part of the Arduino FatReader Library
|
||||
*
|
||||
* This Library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the Arduino FatReader Library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef FatReader_h
|
||||
#define FatReader_h
|
||||
#include <FatStructs.h>
|
||||
#include <SdReader.h>
|
||||
|
||||
// flags for ls()
|
||||
/** ls() flag to print modify date */
|
||||
#define LS_FLAG_FRAGMENTED 1
|
||||
/** ls() flag to print file size */
|
||||
#define LS_SIZE 2
|
||||
/** ls() flag for recursive list of subdirectories */
|
||||
#define LS_R 4
|
||||
|
||||
// offsets for structures used in volume init
|
||||
/** Offset to BIOS Parameter Block in FAT Boot Sector */
|
||||
#define BPB_OFFSET 11
|
||||
/** Byte count for part of BIOS Parameter Block to be read by init() */
|
||||
#define BPB_COUNT 37
|
||||
/** offset to partition table in mbr */
|
||||
#define PART_OFFSET (512 - 64 - 2)
|
||||
|
||||
// format dir.name into name[13] as standard 8.3 string
|
||||
void dirName(dir_t &dir, char name[]);
|
||||
// Print name field of dir_t struct in 8.3 format
|
||||
void printEntryName(dir_t &dir);
|
||||
//------------------------------------------------------------------------------
|
||||
/** \class FatVolume
|
||||
* \brief FatVolume provides access to FAT volumes.
|
||||
*/
|
||||
class FatVolume {
|
||||
/** Allow FatReader access to FatVolume private data. */
|
||||
friend class FatReader;
|
||||
uint8_t blocksPerCluster_;
|
||||
uint32_t blocksPerFat_;
|
||||
uint32_t clusterCount_;
|
||||
uint32_t dataStartBlock_;
|
||||
uint8_t fatCount_;
|
||||
uint32_t fatStartBlock_;
|
||||
uint8_t fatType_;
|
||||
SdReader *rawDevice_;
|
||||
uint16_t rootDirEntryCount_;
|
||||
uint32_t rootDirStart_;
|
||||
uint32_t totalBlocks_;
|
||||
uint8_t chainIsContiguous(uint32_t cluster);
|
||||
uint32_t chainSize(uint32_t cluster);
|
||||
uint8_t isEOC(uint32_t cluster) {
|
||||
return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN);
|
||||
}
|
||||
uint32_t nextCluster(uint32_t cluster);
|
||||
uint8_t rawRead(uint32_t block, uint16_t offset, uint8_t *dst,
|
||||
uint16_t count) {
|
||||
return rawDevice_->readData(block, offset, dst, count);
|
||||
}
|
||||
uint8_t validCluster(uint32_t cluster) {
|
||||
return (1 < cluster && cluster < (clusterCount_ + 2));
|
||||
}
|
||||
|
||||
public:
|
||||
/** Create an instance of FatVolume */
|
||||
FatVolume(void) : fatType_(0) {}
|
||||
/**
|
||||
* Initialize a FAT volume. Try partition one first then try super
|
||||
* floppy format.
|
||||
*
|
||||
* \param[in] dev The SdReader where the volume is located.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure. Reasons for
|
||||
* failure include not finding a valid partition, not finding a valid
|
||||
* FAT file system or an I/O error.
|
||||
*/
|
||||
uint8_t init(SdReader &dev) { return init(dev, 1) ? 1 : init(dev, 0); }
|
||||
uint8_t init(SdReader &dev, uint8_t part);
|
||||
|
||||
// inline functions that return volume info
|
||||
/** \return The volume's cluster size in blocks. */
|
||||
uint8_t blocksPerCluster(void) { return blocksPerCluster_; }
|
||||
/** \return The number of blocks in one FAT. */
|
||||
uint32_t blocksPerFat(void) { return blocksPerFat_; }
|
||||
/** \return The total number of clusters in the volume. */
|
||||
uint32_t clusterCount(void) { return clusterCount_; }
|
||||
/** \return The logical block number for the start of file data. */
|
||||
uint32_t dataStartBlock(void) { return dataStartBlock_; }
|
||||
/** \return The number of FAT structures on the volume. */
|
||||
uint8_t fatCount(void) { return fatCount_; }
|
||||
/** \return The logical block number for the start of the first FAT. */
|
||||
uint32_t fatStartBlock(void) { return fatStartBlock_; }
|
||||
/** \return The FAT type of the volume. Values are 12, 16 or 32. */
|
||||
uint8_t fatType(void) { return fatType_; }
|
||||
|
||||
/*!
|
||||
@brief Raw device for this volume
|
||||
@returns the raw device
|
||||
*/
|
||||
SdReader *rawDevice(void) { return rawDevice_; }
|
||||
/** \return The number of entries in the root directory for FAT16 volumes. */
|
||||
uint32_t rootDirEntryCount(void) { return rootDirEntryCount_; }
|
||||
/** \return The logical block number for the start of the root directory
|
||||
on FAT16 volumes or the first cluster number on FAT32 volumes. */
|
||||
uint32_t rootDirStart(void) { return rootDirStart_; }
|
||||
/** \return The total number of blocks in the volume. */
|
||||
uint32_t totalBlocks(void) { return totalBlocks_; }
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/** \class FatReader
|
||||
* \brief FatReader implements a minimal FAT16/FAT32 file reader class.
|
||||
*/
|
||||
class FatReader {
|
||||
// values for type_
|
||||
/** File is contiguous file */
|
||||
#define FILE_IS_CONTIGUOUS 0X08
|
||||
/** File type mask */
|
||||
#define FILE_TYPE_MASK 0X07
|
||||
/** This FatReader has not been opened. */
|
||||
#define FILE_TYPE_CLOSED 0X00
|
||||
/** FatReader for a file */
|
||||
#define FILE_TYPE_NORMAL 0X01
|
||||
/** FatReader for a FAT16 root directory */
|
||||
#define FILE_TYPE_ROOT16 0X02
|
||||
/** FatReader for a FAT32 root directory */
|
||||
#define FILE_TYPE_ROOT32 0X03
|
||||
/** FatReader for a subdirectory */
|
||||
#define FILE_TYPE_SUBDIR 0X04
|
||||
/** Test value for directory type */
|
||||
#define FILE_TYPE_MIN_DIR FILE_TYPE_ROOT16
|
||||
uint8_t type_;
|
||||
uint32_t fileSize_;
|
||||
uint32_t readCluster_;
|
||||
uint32_t readPosition_;
|
||||
uint32_t firstCluster_;
|
||||
FatVolume *vol_;
|
||||
int16_t readBlockData(uint8_t *dst, uint16_t count);
|
||||
void lsR(dir_t &d, uint8_t flags, uint8_t indent);
|
||||
|
||||
public:
|
||||
/** Create an instance of FatReader. */
|
||||
FatReader(void) : type_(FILE_TYPE_CLOSED) {}
|
||||
void ls(uint8_t flags = 0);
|
||||
uint8_t openRoot(FatVolume &vol);
|
||||
uint8_t open(FatVolume &vol, dir_t &dir);
|
||||
uint8_t open(FatReader &dir, char *name);
|
||||
uint8_t open(FatReader &dir, uint16_t index);
|
||||
void optimizeContiguous(void);
|
||||
int16_t read(void *buf, uint16_t count);
|
||||
int8_t readDir(dir_t &dir);
|
||||
void rewind(void);
|
||||
uint8_t seekCur(uint32_t pos);
|
||||
// inline functions
|
||||
/** Close this instance of FatReader. */
|
||||
void close(void) { type_ = FILE_TYPE_CLOSED; }
|
||||
/** \return The total number of bytes in a file or directory. */
|
||||
uint32_t fileSize(void) { return fileSize_; }
|
||||
/**
|
||||
* Type of this FatReader. You should use isFile() or isDir()
|
||||
* instead of type() if possible.
|
||||
*
|
||||
* \return The file or directory type.
|
||||
*/
|
||||
uint8_t fileType(void) { return type_ & FILE_TYPE_MASK; }
|
||||
/** \return The first cluster number for a file or directory. */
|
||||
uint32_t firstCluster(void) { return firstCluster_; }
|
||||
/**
|
||||
* \return True if the bit for optimized reads is set.
|
||||
* See optimizeContiguous(). */
|
||||
uint8_t isContiguous(void) { return type_ & FILE_IS_CONTIGUOUS; }
|
||||
/** \return True if this is a FatReader for a directory else false */
|
||||
uint8_t isDir(void) { return fileType() >= FILE_TYPE_MIN_DIR; }
|
||||
/** \return True if this is a FatReader for a file else false */
|
||||
uint8_t isFile(void) { return fileType() == FILE_TYPE_NORMAL; }
|
||||
/** \return True if FatReader is for an open file/directory else false */
|
||||
uint8_t isOpen(void) { return fileType() != FILE_TYPE_CLOSED; }
|
||||
/** \return The current cluster number for a file or directory. */
|
||||
uint32_t readCluster(void) { return readCluster_; }
|
||||
/** \return The read position for a file or directory. */
|
||||
uint32_t readPosition(void) { return readPosition_; }
|
||||
/**
|
||||
* Set the read position for a file or directory to \a pos.
|
||||
*
|
||||
* \param[in] pos The new read position in bytes from the beginning
|
||||
* of the file.
|
||||
*
|
||||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
uint8_t seekSet(uint32_t pos) {
|
||||
if (pos >= readPosition_)
|
||||
return seekCur(pos - readPosition_);
|
||||
rewind();
|
||||
return seekCur(pos);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief get the parent volume
|
||||
@returns the parent volume
|
||||
*/
|
||||
FatVolume *volume(void) { return vol_; }
|
||||
};
|
||||
#endif // FatReader_h
|
||||
@@ -0,0 +1,393 @@
|
||||
#ifndef FatStructs_h
|
||||
#define FatStructs_h
|
||||
/**
|
||||
* \file
|
||||
* FAT file structures
|
||||
*/
|
||||
/*
|
||||
* mostly from Microsoft document fatgen103.doc
|
||||
* http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
/** Value for byte 510 of boot block or MBR */
|
||||
#define BOOTSIG0 0X55
|
||||
/** Value for byte 511 of boot block or MBR */
|
||||
#define BOOTSIG1 0XAA
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct partitionTable
|
||||
* \brief MBR partition table entry
|
||||
*
|
||||
* A partition table entry for a MBR formatted storage device.
|
||||
* The MBR partition table has four entries.
|
||||
*/
|
||||
struct partitionTable {
|
||||
/**
|
||||
* Boot Indicator . Indicates whether the volume is the active
|
||||
* partition. Legal values include: 0X00. Do not use for booting.
|
||||
* 0X80 Active partition.
|
||||
*/
|
||||
uint8_t boot;
|
||||
/**
|
||||
* Head part of Cylinder-head-sector address of the first block in
|
||||
* the partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t beginHead;
|
||||
/**
|
||||
* Sector part of Cylinder-head-sector address of the first block in
|
||||
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
||||
*/
|
||||
unsigned beginSector : 6;
|
||||
/** High bits cylinder for first block in partition. */
|
||||
unsigned beginCylinderHigh : 2;
|
||||
/**
|
||||
* Combine beginCylinderLow with beginCylinderHigh. Legal values
|
||||
* are 0-1023. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t beginCylinderLow;
|
||||
/**
|
||||
* Partition type. See defines that begin with PART_TYPE_ for
|
||||
* some Microsoft partition types.
|
||||
*/
|
||||
uint8_t type;
|
||||
/**
|
||||
* head part of cylinder-head-sector address of the last sector in the
|
||||
* partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t endHead;
|
||||
/**
|
||||
* Sector part of cylinder-head-sector address of the last sector in
|
||||
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
||||
*/
|
||||
unsigned endSector : 6;
|
||||
/** High bits of end cylinder */
|
||||
unsigned endCylinderHigh : 2;
|
||||
/**
|
||||
* Combine endCylinderLow with endCylinderHigh. Legal values
|
||||
* are 0-1023. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t endCylinderLow;
|
||||
/** Logical block address of the first block in the partition. */
|
||||
uint32_t firstSector;
|
||||
/** Length of the partition, in blocks. */
|
||||
uint32_t totalSectors;
|
||||
};
|
||||
/** Type name for partitionTable */
|
||||
typedef struct partitionTable part_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct masterBootRecord
|
||||
*
|
||||
* \brief Master Boot Record
|
||||
*
|
||||
* The first block of a storage device that is formatted with a MBR.
|
||||
*/
|
||||
struct masterBootRecord {
|
||||
/** Code Area for master boot program. */
|
||||
uint8_t codeArea[440];
|
||||
/** Optional WindowsNT disk signature. May contain more boot code. */
|
||||
uint32_t diskSignature;
|
||||
/** Usually zero but may be more boot code. */
|
||||
uint16_t usuallyZero;
|
||||
/** Partition tables. */
|
||||
part_t part[4];
|
||||
/** First MBR signature byte. Must be 0X55 */
|
||||
uint8_t mbrSig0;
|
||||
/** Second MBR signature byte. Must be 0XAA */
|
||||
uint8_t mbrSig1;
|
||||
};
|
||||
/** Type name for masterBootRecord */
|
||||
typedef struct masterBootRecord mbr_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct biosParmBlock
|
||||
*
|
||||
* \brief BIOS parameter block
|
||||
*
|
||||
* The BIOS parameter block describes the physical layout of a FAT volume.
|
||||
*/
|
||||
struct biosParmBlock {
|
||||
/**
|
||||
* Count of bytes per sector. This value may take on only the
|
||||
* following values: 512, 1024, 2048 or 4096
|
||||
*/
|
||||
uint16_t bytesPerSector;
|
||||
/**
|
||||
* Number of sectors per allocation unit. This value must be a
|
||||
* power of 2 that is greater than 0. The legal values are
|
||||
* 1, 2, 4, 8, 16, 32, 64, and 128.
|
||||
*/
|
||||
uint8_t sectorsPerCluster;
|
||||
/**
|
||||
* Number of sectors before the first FAT.
|
||||
* This value must not be zero.
|
||||
*/
|
||||
uint16_t reservedSectorCount;
|
||||
/** The count of FAT data structures on the volume. This field should
|
||||
* always contain the value 2 for any FAT volume of any type.
|
||||
*/
|
||||
uint8_t fatCount;
|
||||
/**
|
||||
* For FAT12 and FAT16 volumes, this field contains the count of
|
||||
* 32-byte directory entries in the root directory. For FAT32 volumes,
|
||||
* this field must be set to 0. For FAT12 and FAT16 volumes, this
|
||||
* value should always specify a count that when multiplied by 32
|
||||
* results in a multiple of bytesPerSector. FAT16 volumes should
|
||||
* use the value 512.
|
||||
*/
|
||||
uint16_t rootDirEntryCount;
|
||||
/**
|
||||
* This field is the old 16-bit total count of sectors on the volume.
|
||||
* This count includes the count of all sectors in all four regions
|
||||
* of the volume. This field can be 0; if it is 0, then totalSectors32
|
||||
* must be nonzero. For FAT32 volumes, this field must be 0. For
|
||||
* FAT12 and FAT16 volumes, this field contains the sector count, and
|
||||
* totalSectors32 is 0 if the total sector count fits
|
||||
* (is less than 0x10000).
|
||||
*/
|
||||
uint16_t totalSectors16;
|
||||
/**
|
||||
* This dates back to the old MS-DOS 1.x media determination and is
|
||||
* no longer usually used for anything. 0xF8 is the standard value
|
||||
* for fixed (nonremovable) media. For removable media, 0xF0 is
|
||||
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
||||
*/
|
||||
uint8_t mediaType;
|
||||
/**
|
||||
* Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
|
||||
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
||||
* contains the FAT size count.
|
||||
*/
|
||||
uint16_t sectorsPerFat16;
|
||||
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t sectorsPerTrtack;
|
||||
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t headCount;
|
||||
/**
|
||||
* Count of hidden sectors preceding the partition that contains this
|
||||
* FAT volume. This field is generally only relevant for media
|
||||
* visible on interrupt 0x13.
|
||||
*/
|
||||
uint32_t hidddenSectors;
|
||||
/**
|
||||
* This field is the new 32-bit total count of sectors on the volume.
|
||||
* This count includes the count of all sectors in all four regions
|
||||
* of the volume. This field can be 0; if it is 0, then
|
||||
* totalSectors16 must be nonzero.
|
||||
*/
|
||||
uint32_t totalSectors32;
|
||||
/**
|
||||
* Count of sectors occupied by one FAT on FAT32 volumes.
|
||||
*/
|
||||
uint32_t sectorsPerFat32;
|
||||
/**
|
||||
* This field is only defined for FAT32 media and does not exist on
|
||||
* FAT12 and FAT16 media.
|
||||
* Bits 0-3 -- Zero-based number of active FAT.
|
||||
* Only valid if mirroring is disabled.
|
||||
* Bits 4-6 -- Reserved.
|
||||
* Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
|
||||
* -- 1 means only one FAT is active; it is the one referenced in bits
|
||||
* 0-3. Bits 8-15 -- Reserved.
|
||||
*/
|
||||
uint16_t fat32Flags;
|
||||
/**
|
||||
* FAT32 version. High byte is major revision number.
|
||||
* Low byte is minor revision number. Only 0.0 define.
|
||||
*/
|
||||
uint16_t fat32Version;
|
||||
/**
|
||||
* Cluster number of the first cluster of the root directory for FAT32.
|
||||
* This usually 2 but not required to be 2.
|
||||
*/
|
||||
uint32_t fat32RootCluster;
|
||||
/**
|
||||
* Sector number of FSINFO structure in the reserved area of the
|
||||
* FAT32 volume. Usually 1.
|
||||
*/
|
||||
uint16_t fat32FSInfo;
|
||||
/**
|
||||
* If nonzero, indicates the sector number in the reserved area
|
||||
* of the volume of a copy of the boot record. Usually 6.
|
||||
* No value other than 6 is recommended.
|
||||
*/
|
||||
uint16_t fat32BackBootBlock;
|
||||
/**
|
||||
* Reserved for future expansion. Code that formats FAT32 volumes
|
||||
* should always set all of the bytes of this field to 0.
|
||||
*/
|
||||
uint8_t fat32Reserved[12];
|
||||
};
|
||||
/** Type name for biosParmBlock */
|
||||
typedef struct biosParmBlock bpb_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct fat32BootSector
|
||||
*
|
||||
* \brief Boot sector for a FAT16 or FAT32 volume.
|
||||
*
|
||||
*/
|
||||
struct fat32BootSector {
|
||||
/** X86 jmp to boot program */
|
||||
uint8_t jmpToBootCode[3];
|
||||
/** informational only - don't depend on it */
|
||||
char oemName[8];
|
||||
/** BIOS Parameter Block */
|
||||
bpb_t bpb;
|
||||
/** for int0x13 use value 0X80 for hard drive */
|
||||
uint8_t driveNumber;
|
||||
/**used by Windows NT - should be zero for FAT */
|
||||
uint8_t reserved1;
|
||||
/** 0X29 if next three fields are valid */
|
||||
uint8_t bootSignature;
|
||||
/** usually generated by combining date and time */
|
||||
uint32_t volumeSerialNumber;
|
||||
/** should match volume label in root dir */
|
||||
char volumeLabel[11];
|
||||
/** informational only - don't depend on it */
|
||||
char fileSystemType[8];
|
||||
/** X86 boot code */
|
||||
uint8_t bootCode[420];
|
||||
/** must be 0X55 */
|
||||
uint8_t bootSectorSig0;
|
||||
/** must be 0XAA */
|
||||
uint8_t bootSectorSig1;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
// End Of Chain values for FAT entries
|
||||
/** Minimum value for FAT16 EOC. Use to test for EOC. */
|
||||
#define FAT16EOC_MIN 0XFFF8
|
||||
/** Minimum value for FAT32 EOC. Use to test for EOC. */
|
||||
#define FAT32EOC_MIN 0X0FFFFFF8
|
||||
/** FAT16 end of chain value used by Microsoft. */
|
||||
#define FAT16EOC 0XFFFF
|
||||
/** FAT32 end of chain value used by Microsoft. */
|
||||
#define FAT32EOC 0X0FFFFFFF
|
||||
/** Mask a for FAT32 entry. Entries are 28 bits. */
|
||||
#define FAT32MASK 0X0FFFFFFF
|
||||
|
||||
/** Type name for fat32BootSector */
|
||||
typedef struct fat32BootSector fbs_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct directoryEntry
|
||||
* \brief FAT short directory entry
|
||||
*
|
||||
* Short means short 8.3 name, not the entry size.
|
||||
*
|
||||
* Date Format. A FAT directory entry date stamp is a 16-bit field that is
|
||||
* basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
|
||||
* format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the
|
||||
* 16-bit word):
|
||||
*
|
||||
* Bits 9-15: Count of years from 1980, valid value range 0-127
|
||||
* inclusive (1980-2107).
|
||||
*
|
||||
* Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
|
||||
*
|
||||
* Bits 0-4: Day of month, valid value range 1-31 inclusive.
|
||||
*
|
||||
* Time Format. A FAT directory entry time stamp is a 16-bit field that has
|
||||
* a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the
|
||||
* 16-bit word, bit 15 is the MSB of the 16-bit word).
|
||||
*
|
||||
* Bits 11-15: Hours, valid value range 0-23 inclusive.
|
||||
*
|
||||
* Bits 5-10: Minutes, valid value range 0-59 inclusive.
|
||||
*
|
||||
* Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
|
||||
*
|
||||
* The valid time range is from Midnight 00:00:00 to 23:59:58.
|
||||
*/
|
||||
struct directoryEntry {
|
||||
/**
|
||||
* Short 8.3 name.
|
||||
* The first eight bytes contain the file name with blank fill.
|
||||
* The last three bytes contain the file extension with blank fill.
|
||||
*/
|
||||
uint8_t name[11];
|
||||
/** Entry attributes.
|
||||
*
|
||||
* The upper two bits of the attribute byte are reserved and should
|
||||
* always be set to 0 when a file is created and never modified or
|
||||
* looked at after that. See defines that begin with DIR_ATT_.
|
||||
*/
|
||||
uint8_t attributes;
|
||||
/**
|
||||
* Reserved for use by Windows NT. Set value to 0 when a file is
|
||||
* created and never modify or look at it after that.
|
||||
*/
|
||||
uint8_t reservedNT;
|
||||
/**
|
||||
* The granularity of the seconds part of creationTime is 2 seconds
|
||||
* so this field is a count of tenths of a second and its valid
|
||||
* value range is 0-199 inclusive. (WHG note - seems to be hundredths)
|
||||
*/
|
||||
uint8_t creationTimeTenths;
|
||||
/** Time file was created. */
|
||||
uint16_t creationTime;
|
||||
/** Date file was created. */
|
||||
uint16_t creationDate;
|
||||
/**
|
||||
* Last access date. Note that there is no last access time, only
|
||||
* a date. This is the date of last read or write. In the case of
|
||||
* a write, this should be set to the same date as lastWriteDate.
|
||||
*/
|
||||
uint16_t lastAccessDate;
|
||||
/**
|
||||
* High word of this entry's first cluster number (always 0 for a
|
||||
* FAT12 or FAT16 volume).
|
||||
*/
|
||||
uint16_t firstClusterHigh;
|
||||
/** Time of last write. File creation is considered a write. */
|
||||
uint16_t lastWriteTime;
|
||||
/** Date of last write. File creation is considered a write. */
|
||||
uint16_t lastWriteDate;
|
||||
/** Low word of this entry's first cluster number. */
|
||||
uint16_t firstClusterLow;
|
||||
/** 32-bit unsigned holding this file's size in bytes. */
|
||||
uint32_t fileSize;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
// Macros for directory entries
|
||||
//
|
||||
/** Type name for directoryEntry */
|
||||
typedef struct directoryEntry dir_t;
|
||||
/** escape for name[0] = 0XE5 */
|
||||
#define DIR_NAME_0XE5 0X05
|
||||
/** name[0] value for entry that is free after being "deleted" */
|
||||
#define DIR_NAME_DELETED 0XE5
|
||||
/** name[0] value for entry that is free and no allocated entries follow */
|
||||
#define DIR_NAME_FREE 0X00
|
||||
/** file is read-only */
|
||||
#define DIR_ATT_READ_ONLY 0X01
|
||||
/** File should hidden in directory listings */
|
||||
#define DIR_ATT_HIDDEN 0X02
|
||||
/** Entry is for a system file */
|
||||
#define DIR_ATT_SYSTEM 0X04
|
||||
/** Directory entry contains the volume label */
|
||||
#define DIR_ATT_VOLUME_ID 0X08
|
||||
/** Entry is for a directory */
|
||||
#define DIR_ATT_DIRECTORY 0X10
|
||||
/** Old DOS archive bit for backup support */
|
||||
#define DIR_ATT_ARCHIVE 0X20
|
||||
/** Test value for long name entry. Test is
|
||||
d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
|
||||
#define DIR_ATT_LONG_NAME 0X0F
|
||||
/** Test mask for long name entry */
|
||||
#define DIR_ATT_LONG_NAME_MASK 0X3F
|
||||
/** defined attribute bits */
|
||||
#define DIR_ATT_DEFINED_BITS 0X3F
|
||||
/** Directory entry is part of a long name */
|
||||
#define DIR_IS_LONG_NAME(dir) \
|
||||
(((dir).attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME)
|
||||
/** Mask for file/subdirectory tests */
|
||||
#define DIR_ATT_FILE_TYPE_MASK (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY)
|
||||
/** Directory entry is for a file */
|
||||
#define DIR_IS_FILE(dir) (((dir).attributes & DIR_ATT_FILE_TYPE_MASK) == 0)
|
||||
/** Directory entry is for a subdirectory */
|
||||
#define DIR_IS_SUBDIR(dir) \
|
||||
(((dir).attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY)
|
||||
/** Directory entry is for a file or subdirectory */
|
||||
#define DIR_IS_FILE_OR_SUBDIR(dir) (((dir).attributes & DIR_ATT_VOLUME_ID) == 0)
|
||||
#endif // FatStructs_h
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
0.TXT
|
||||
@@ -0,0 +1 @@
|
||||
1.TXT
|
||||
@@ -0,0 +1 @@
|
||||
10.TXT
|
||||
@@ -0,0 +1 @@
|
||||
100.TXT
|
||||
@@ -0,0 +1 @@
|
||||
101.TXT
|
||||
@@ -0,0 +1 @@
|
||||
102.TXT
|
||||
@@ -0,0 +1 @@
|
||||
103.TXT
|
||||
@@ -0,0 +1 @@
|
||||
104.TXT
|
||||
@@ -0,0 +1 @@
|
||||
105.TXT
|
||||
@@ -0,0 +1 @@
|
||||
106.TXT
|
||||
@@ -0,0 +1 @@
|
||||
107.TXT
|
||||
@@ -0,0 +1 @@
|
||||
108.TXT
|
||||
@@ -0,0 +1 @@
|
||||
109.TXT
|
||||
@@ -0,0 +1 @@
|
||||
11.TXT
|
||||
@@ -0,0 +1 @@
|
||||
110.TXT
|
||||
@@ -0,0 +1 @@
|
||||
111.TXT
|
||||
@@ -0,0 +1 @@
|
||||
112.TXT
|
||||
@@ -0,0 +1 @@
|
||||
113.TXT
|
||||
@@ -0,0 +1 @@
|
||||
114.TXT
|
||||
@@ -0,0 +1 @@
|
||||
115.TXT
|
||||
@@ -0,0 +1 @@
|
||||
116.TXT
|
||||
@@ -0,0 +1 @@
|
||||
117.TXT
|
||||
@@ -0,0 +1 @@
|
||||
118.TXT
|
||||
@@ -0,0 +1 @@
|
||||
119.TXT
|
||||
@@ -0,0 +1 @@
|
||||
12.TXT
|
||||
@@ -0,0 +1 @@
|
||||
120.TXT
|
||||
@@ -0,0 +1 @@
|
||||
121.TXT
|
||||
@@ -0,0 +1 @@
|
||||
122.TXT
|
||||
@@ -0,0 +1 @@
|
||||
123.TXT
|
||||
@@ -0,0 +1 @@
|
||||
124.TXT
|
||||
@@ -0,0 +1 @@
|
||||
125.TXT
|
||||
@@ -0,0 +1 @@
|
||||
126.TXT
|
||||
@@ -0,0 +1 @@
|
||||
127.TXT
|
||||
@@ -0,0 +1 @@
|
||||
128.TXT
|
||||
@@ -0,0 +1 @@
|
||||
129.TXT
|
||||
@@ -0,0 +1 @@
|
||||
13.TXT
|
||||
@@ -0,0 +1 @@
|
||||
130.TXT
|
||||
@@ -0,0 +1 @@
|
||||
131.TXT
|
||||
@@ -0,0 +1 @@
|
||||
132.TXT
|
||||
@@ -0,0 +1 @@
|
||||
133.TXT
|
||||
@@ -0,0 +1 @@
|
||||
134.TXT
|
||||
@@ -0,0 +1 @@
|
||||
135.TXT
|
||||
@@ -0,0 +1 @@
|
||||
136.TXT
|
||||
@@ -0,0 +1 @@
|
||||
137.TXT
|
||||
@@ -0,0 +1 @@
|
||||
138.TXT
|
||||
@@ -0,0 +1 @@
|
||||
139.TXT
|
||||
@@ -0,0 +1 @@
|
||||
14.TXT
|
||||
@@ -0,0 +1 @@
|
||||
140.TXT
|
||||
@@ -0,0 +1 @@
|
||||
141.TXT
|
||||
@@ -0,0 +1 @@
|
||||
142.TXT
|
||||
@@ -0,0 +1 @@
|
||||
143.TXT
|
||||
@@ -0,0 +1 @@
|
||||
144.TXT
|
||||
@@ -0,0 +1 @@
|
||||
145.TXT
|
||||
@@ -0,0 +1 @@
|
||||
146.TXT
|
||||
@@ -0,0 +1 @@
|
||||
147.TXT
|
||||
@@ -0,0 +1 @@
|
||||
148.TXT
|
||||
@@ -0,0 +1 @@
|
||||
149.TXT
|
||||
@@ -0,0 +1 @@
|
||||
15.TXT
|
||||
@@ -0,0 +1 @@
|
||||
150.TXT
|
||||
@@ -0,0 +1 @@
|
||||
151.TXT
|
||||
@@ -0,0 +1 @@
|
||||
152.TXT
|
||||
@@ -0,0 +1 @@
|
||||
153.TXT
|
||||
@@ -0,0 +1 @@
|
||||
154.TXT
|
||||
@@ -0,0 +1 @@
|
||||
155.TXT
|
||||
@@ -0,0 +1 @@
|
||||
156.TXT
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user