aboutsummaryrefslogtreecommitdiff
path: root/lib/lufa/Projects/TempDataLogger
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lufa/Projects/TempDataLogger')
-rw-r--r--lib/lufa/Projects/TempDataLogger/Config/AppConfig.h48
-rw-r--r--lib/lufa/Projects/TempDataLogger/Config/LUFAConfig.h93
-rw-r--r--lib/lufa/Projects/TempDataLogger/Descriptors.c257
-rw-r--r--lib/lufa/Projects/TempDataLogger/Descriptors.h87
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.c534
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.h86
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/FATFs/00readme.txt135
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.c98
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.h55
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.c4139
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.h337
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/FATFs/ffconf.h191
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/FATFs/integer.h38
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/RTC.c159
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/RTC.h126
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/SCSI.c344
-rw-r--r--lib/lufa/Projects/TempDataLogger/Lib/SCSI.h89
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempDataLogger.c331
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempDataLogger.h112
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.LESSER.txt166
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.txt675
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.Designer.cs181
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.cs179
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.resx120
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Linux.dllbin0 -> 9216 bytes
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Net.dllbin0 -> 24576 bytes
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Win32.dllbin0 -> 94208 bytes
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Program.cs21
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/AssemblyInfo.cs36
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.Designer.cs63
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.resx117
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.Designer.cs26
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.settings7
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/README.txt24
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp/TempLoggerHostApp.csproj99
-rw-r--r--lib/lufa/Projects/TempDataLogger/TempLogHostApp_Python/temp_log_config.py99
-rw-r--r--lib/lufa/Projects/TempDataLogger/TemperatureDataLogger.txt86
-rw-r--r--lib/lufa/Projects/TempDataLogger/asf.xml72
-rw-r--r--lib/lufa/Projects/TempDataLogger/doxyfile2397
-rw-r--r--lib/lufa/Projects/TempDataLogger/makefile44
40 files changed, 11671 insertions, 0 deletions
diff --git a/lib/lufa/Projects/TempDataLogger/Config/AppConfig.h b/lib/lufa/Projects/TempDataLogger/Config/AppConfig.h
new file mode 100644
index 000000000..fcfcb2590
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Config/AppConfig.h
@@ -0,0 +1,48 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 * \brief Application Configuration Header File
33 *
34 * This is a header file which is be used to configure some of
35 * the application's compile time options, as an alternative to
36 * specifying the compile time constants supplied through a
37 * makefile or build system.
38 *
39 * For information on what each token does, refer to the
40 * \ref Sec_Options section of the application documentation.
41 */
42
43#ifndef _APP_CONFIG_H_
44#define _APP_CONFIG_H_
45
46 #define DUMMY_RTC
47
48#endif
diff --git a/lib/lufa/Projects/TempDataLogger/Config/LUFAConfig.h b/lib/lufa/Projects/TempDataLogger/Config/LUFAConfig.h
new file mode 100644
index 000000000..f7d7e6270
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 * \brief LUFA Library Configuration Header File
33 *
34 * This header file is used to configure LUFA's compile time options,
35 * as an alternative to the compile time constants supplied through
36 * a makefile.
37 *
38 * For information on what each token does, refer to the LUFA
39 * manual section "Summary of Compile Tokens".
40 */
41
42#ifndef _LUFA_CONFIG_H_
43#define _LUFA_CONFIG_H_
44
45 #if (ARCH == ARCH_AVR8)
46
47 /* Non-USB Related Configuration Tokens: */
48// #define DISABLE_TERMINAL_CODES
49
50 /* USB Class Driver Related Tokens: */
51// #define HID_HOST_BOOT_PROTOCOL_ONLY
52// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
53// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
54// #define HID_MAX_COLLECTIONS {Insert Value Here}
55// #define HID_MAX_REPORTITEMS {Insert Value Here}
56// #define HID_MAX_REPORT_IDS {Insert Value Here}
57// #define NO_CLASS_DRIVER_AUTOFLUSH
58
59 /* General USB Driver Related Tokens: */
60// #define ORDERED_EP_CONFIG
61 #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
62 #define USB_DEVICE_ONLY
63// #define USB_HOST_ONLY
64// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
65// #define NO_LIMITED_CONTROLLER_CONNECT
66// #define NO_SOF_EVENTS
67
68 /* USB Device Mode Driver Related Tokens: */
69// #define USE_RAM_DESCRIPTORS
70 #define USE_FLASH_DESCRIPTORS
71// #define USE_EEPROM_DESCRIPTORS
72// #define NO_INTERNAL_SERIAL
73 #define FIXED_CONTROL_ENDPOINT_SIZE 8
74 #define DEVICE_STATE_AS_GPIOR 0
75 #define FIXED_NUM_CONFIGURATIONS 1
76// #define CONTROL_ONLY_DEVICE
77 #define INTERRUPT_CONTROL_ENDPOINT
78// #define NO_DEVICE_REMOTE_WAKEUP
79// #define NO_DEVICE_SELF_POWER
80
81 /* USB Host Mode Driver Related Tokens: */
82// #define HOST_STATE_AS_GPIOR 0
83// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
84// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
85// #define NO_AUTO_VBUS_MANAGEMENT
86// #define INVERTED_VBUS_ENABLE_LINE
87
88 #else
89
90 #error Unsupported architecture for this LUFA configuration file.
91
92 #endif
93#endif
diff --git a/lib/lufa/Projects/TempDataLogger/Descriptors.c b/lib/lufa/Projects/TempDataLogger/Descriptors.c
new file mode 100644
index 000000000..c07a58878
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Descriptors.c
@@ -0,0 +1,257 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 *
33 * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
34 * computer-readable structures which the host requests upon device enumeration, to determine
35 * the device's capabilities and functions.
36 */
37
38#include "Descriptors.h"
39
40
41/** HID class report descriptor. This is a special descriptor constructed with values from the
42 * USBIF HID class specification to describe the reports and capabilities of the HID device. This
43 * descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
44 * the device will send, and what it may be sent back from the host. Refer to the HID specification for
45 * more details on HID report descriptors.
46 */
47const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] =
48{
49 /* Use the HID class driver's standard Vendor HID report.
50 * Vendor Usage Page: 1
51 * Vendor Collection Usage: 1
52 * Vendor Report IN Usage: 2
53 * Vendor Report OUT Usage: 3
54 * Vendor Report Size: GENERIC_REPORT_SIZE
55 */
56 HID_DESCRIPTOR_VENDOR(0x00, 0x01, 0x02, 0x03, GENERIC_REPORT_SIZE)
57};
58
59/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
60 * device characteristics, including the supported USB version, control endpoint size and the
61 * number of device configurations. The descriptor is read out by the USB host when the enumeration
62 * process begins.
63 */
64const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
65{
66 .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
67
68 .USBSpecification = VERSION_BCD(1,1,0),
69 .Class = USB_CSCP_NoDeviceClass,
70 .SubClass = USB_CSCP_NoDeviceSubclass,
71 .Protocol = USB_CSCP_NoDeviceProtocol,
72
73 .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
74
75 .VendorID = 0x03EB,
76 .ProductID = 0x2063,
77 .ReleaseNumber = VERSION_BCD(0,0,1),
78
79 .ManufacturerStrIndex = STRING_ID_Manufacturer,
80 .ProductStrIndex = STRING_ID_Product,
81 .SerialNumStrIndex = USE_INTERNAL_SERIAL,
82
83 .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
84};
85
86/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
87 * of the device in one of its supported configurations, including information about any device interfaces
88 * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
89 * a configuration so that the host may correctly communicate with the USB device.
90 */
91const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
92{
93 .Config =
94 {
95 .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
96
97 .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
98 .TotalInterfaces = 2,
99
100 .ConfigurationNumber = 1,
101 .ConfigurationStrIndex = NO_DESCRIPTOR,
102
103 .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED),
104
105 .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
106 },
107
108 .MS_Interface =
109 {
110 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
111
112 .InterfaceNumber = INTERFACE_ID_MassStorage,
113 .AlternateSetting = 0,
114
115 .TotalEndpoints = 2,
116
117 .Class = MS_CSCP_MassStorageClass,
118 .SubClass = MS_CSCP_SCSITransparentSubclass,
119 .Protocol = MS_CSCP_BulkOnlyTransportProtocol,
120
121 .InterfaceStrIndex = NO_DESCRIPTOR
122 },
123
124 .MS_DataInEndpoint =
125 {
126 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
127
128 .EndpointAddress = MASS_STORAGE_IN_EPADDR,
129 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
130 .EndpointSize = MASS_STORAGE_IO_EPSIZE,
131 .PollingIntervalMS = 0x05
132 },
133
134 .MS_DataOutEndpoint =
135 {
136 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
137
138 .EndpointAddress = MASS_STORAGE_OUT_EPADDR,
139 .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
140 .EndpointSize = MASS_STORAGE_IO_EPSIZE,
141 .PollingIntervalMS = 0x05
142 },
143
144 .HID_Interface =
145 {
146 .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
147
148 .InterfaceNumber = INTERFACE_ID_HID,
149 .AlternateSetting = 0,
150
151 .TotalEndpoints = 1,
152
153 .Class = HID_CSCP_HIDClass,
154 .SubClass = HID_CSCP_NonBootSubclass,
155 .Protocol = HID_CSCP_NonBootProtocol,
156
157 .InterfaceStrIndex = NO_DESCRIPTOR
158 },
159
160 .HID_GenericHID =
161 {
162 .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
163
164 .HIDSpec = VERSION_BCD(1,1,1),
165 .CountryCode = 0x00,
166 .TotalReportDescriptors = 1,
167 .HIDReportType = HID_DTYPE_Report,
168 .HIDReportLength = sizeof(GenericReport)
169 },
170
171 .HID_ReportINEndpoint =
172 {
173 .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
174
175 .EndpointAddress = GENERIC_IN_EPADDR,
176 .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
177 .EndpointSize = GENERIC_EPSIZE,
178 .PollingIntervalMS = 0x05
179 },
180};
181
182/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
183 * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
184 * via the language ID table available at USB.org what languages the device supports for its string descriptors.
185 */
186const USB_Descriptor_String_t PROGMEM LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
187
188/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
189 * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
190 * Descriptor.
191 */
192const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR(L"Dean Camera");
193
194/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
195 * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
196 * Descriptor.
197 */
198const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Temperature Datalogger");
199
200/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
201 * documentation) by the application code so that the address and size of a requested descriptor can be given
202 * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
203 * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
204 * USB host.
205 */
206uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
207 const uint16_t wIndex,
208 const void** const DescriptorAddress)
209{
210 const uint8_t DescriptorType = (wValue >> 8);
211 const uint8_t DescriptorNumber = (wValue & 0xFF);
212
213 const void* Address = NULL;
214 uint16_t Size = NO_DESCRIPTOR;
215
216 switch (DescriptorType)
217 {
218 case DTYPE_Device:
219 Address = &DeviceDescriptor;
220 Size = sizeof(USB_Descriptor_Device_t);
221 break;
222 case DTYPE_Configuration:
223 Address = &ConfigurationDescriptor;
224 Size = sizeof(USB_Descriptor_Configuration_t);
225 break;
226 case DTYPE_String:
227 switch (DescriptorNumber)
228 {
229 case STRING_ID_Language:
230 Address = &LanguageString;
231 Size = pgm_read_byte(&LanguageString.Header.Size);
232 break;
233 case STRING_ID_Manufacturer:
234 Address = &ManufacturerString;
235 Size = pgm_read_byte(&ManufacturerString.Header.Size);
236 break;
237 case STRING_ID_Product:
238 Address = &ProductString;
239 Size = pgm_read_byte(&ProductString.Header.Size);
240 break;
241 }
242
243 break;
244 case HID_DTYPE_HID:
245 Address = &ConfigurationDescriptor.HID_GenericHID;
246 Size = sizeof(USB_HID_Descriptor_HID_t);
247 break;
248 case HID_DTYPE_Report:
249 Address = &GenericReport;
250 Size = sizeof(GenericReport);
251 break;
252 }
253
254 *DescriptorAddress = Address;
255 return Size;
256}
257
diff --git a/lib/lufa/Projects/TempDataLogger/Descriptors.h b/lib/lufa/Projects/TempDataLogger/Descriptors.h
new file mode 100644
index 000000000..ffbd65d46
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Descriptors.h
@@ -0,0 +1,87 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9#ifndef _DESCRIPTORS_H_
10#define _DESCRIPTORS_H_
11
12 /* Includes: */
13 #include <avr/pgmspace.h>
14
15 #include <LUFA/Drivers/USB/USB.h>
16
17 #include "TempDataLogger.h"
18 #include "Config/AppConfig.h"
19
20 /* Macros: */
21 /** Endpoint address of the Mass Storage device-to-host data IN endpoint. */
22 #define MASS_STORAGE_IN_EPADDR (ENDPOINT_DIR_IN | 3)
23
24 /** Endpoint address of the Mass Storage host-to-device data OUT endpoint. */
25 #define MASS_STORAGE_OUT_EPADDR (ENDPOINT_DIR_OUT | 4)
26
27 /** Size in bytes of the Mass Storage data endpoints. */
28 #define MASS_STORAGE_IO_EPSIZE 64
29
30 /** Endpoint address of the Generic HID reporting IN endpoint. */
31 #define GENERIC_IN_EPADDR (ENDPOINT_DIR_IN | 1)
32
33 /** Size in bytes of the Generic HID reporting endpoint. */
34 #define GENERIC_EPSIZE 16
35
36 /** Size in bytes of the Generic HID reports (including report ID byte). */
37 #define GENERIC_REPORT_SIZE sizeof(Device_Report_t)
38
39 /* Type Defines: */
40 /** Type define for the device configuration descriptor structure. This must be defined in the
41 * application code, as the configuration descriptor contains several sub-descriptors which
42 * vary between devices, and which describe the device's usage to the host.
43 */
44 typedef struct
45 {
46 USB_Descriptor_Configuration_Header_t Config;
47
48 // Mass Storage Interface
49 USB_Descriptor_Interface_t MS_Interface;
50 USB_Descriptor_Endpoint_t MS_DataInEndpoint;
51 USB_Descriptor_Endpoint_t MS_DataOutEndpoint;
52
53 // Settings Management Generic HID Interface
54 USB_Descriptor_Interface_t HID_Interface;
55 USB_HID_Descriptor_HID_t HID_GenericHID;
56 USB_Descriptor_Endpoint_t HID_ReportINEndpoint;
57 } USB_Descriptor_Configuration_t;
58
59 /** Enum for the device interface descriptor IDs within the device. Each interface descriptor
60 * should have a unique ID index associated with it, which can be used to refer to the
61 * interface from other descriptors.
62 */
63 enum InterfaceDescriptors_t
64 {
65 INTERFACE_ID_MassStorage = 0, /**< Mass storage interface descriptor ID */
66 INTERFACE_ID_HID = 1, /**< HID interface descriptor ID */
67 };
68
69 /** Enum for the device string descriptor IDs within the device. Each string descriptor should
70 * have a unique ID index associated with it, which can be used to refer to the string from
71 * other descriptors.
72 */
73 enum StringDescriptors_t
74 {
75 STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
76 STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
77 STRING_ID_Product = 2, /**< Product string ID */
78 };
79
80 /* Function Prototypes: */
81 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
82 const uint16_t wIndex,
83 const void** const DescriptorAddress)
84 ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
85
86#endif
87
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.c b/lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.c
new file mode 100644
index 000000000..b1111ce39
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.c
@@ -0,0 +1,534 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 *
33 * Functions to manage the physical Dataflash media, including reading and writing of
34 * blocks of data. These functions are called by the SCSI layer when data must be stored
35 * or retrieved to/from the physical storage media. If a different media is used (such
36 * as a SD card or EEPROM), functions similar to these will need to be generated.
37 */
38
39#define INCLUDE_FROM_DATAFLASHMANAGER_C
40#include "DataflashManager.h"
41
42/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board Dataflash IC(s), from
43 * the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes
44 * them to the Dataflash in Dataflash page sized blocks.
45 *
46 * \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
47 * \param[in] BlockAddress Data block starting address for the write sequence
48 * \param[in] TotalBlocks Number of blocks of data to write
49 */
50void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
51 const uint32_t BlockAddress,
52 uint16_t TotalBlocks)
53{
54 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
55 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
56 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
57 bool UsingSecondBuffer = false;
58
59 /* Select the correct starting Dataflash IC for the block requested */
60 Dataflash_SelectChipFromPage(CurrDFPage);
61
62#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
63 /* Copy selected dataflash's current page contents to the Dataflash buffer */
64 Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
65 Dataflash_SendAddressBytes(CurrDFPage, 0);
66 Dataflash_WaitWhileBusy();
67#endif
68
69 /* Send the Dataflash buffer write command */
70 Dataflash_SendByte(DF_CMD_BUFF1WRITE);
71 Dataflash_SendAddressBytes(0, CurrDFPageByte);
72
73 /* Wait until endpoint is ready before continuing */
74 if (Endpoint_WaitUntilReady())
75 return;
76
77 while (TotalBlocks)
78 {
79 uint8_t BytesInBlockDiv16 = 0;
80
81 /* Write an endpoint packet sized data block to the Dataflash */
82 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
83 {
84 /* Check if the endpoint is currently empty */
85 if (!(Endpoint_IsReadWriteAllowed()))
86 {
87 /* Clear the current endpoint bank */
88 Endpoint_ClearOUT();
89
90 /* Wait until the host has sent another packet */
91 if (Endpoint_WaitUntilReady())
92 return;
93 }
94
95 /* Check if end of Dataflash page reached */
96 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
97 {
98 /* Write the Dataflash buffer contents back to the Dataflash page */
99 Dataflash_WaitWhileBusy();
100 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
101 Dataflash_SendAddressBytes(CurrDFPage, 0);
102
103 /* Reset the Dataflash buffer counter, increment the page counter */
104 CurrDFPageByteDiv16 = 0;
105 CurrDFPage++;
106
107 /* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
108 if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))
109 UsingSecondBuffer = !(UsingSecondBuffer);
110
111 /* Select the next Dataflash chip based on the new Dataflash page index */
112 Dataflash_SelectChipFromPage(CurrDFPage);
113
114#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
115 /* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */
116 if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))
117 {
118 /* Copy selected dataflash's current page contents to the Dataflash buffer */
119 Dataflash_WaitWhileBusy();
120 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
121 Dataflash_SendAddressBytes(CurrDFPage, 0);
122 Dataflash_WaitWhileBusy();
123 }
124#endif
125
126 /* Send the Dataflash buffer write command */
127 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);
128 Dataflash_SendAddressBytes(0, 0);
129 }
130
131 /* Write one 16-byte chunk of data to the Dataflash */
132 Dataflash_SendByte(Endpoint_Read_8());
133 Dataflash_SendByte(Endpoint_Read_8());
134 Dataflash_SendByte(Endpoint_Read_8());
135 Dataflash_SendByte(Endpoint_Read_8());
136 Dataflash_SendByte(Endpoint_Read_8());
137 Dataflash_SendByte(Endpoint_Read_8());
138 Dataflash_SendByte(Endpoint_Read_8());
139 Dataflash_SendByte(Endpoint_Read_8());
140 Dataflash_SendByte(Endpoint_Read_8());
141 Dataflash_SendByte(Endpoint_Read_8());
142 Dataflash_SendByte(Endpoint_Read_8());
143 Dataflash_SendByte(Endpoint_Read_8());
144 Dataflash_SendByte(Endpoint_Read_8());
145 Dataflash_SendByte(Endpoint_Read_8());
146 Dataflash_SendByte(Endpoint_Read_8());
147 Dataflash_SendByte(Endpoint_Read_8());
148
149 /* Increment the Dataflash page 16 byte block counter */
150 CurrDFPageByteDiv16++;
151
152 /* Increment the block 16 byte block counter */
153 BytesInBlockDiv16++;
154
155 /* Check if the current command is being aborted by the host */
156 if (MSInterfaceInfo->State.IsMassStoreReset)
157 return;
158 }
159
160 /* Decrement the blocks remaining counter */
161 TotalBlocks--;
162 }
163
164 /* Write the Dataflash buffer contents back to the Dataflash page */
165 Dataflash_WaitWhileBusy();
166 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
167 Dataflash_SendAddressBytes(CurrDFPage, 0x00);
168 Dataflash_WaitWhileBusy();
169
170 /* If the endpoint is empty, clear it ready for the next packet from the host */
171 if (!(Endpoint_IsReadWriteAllowed()))
172 Endpoint_ClearOUT();
173
174 /* Deselect all Dataflash chips */
175 Dataflash_DeselectChip();
176}
177
178/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board Dataflash IC(s), into
179 * the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash
180 * and writes them in OS sized blocks to the endpoint.
181 *
182 * \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
183 * \param[in] BlockAddress Data block starting address for the read sequence
184 * \param[in] TotalBlocks Number of blocks of data to read
185 */
186void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
187 const uint32_t BlockAddress,
188 uint16_t TotalBlocks)
189{
190 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
191 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
192 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
193
194 /* Select the correct starting Dataflash IC for the block requested */
195 Dataflash_SelectChipFromPage(CurrDFPage);
196
197 /* Send the Dataflash main memory page read command */
198 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
199 Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
200 Dataflash_SendByte(0x00);
201 Dataflash_SendByte(0x00);
202 Dataflash_SendByte(0x00);
203 Dataflash_SendByte(0x00);
204
205 /* Wait until endpoint is ready before continuing */
206 if (Endpoint_WaitUntilReady())
207 return;
208
209 while (TotalBlocks)
210 {
211 uint8_t BytesInBlockDiv16 = 0;
212
213 /* Read an endpoint packet sized data block from the Dataflash */
214 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
215 {
216 /* Check if the endpoint is currently full */
217 if (!(Endpoint_IsReadWriteAllowed()))
218 {
219 /* Clear the endpoint bank to send its contents to the host */
220 Endpoint_ClearIN();
221
222 /* Wait until the endpoint is ready for more data */
223 if (Endpoint_WaitUntilReady())
224 return;
225 }
226
227 /* Check if end of Dataflash page reached */
228 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
229 {
230 /* Reset the Dataflash buffer counter, increment the page counter */
231 CurrDFPageByteDiv16 = 0;
232 CurrDFPage++;
233
234 /* Select the next Dataflash chip based on the new Dataflash page index */
235 Dataflash_SelectChipFromPage(CurrDFPage);
236
237 /* Send the Dataflash main memory page read command */
238 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
239 Dataflash_SendAddressBytes(CurrDFPage, 0);
240 Dataflash_SendByte(0x00);
241 Dataflash_SendByte(0x00);
242 Dataflash_SendByte(0x00);
243 Dataflash_SendByte(0x00);
244 }
245
246 /* Read one 16-byte chunk of data from the Dataflash */
247 Endpoint_Write_8(Dataflash_ReceiveByte());
248 Endpoint_Write_8(Dataflash_ReceiveByte());
249 Endpoint_Write_8(Dataflash_ReceiveByte());
250 Endpoint_Write_8(Dataflash_ReceiveByte());
251 Endpoint_Write_8(Dataflash_ReceiveByte());
252 Endpoint_Write_8(Dataflash_ReceiveByte());
253 Endpoint_Write_8(Dataflash_ReceiveByte());
254 Endpoint_Write_8(Dataflash_ReceiveByte());
255 Endpoint_Write_8(Dataflash_ReceiveByte());
256 Endpoint_Write_8(Dataflash_ReceiveByte());
257 Endpoint_Write_8(Dataflash_ReceiveByte());
258 Endpoint_Write_8(Dataflash_ReceiveByte());
259 Endpoint_Write_8(Dataflash_ReceiveByte());
260 Endpoint_Write_8(Dataflash_ReceiveByte());
261 Endpoint_Write_8(Dataflash_ReceiveByte());
262 Endpoint_Write_8(Dataflash_ReceiveByte());
263
264 /* Increment the Dataflash page 16 byte block counter */
265 CurrDFPageByteDiv16++;
266
267 /* Increment the block 16 byte block counter */
268 BytesInBlockDiv16++;
269
270 /* Check if the current command is being aborted by the host */
271 if (MSInterfaceInfo->State.IsMassStoreReset)
272 return;
273 }
274
275 /* Decrement the blocks remaining counter */
276 TotalBlocks--;
277 }
278
279 /* If the endpoint is full, send its contents to the host */
280 if (!(Endpoint_IsReadWriteAllowed()))
281 Endpoint_ClearIN();
282
283 /* Deselect all Dataflash chips */
284 Dataflash_DeselectChip();
285}
286
287/** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board Dataflash IC(s), from
288 * the given RAM buffer. This routine reads in OS sized blocks from the buffer and writes them to the
289 * Dataflash in Dataflash page sized blocks. This can be linked to FAT libraries to write files to the
290 * Dataflash.
291 *
292 * \param[in] BlockAddress Data block starting address for the write sequence
293 * \param[in] TotalBlocks Number of blocks of data to write
294 * \param[in] BufferPtr Pointer to the data source RAM buffer
295 */
296void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress,
297 uint16_t TotalBlocks,
298 const uint8_t* BufferPtr)
299{
300 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
301 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
302 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
303 bool UsingSecondBuffer = false;
304
305 /* Select the correct starting Dataflash IC for the block requested */
306 Dataflash_SelectChipFromPage(CurrDFPage);
307
308#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
309 /* Copy selected dataflash's current page contents to the Dataflash buffer */
310 Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
311 Dataflash_SendAddressBytes(CurrDFPage, 0);
312 Dataflash_WaitWhileBusy();
313#endif
314
315 /* Send the Dataflash buffer write command */
316 Dataflash_SendByte(DF_CMD_BUFF1WRITE);
317 Dataflash_SendAddressBytes(0, CurrDFPageByte);
318
319 while (TotalBlocks)
320 {
321 uint8_t BytesInBlockDiv16 = 0;
322
323 /* Write an endpoint packet sized data block to the Dataflash */
324 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
325 {
326 /* Check if end of Dataflash page reached */
327 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
328 {
329 /* Write the Dataflash buffer contents back to the Dataflash page */
330 Dataflash_WaitWhileBusy();
331 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
332 Dataflash_SendAddressBytes(CurrDFPage, 0);
333
334 /* Reset the Dataflash buffer counter, increment the page counter */
335 CurrDFPageByteDiv16 = 0;
336 CurrDFPage++;
337
338 /* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
339 if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))
340 UsingSecondBuffer = !(UsingSecondBuffer);
341
342 /* Select the next Dataflash chip based on the new Dataflash page index */
343 Dataflash_SelectChipFromPage(CurrDFPage);
344
345#if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
346 /* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */
347 if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))
348 {
349 /* Copy selected dataflash's current page contents to the Dataflash buffer */
350 Dataflash_WaitWhileBusy();
351 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
352 Dataflash_SendAddressBytes(CurrDFPage, 0);
353 Dataflash_WaitWhileBusy();
354 }
355#endif
356
357 /* Send the Dataflash buffer write command */
358 Dataflash_ToggleSelectedChipCS();
359 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);
360 Dataflash_SendAddressBytes(0, 0);
361 }
362
363 /* Write one 16-byte chunk of data to the Dataflash */
364 for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)
365 Dataflash_SendByte(*(BufferPtr++));
366
367 /* Increment the Dataflash page 16 byte block counter */
368 CurrDFPageByteDiv16++;
369
370 /* Increment the block 16 byte block counter */
371 BytesInBlockDiv16++;
372 }
373
374 /* Decrement the blocks remaining counter */
375 TotalBlocks--;
376 }
377
378 /* Write the Dataflash buffer contents back to the Dataflash page */
379 Dataflash_WaitWhileBusy();
380 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
381 Dataflash_SendAddressBytes(CurrDFPage, 0x00);
382 Dataflash_WaitWhileBusy();
383
384 /* Deselect all Dataflash chips */
385 Dataflash_DeselectChip();
386}
387
388/** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board Dataflash IC(s), into
389 * the preallocated RAM buffer. This routine reads in Dataflash page sized blocks from the Dataflash
390 * and writes them in OS sized blocks to the given buffer. This can be linked to FAT libraries to read
391 * the files stored on the Dataflash.
392 *
393 * \param[in] BlockAddress Data block starting address for the read sequence
394 * \param[in] TotalBlocks Number of blocks of data to read
395 * \param[out] BufferPtr Pointer to the data destination RAM buffer
396 */
397void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress,
398 uint16_t TotalBlocks,
399 uint8_t* BufferPtr)
400{
401 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
402 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
403 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
404
405 /* Select the correct starting Dataflash IC for the block requested */
406 Dataflash_SelectChipFromPage(CurrDFPage);
407
408 /* Send the Dataflash main memory page read command */
409 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
410 Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
411 Dataflash_SendByte(0x00);
412 Dataflash_SendByte(0x00);
413 Dataflash_SendByte(0x00);
414 Dataflash_SendByte(0x00);
415
416 while (TotalBlocks)
417 {
418 uint8_t BytesInBlockDiv16 = 0;
419
420 /* Read an endpoint packet sized data block from the Dataflash */
421 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
422 {
423 /* Check if end of Dataflash page reached */
424 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
425 {
426 /* Reset the Dataflash buffer counter, increment the page counter */
427 CurrDFPageByteDiv16 = 0;
428 CurrDFPage++;
429
430 /* Select the next Dataflash chip based on the new Dataflash page index */
431 Dataflash_SelectChipFromPage(CurrDFPage);
432
433 /* Send the Dataflash main memory page read command */
434 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
435 Dataflash_SendAddressBytes(CurrDFPage, 0);
436 Dataflash_SendByte(0x00);
437 Dataflash_SendByte(0x00);
438 Dataflash_SendByte(0x00);
439 Dataflash_SendByte(0x00);
440 }
441
442 /* Read one 16-byte chunk of data from the Dataflash */
443 for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)
444 *(BufferPtr++) = Dataflash_ReceiveByte();
445
446 /* Increment the Dataflash page 16 byte block counter */
447 CurrDFPageByteDiv16++;
448
449 /* Increment the block 16 byte block counter */
450 BytesInBlockDiv16++;
451 }
452
453 /* Decrement the blocks remaining counter */
454 TotalBlocks--;
455 }
456
457 /* Deselect all Dataflash chips */
458 Dataflash_DeselectChip();
459}
460
461/** Disables the Dataflash memory write protection bits on the board Dataflash ICs, if enabled. */
462void DataflashManager_ResetDataflashProtections(void)
463{
464 /* Select first Dataflash chip, send the read status register command */
465 Dataflash_SelectChip(DATAFLASH_CHIP1);
466 Dataflash_SendByte(DF_CMD_GETSTATUS);
467
468 /* Check if sector protection is enabled */
469 if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)
470 {
471 Dataflash_ToggleSelectedChipCS();
472
473 /* Send the commands to disable sector protection */
474 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
475 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
476 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
477 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
478 }
479
480 /* Select second Dataflash chip (if present on selected board), send read status register command */
481 #if (DATAFLASH_TOTALCHIPS == 2)
482 Dataflash_SelectChip(DATAFLASH_CHIP2);
483 Dataflash_SendByte(DF_CMD_GETSTATUS);
484
485 /* Check if sector protection is enabled */
486 if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)
487 {
488 Dataflash_ToggleSelectedChipCS();
489
490 /* Send the commands to disable sector protection */
491 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
492 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
493 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
494 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
495 }
496 #endif
497
498 /* Deselect current Dataflash chip */
499 Dataflash_DeselectChip();
500}
501
502/** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working.
503 *
504 * \return Boolean \c true if all media chips are working, \c false otherwise
505 */
506bool DataflashManager_CheckDataflashOperation(void)
507{
508 uint8_t ReturnByte;
509
510 /* Test first Dataflash IC is present and responding to commands */
511 Dataflash_SelectChip(DATAFLASH_CHIP1);
512 Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
513 ReturnByte = Dataflash_ReceiveByte();
514 Dataflash_DeselectChip();
515
516 /* If returned data is invalid, fail the command */
517 if (ReturnByte != DF_MANUFACTURER_ATMEL)
518 return false;
519
520 #if (DATAFLASH_TOTALCHIPS == 2)
521 /* Test second Dataflash IC is present and responding to commands */
522 Dataflash_SelectChip(DATAFLASH_CHIP2);
523 Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
524 ReturnByte = Dataflash_ReceiveByte();
525 Dataflash_DeselectChip();
526
527 /* If returned data is invalid, fail the command */
528 if (ReturnByte != DF_MANUFACTURER_ATMEL)
529 return false;
530 #endif
531
532 return true;
533}
534
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.h b/lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.h
new file mode 100644
index 000000000..f0feeb67b
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/DataflashManager.h
@@ -0,0 +1,86 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 *
33 * Header file for DataflashManager.c.
34 */
35
36#ifndef _DATAFLASH_MANAGER_H_
37#define _DATAFLASH_MANAGER_H_
38
39 /* Includes: */
40 #include <avr/io.h>
41
42 #include "../TempDataLogger.h"
43 #include "../Descriptors.h"
44 #include "Config/AppConfig.h"
45
46 #include <LUFA/Common/Common.h>
47 #include <LUFA/Drivers/USB/USB.h>
48 #include <LUFA/Drivers/Board/Dataflash.h>
49
50 /* Preprocessor Checks: */
51 #if (DATAFLASH_PAGE_SIZE % 16)
52 #error Dataflash page size must be a multiple of 16 bytes.
53 #endif
54
55 /* Defines: */
56 /** Total number of bytes of the storage medium, comprised of one or more Dataflash ICs. */
57 #define VIRTUAL_MEMORY_BYTES ((uint32_t)DATAFLASH_PAGES * DATAFLASH_PAGE_SIZE * DATAFLASH_TOTALCHIPS)
58
59 /** Block size of the device. This is kept at 512 to remain compatible with the OS despite the underlying
60 * storage media (Dataflash) using a different native block size. Do not change this value.
61 */
62 #define VIRTUAL_MEMORY_BLOCK_SIZE 512
63
64 /** Total number of blocks of the virtual memory for reporting to the host as the device's total capacity. Do not
65 * change this value; change VIRTUAL_MEMORY_BYTES instead to alter the media size.
66 */
67 #define VIRTUAL_MEMORY_BLOCKS (VIRTUAL_MEMORY_BYTES / VIRTUAL_MEMORY_BLOCK_SIZE)
68
69 /* Function Prototypes: */
70 void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
71 const uint32_t BlockAddress,
72 uint16_t TotalBlocks);
73 void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
74 const uint32_t BlockAddress,
75 uint16_t TotalBlocks);
76 void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress,
77 uint16_t TotalBlocks,
78 const uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
79 void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress,
80 uint16_t TotalBlocks,
81 uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
82 void DataflashManager_ResetDataflashProtections(void);
83 bool DataflashManager_CheckDataflashOperation(void);
84
85#endif
86
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/FATFs/00readme.txt b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/00readme.txt
new file mode 100644
index 000000000..80d8843d1
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/00readme.txt
@@ -0,0 +1,135 @@
1FatFs Module Source Files R0.09a (C)ChaN, 2012
2
3
4FILES
5
6 ffconf.h Configuration file for FatFs module.
7 ff.h Common include file for FatFs and application module.
8 ff.c FatFs module.
9 diskio.h Common include file for FatFs and disk I/O module.
10 diskio.c An example of glue function to attach existing disk I/O module to FatFs.
11 integer.h Integer type definitions for FatFs.
12 option Optional external functions.
13
14 Low level disk I/O module is not included in this archive because the FatFs
15 module is only a generic file system layer and not depend on any specific
16 storage device. You have to provide a low level disk I/O module that written
17 to control your storage device.
18
19
20
21AGREEMENTS
22
23 FatFs module is an open source software to implement FAT file system to
24 small embedded systems. This is a free software and is opened for education,
25 research and commercial developments under license policy of following trems.
26
27 Copyright (C) 2012, ChaN, all right reserved.
28
29 * The FatFs module is a free software and there is NO WARRANTY.
30 * No restriction on use. You can use, modify and redistribute it for
31 personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
32 * Redistributions of source code must retain the above copyright notice.
33
34
35
36REVISION HISTORY
37
38 Feb 26, 2006 R0.00 Prototype
39
40 Apr 29, 2006 R0.01 First release.
41
42 Jun 01, 2006 R0.02 Added FAT12.
43 Removed unbuffered mode.
44 Fixed a problem on small (<32M) patition.
45
46 Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM.
47
48 Sep 22, 2006 R0.03 Added f_rename.
49 Changed option _FS_MINIMUM to _FS_MINIMIZE.
50
51 Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast.
52 Fixed f_mkdir creates incorrect directory on FAT32.
53
54 Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs)
55 Changed some APIs for multiple drive system.
56 Added f_mkfs. (FatFs)
57 Added _USE_FAT32 option. (Tiny-FatFs)
58
59 Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs)
60 Fixed an endian sensitive code in f_mkfs. (FatFs)
61 Added a capability of extending the file size to f_lseek.
62 Added minimization level 3.
63 Fixed a problem that can collapse a sector when recreate an
64 existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs)
65
66 May 05, 2007 R0.04b Added _USE_NTFLAG option.
67 Added FSInfo support.
68 Fixed some problems corresponds to FAT32. (Tiny-FatFs)
69 Fixed DBCS name can result FR_INVALID_NAME.
70 Fixed short seek (0 < ofs <= csize) collapses the file object.
71
72 Aug 25, 2007 R0.05 Changed arguments of f_read, f_write.
73 Changed arguments of f_mkfs. (FatFs)
74 Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs)
75 Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs)
76
77 Feb 03, 2008 R0.05a Added f_truncate().
78 Added f_utime().
79 Fixed off by one error at FAT sub-type determination.
80 Fixed btr in f_read() can be mistruncated.
81 Fixed cached sector is not flushed when create and close without write.
82
83 Apr 01, 2008 R0.06 Added f_forward(). (Tiny-FatFs)
84 Added string functions: fputc(), fputs(), fprintf() and fgets().
85 Improved performance of f_lseek() on move to the same or following cluster.
86
87 Apr 01, 2009, R0.07 Merged Tiny-FatFs as a buffer configuration option.
88 Added long file name support.
89 Added multiple code page support.
90 Added re-entrancy for multitask operation.
91 Added auto cluster size selection to f_mkfs().
92 Added rewind option to f_readdir().
93 Changed result code of critical errors.
94 Renamed string functions to avoid name collision.
95
96 Apr 14, 2009, R0.07a Separated out OS dependent code on reentrant cfg.
97 Added multiple sector size support.
98
99 Jun 21, 2009, R0.07c Fixed f_unlink() may return FR_OK on error.
100 Fixed wrong cache control in f_lseek().
101 Added relative path feature.
102 Added f_chdir().
103 Added f_chdrive().
104 Added proper case conversion for extended characters.
105
106 Nov 03, 2009 R0.07e Separated out configuration options from ff.h to ffconf.h.
107 Added a configuration option, _LFN_UNICODE.
108 Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
109 Fixed name matching error on the 13 char boundary.
110 Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
111
112 May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN)
113 Added file lock feature. (_FS_SHARE)
114 Added fast seek feature. (_USE_FASTSEEK)
115 Changed some types on the API, XCHAR->TCHAR.
116 Changed fname member in the FILINFO structure on Unicode cfg.
117 String functions support UTF-8 encoding files on Unicode cfg.
118
119 Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
120 Added sector erase feature. (_USE_ERASE)
121 Moved file lock semaphore table from fs object to the bss.
122 Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
123 Fixed f_mkfs() creates wrong FAT32 volume.
124
125 Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
126 f_lseek() reports required table size on creating CLMP.
127 Extended format syntax of f_printf function.
128 Ignores duplicated directory separators in given path names.
129
130 Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
131 Added f_fdisk(). (_MULTI_PARTITION = 2)
132
133 Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16.
134 Changed API rejects null object pointer to avoid crash.
135 Changed option name _FS_SHARE to _FS_LOCK.
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.c b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.c
new file mode 100644
index 000000000..8cc8cd404
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.c
@@ -0,0 +1,98 @@
1/*-----------------------------------------------------------------------*/
2/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2007 */
3/*-----------------------------------------------------------------------*/
4/* This is a stub disk I/O module that acts as front end of the existing */
5/* disk I/O modules and attach it to FatFs module with common interface. */
6/*-----------------------------------------------------------------------*/
7
8#include "diskio.h"
9
10/*-----------------------------------------------------------------------*/
11/* Initialize a Drive */
12
13DSTATUS disk_initialize (
14 BYTE drv /* Physical drive number (0..) */
15)
16{
17 return FR_OK;
18}
19
20
21
22/*-----------------------------------------------------------------------*/
23/* Return Disk Status */
24
25DSTATUS disk_status (
26 BYTE drv /* Physical drive number (0..) */
27)
28{
29 return FR_OK;
30}
31
32
33
34/*-----------------------------------------------------------------------*/
35/* Read Sector(s) */
36
37DRESULT disk_read (
38 BYTE drv, /* Physical drive number (0..) */
39 BYTE *buff, /* Data buffer to store read data */
40 DWORD sector, /* Sector address (LBA) */
41 BYTE count /* Number of sectors to read (1..128) */
42)
43{
44 DataflashManager_ReadBlocks_RAM(sector, count, buff);
45 return RES_OK;
46}
47
48
49
50/*-----------------------------------------------------------------------*/
51/* Write Sector(s) */
52
53#if _READONLY == 0
54DRESULT disk_write (
55 BYTE drv, /* Physical drive number (0..) */
56 const BYTE *buff, /* Data to be written */
57 DWORD sector, /* Sector address (LBA) */
58 BYTE count /* Number of sectors to write (1..128) */
59)
60{
61 DataflashManager_WriteBlocks_RAM(sector, count, buff);
62 return RES_OK;
63}
64#endif /* _READONLY */
65
66
67
68/*-----------------------------------------------------------------------*/
69/* Miscellaneous Functions */
70
71DRESULT disk_ioctl (
72 BYTE drv, /* Physical drive number (0..) */
73 BYTE ctrl, /* Control code */
74 void *buff /* Buffer to send/receive control data */
75)
76{
77 if (ctrl == CTRL_SYNC)
78 return RES_OK;
79 else
80 return RES_PARERR;
81}
82
83
84DWORD get_fattime (void)
85{
86 TimeDate_t CurrTimeDate;
87
88 RTC_GetTimeDate(&CurrTimeDate);
89
90
91 return ((DWORD)(20 + CurrTimeDate.Year) << 25) |
92 ((DWORD)CurrTimeDate.Month << 21) |
93 ((DWORD)CurrTimeDate.Day << 16) |
94 ((DWORD)CurrTimeDate.Hour << 11) |
95 ((DWORD)CurrTimeDate.Minute << 5) |
96 (((DWORD)CurrTimeDate.Second >> 1) << 0);
97}
98
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.h b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.h
new file mode 100644
index 000000000..d3c3149a5
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/diskio.h
@@ -0,0 +1,55 @@
1/*-----------------------------------------------------------------------
2/ Low level disk interface module include file
3/-----------------------------------------------------------------------*/
4
5#ifndef _DISKIO_DEFINED
6#define _DISKIO_DEFINED
7
8#ifdef __cplusplus
9extern "C" {
10#endif
11
12#include "integer.h"
13
14#include "../DataflashManager.h"
15
16
17/* Status of Disk Functions */
18typedef BYTE DSTATUS;
19
20/* Results of Disk Functions */
21typedef enum {
22 RES_OK = 0, /* 0: Successful */
23 RES_ERROR, /* 1: R/W Error */
24 RES_WRPRT, /* 2: Write Protected */
25 RES_NOTRDY, /* 3: Not Ready */
26 RES_PARERR /* 4: Invalid Parameter */
27} DRESULT;
28
29
30/*---------------------------------------*/
31/* Prototypes for disk control functions */
32
33DSTATUS disk_initialize (BYTE);
34DSTATUS disk_status (BYTE);
35DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
36#if _READONLY == 0
37DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
38#endif
39DRESULT disk_ioctl (BYTE, BYTE, void*);
40
41
42/* Disk Status Bits (DSTATUS) */
43
44#define STA_NOINIT 0x01 /* Drive not initialized */
45#define STA_NODISK 0x02 /* No medium in the drive */
46#define STA_PROTECT 0x04 /* Write protected */
47
48/* Generic command */
49#define CTRL_SYNC 0 /* Mandatory for write functions */
50
51#ifdef __cplusplus
52}
53#endif
54
55#endif
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.c b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.c
new file mode 100644
index 000000000..059b5885a
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.c
@@ -0,0 +1,4139 @@
1/*----------------------------------------------------------------------------/
2/ FatFs - FAT file system module R0.09a (C)ChaN, 2012
3/-----------------------------------------------------------------------------/
4/ FatFs module is a generic FAT file system module for small embedded systems.
5/ This is a free software that opened for education, research and commercial
6/ developments under license policy of following terms.
7/
8/ Copyright (C) 2012, ChaN, all right reserved.
9/
10/ * The FatFs module is a free software and there is NO WARRANTY.
11/ * No restriction on use. You can use, modify and redistribute it for
12/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
13/ * Redistributions of source code must retain the above copyright notice.
14/
15/-----------------------------------------------------------------------------/
16/ Feb 26,'06 R0.00 Prototype.
17/
18/ Apr 29,'06 R0.01 First stable version.
19/
20/ Jun 01,'06 R0.02 Added FAT12 support.
21/ Removed unbuffered mode.
22/ Fixed a problem on small (<32M) partition.
23/ Jun 10,'06 R0.02a Added a configuration option (_FS_MINIMUM).
24/
25/ Sep 22,'06 R0.03 Added f_rename().
26/ Changed option _FS_MINIMUM to _FS_MINIMIZE.
27/ Dec 11,'06 R0.03a Improved cluster scan algorithm to write files fast.
28/ Fixed f_mkdir() creates incorrect directory on FAT32.
29/
30/ Feb 04,'07 R0.04 Supported multiple drive system.
31/ Changed some interfaces for multiple drive system.
32/ Changed f_mountdrv() to f_mount().
33/ Added f_mkfs().
34/ Apr 01,'07 R0.04a Supported multiple partitions on a physical drive.
35/ Added a capability of extending file size to f_lseek().
36/ Added minimization level 3.
37/ Fixed an endian sensitive code in f_mkfs().
38/ May 05,'07 R0.04b Added a configuration option _USE_NTFLAG.
39/ Added FSInfo support.
40/ Fixed DBCS name can result FR_INVALID_NAME.
41/ Fixed short seek (<= csize) collapses the file object.
42/
43/ Aug 25,'07 R0.05 Changed arguments of f_read(), f_write() and f_mkfs().
44/ Fixed f_mkfs() on FAT32 creates incorrect FSInfo.
45/ Fixed f_mkdir() on FAT32 creates incorrect directory.
46/ Feb 03,'08 R0.05a Added f_truncate() and f_utime().
47/ Fixed off by one error at FAT sub-type determination.
48/ Fixed btr in f_read() can be mistruncated.
49/ Fixed cached sector is not flushed when create and close without write.
50/
51/ Apr 01,'08 R0.06 Added fputc(), fputs(), fprintf() and fgets().
52/ Improved performance of f_lseek() on moving to the same or following cluster.
53/
54/ Apr 01,'09 R0.07 Merged Tiny-FatFs as a configuration option. (_FS_TINY)
55/ Added long file name feature.
56/ Added multiple code page feature.
57/ Added re-entrancy for multitask operation.
58/ Added auto cluster size selection to f_mkfs().
59/ Added rewind option to f_readdir().
60/ Changed result code of critical errors.
61/ Renamed string functions to avoid name collision.
62/ Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg.
63/ Added multiple sector size feature.
64/ Jun 21,'09 R0.07c Fixed f_unlink() can return FR_OK on error.
65/ Fixed wrong cache control in f_lseek().
66/ Added relative path feature.
67/ Added f_chdir() and f_chdrive().
68/ Added proper case conversion to extended char.
69/ Nov 03,'09 R0.07e Separated out configuration options from ff.h to ffconf.h.
70/ Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
71/ Fixed name matching error on the 13 char boundary.
72/ Added a configuration option, _LFN_UNICODE.
73/ Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
74/
75/ May 15,'10 R0.08 Added a memory configuration option. (_USE_LFN = 3)
76/ Added file lock feature. (_FS_SHARE)
77/ Added fast seek feature. (_USE_FASTSEEK)
78/ Changed some types on the API, XCHAR->TCHAR.
79/ Changed fname member in the FILINFO structure on Unicode cfg.
80/ String functions support UTF-8 encoding files on Unicode cfg.
81/ Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
82/ Added sector erase feature. (_USE_ERASE)
83/ Moved file lock semaphore table from fs object to the bss.
84/ Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
85/ Fixed f_mkfs() creates wrong FAT32 volume.
86/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
87/ f_lseek() reports required table size on creating CLMP.
88/ Extended format syntax of f_printf function.
89/ Ignores duplicated directory separators in given path name.
90/
91/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
92/ Added f_fdisk(). (_MULTI_PARTITION = 2)
93/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
94/ Changed f_open() and f_opendir reject null object pointer to avoid crash.
95/ Changed option name _FS_SHARE to _FS_LOCK.
96/---------------------------------------------------------------------------*/
97
98#include "ff.h" /* FatFs configurations and declarations */
99#include "diskio.h" /* Declarations of low level disk I/O functions */
100
101
102/*--------------------------------------------------------------------------
103
104 Module Private Definitions
105
106---------------------------------------------------------------------------*/
107
108#if _FATFS != 4004 /* Revision ID */
109#error Wrong include file (ff.h).
110#endif
111
112
113/* Definitions on sector size */
114#if _MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096
115#error Wrong sector size.
116#endif
117#if _MAX_SS != 512
118#define SS(fs) ((fs)->ssize) /* Variable sector size */
119#else
120#define SS(fs) 512U /* Fixed sector size */
121#endif
122
123
124/* Reentrancy related */
125#if _FS_REENTRANT
126#if _USE_LFN == 1
127#error Static LFN work area must not be used in re-entrant configuration.
128#endif
129#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; }
130#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
131#else
132#define ENTER_FF(fs)
133#define LEAVE_FF(fs, res) return res
134#endif
135
136#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
137
138
139/* File access control feature */
140#if _FS_LOCK
141#if _FS_READONLY
142#error _FS_LOCK must be 0 on read-only cfg.
143#endif
144typedef struct {
145 FATFS *fs; /* File ID 1, volume (NULL:blank entry) */
146 DWORD clu; /* File ID 2, directory */
147 WORD idx; /* File ID 3, directory index */
148 WORD ctr; /* File open counter, 0:none, 0x01..0xFF:read open count, 0x100:write mode */
149} FILESEM;
150#endif
151
152
153
154/* DBCS code ranges and SBCS extend char conversion table */
155
156#if _CODE_PAGE == 932 /* Japanese Shift-JIS */
157#define _DF1S 0x81 /* DBC 1st byte range 1 start */
158#define _DF1E 0x9F /* DBC 1st byte range 1 end */
159#define _DF2S 0xE0 /* DBC 1st byte range 2 start */
160#define _DF2E 0xFC /* DBC 1st byte range 2 end */
161#define _DS1S 0x40 /* DBC 2nd byte range 1 start */
162#define _DS1E 0x7E /* DBC 2nd byte range 1 end */
163#define _DS2S 0x80 /* DBC 2nd byte range 2 start */
164#define _DS2E 0xFC /* DBC 2nd byte range 2 end */
165
166#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
167#define _DF1S 0x81
168#define _DF1E 0xFE
169#define _DS1S 0x40
170#define _DS1E 0x7E
171#define _DS2S 0x80
172#define _DS2E 0xFE
173
174#elif _CODE_PAGE == 949 /* Korean */
175#define _DF1S 0x81
176#define _DF1E 0xFE
177#define _DS1S 0x41
178#define _DS1E 0x5A
179#define _DS2S 0x61
180#define _DS2E 0x7A
181#define _DS3S 0x81
182#define _DS3E 0xFE
183
184#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
185#define _DF1S 0x81
186#define _DF1E 0xFE
187#define _DS1S 0x40
188#define _DS1E 0x7E
189#define _DS2S 0xA1
190#define _DS2E 0xFE
191
192#elif _CODE_PAGE == 437 /* U.S. (OEM) */
193#define _DF1S 0
194#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
195 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
196 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
197 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
198
199#elif _CODE_PAGE == 720 /* Arabic (OEM) */
200#define _DF1S 0
201#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
202 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
203 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
204 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
205
206#elif _CODE_PAGE == 737 /* Greek (OEM) */
207#define _DF1S 0
208#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \
209 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
210 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
211 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
212
213#elif _CODE_PAGE == 775 /* Baltic (OEM) */
214#define _DF1S 0
215#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
216 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
217 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
218 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
219
220#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */
221#define _DF1S 0
222#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
223 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
224 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
225 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
226
227#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */
228#define _DF1S 0
229#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \
230 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \
231 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
232 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}
233
234#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */
235#define _DF1S 0
236#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \
237 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \
238 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \
239 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}
240
241#elif _CODE_PAGE == 857 /* Turkish (OEM) */
242#define _DF1S 0
243#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
244 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
245 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
246 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
247
248#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */
249#define _DF1S 0
250#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
251 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
252 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
253 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
254
255#elif _CODE_PAGE == 862 /* Hebrew (OEM) */
256#define _DF1S 0
257#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
258 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
259 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
260 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
261
262#elif _CODE_PAGE == 866 /* Russian (OEM) */
263#define _DF1S 0
264#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
265 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
266 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
267 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
268
269#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */
270#define _DF1S 0
271#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
272 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
273 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
274 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
275
276#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
277#define _DF1S 0
278#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
279 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \
280 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
281 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
282
283#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
284#define _DF1S 0
285#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \
286 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \
287 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
288 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}
289
290#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
291#define _DF1S 0
292#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \
293 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
294 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
295 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
296
297#elif _CODE_PAGE == 1253 /* Greek (Windows) */
298#define _DF1S 0
299#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
300 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
301 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \
302 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}
303
304#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
305#define _DF1S 0
306#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \
307 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
308 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
309 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}
310
311#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
312#define _DF1S 0
313#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
314 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
315 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
316 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
317
318#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
319#define _DF1S 0
320#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \
321 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
322 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
323 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}
324
325#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
326#define _DF1S 0
327#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
328 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \
329 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
330 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}
331
332#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
333#define _DF1S 0
334#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \
335 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
336 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
337 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}
338
339#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */
340#if _USE_LFN
341#error Cannot use LFN feature without valid code page.
342#endif
343#define _DF1S 0
344
345#else
346#error Unknown code page
347
348#endif
349
350
351/* Character code support macros */
352#define IsUpper(c) (((c)>='A')&&((c)<='Z'))
353#define IsLower(c) (((c)>='a')&&((c)<='z'))
354#define IsDigit(c) (((c)>='0')&&((c)<='9'))
355
356#if _DF1S /* Code page is DBCS */
357
358#ifdef _DF2S /* Two 1st byte areas */
359#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
360#else /* One 1st byte area */
361#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
362#endif
363
364#ifdef _DS3S /* Three 2nd byte areas */
365#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
366#else /* Two 2nd byte areas */
367#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
368#endif
369
370#else /* Code page is SBCS */
371
372#define IsDBCS1(c) 0
373#define IsDBCS2(c) 0
374
375#endif /* _DF1S */
376
377
378/* Name status flags */
379#define NS 11 /* Index of name status byte in fn[] */
380#define NS_LOSS 0x01 /* Out of 8.3 format */
381#define NS_LFN 0x02 /* Force to create LFN entry */
382#define NS_LAST 0x04 /* Last segment */
383#define NS_BODY 0x08 /* Lower case flag (body) */
384#define NS_EXT 0x10 /* Lower case flag (ext) */
385#define NS_DOT 0x20 /* Dot entry */
386
387
388/* FAT sub-type boundaries */
389/* Note that the FAT spec by Microsoft says 4085 but Windows works with 4087! */
390#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */
391#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */
392
393
394/* FatFs refers the members in the FAT structures as byte array instead of
395/ structure member because the structure is not binary compatible between
396/ different platforms */
397
398#define BS_jmpBoot 0 /* Jump instruction (3) */
399#define BS_OEMName 3 /* OEM name (8) */
400#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */
401#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */
402#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */
403#define BPB_NumFATs 16 /* Number of FAT copies (1) */
404#define BPB_RootEntCnt 17 /* Number of root dir entries for FAT12/16 (2) */
405#define BPB_TotSec16 19 /* Volume size [sector] (2) */
406#define BPB_Media 21 /* Media descriptor (1) */
407#define BPB_FATSz16 22 /* FAT size [sector] (2) */
408#define BPB_SecPerTrk 24 /* Track size [sector] (2) */
409#define BPB_NumHeads 26 /* Number of heads (2) */
410#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */
411#define BPB_TotSec32 32 /* Volume size [sector] (4) */
412#define BS_DrvNum 36 /* Physical drive number (2) */
413#define BS_BootSig 38 /* Extended boot signature (1) */
414#define BS_VolID 39 /* Volume serial number (4) */
415#define BS_VolLab 43 /* Volume label (8) */
416#define BS_FilSysType 54 /* File system type (1) */
417#define BPB_FATSz32 36 /* FAT size [sector] (4) */
418#define BPB_ExtFlags 40 /* Extended flags (2) */
419#define BPB_FSVer 42 /* File system version (2) */
420#define BPB_RootClus 44 /* Root dir first cluster (4) */
421#define BPB_FSInfo 48 /* Offset of FSInfo sector (2) */
422#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */
423#define BS_DrvNum32 64 /* Physical drive number (2) */
424#define BS_BootSig32 66 /* Extended boot signature (1) */
425#define BS_VolID32 67 /* Volume serial number (4) */
426#define BS_VolLab32 71 /* Volume label (8) */
427#define BS_FilSysType32 82 /* File system type (1) */
428#define FSI_LeadSig 0 /* FSI: Leading signature (4) */
429#define FSI_StrucSig 484 /* FSI: Structure signature (4) */
430#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */
431#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */
432#define MBR_Table 446 /* MBR: Partition table offset (2) */
433#define SZ_PTE 16 /* MBR: Size of a partition table entry */
434#define BS_55AA 510 /* Boot sector signature (2) */
435
436#define DIR_Name 0 /* Short file name (11) */
437#define DIR_Attr 11 /* Attribute (1) */
438#define DIR_NTres 12 /* NT flag (1) */
439#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */
440#define DIR_CrtTime 14 /* Created time (2) */
441#define DIR_CrtDate 16 /* Created date (2) */
442#define DIR_LstAccDate 18 /* Last accessed date (2) */
443#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */
444#define DIR_WrtTime 22 /* Modified time (2) */
445#define DIR_WrtDate 24 /* Modified date (2) */
446#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */
447#define DIR_FileSize 28 /* File size (4) */
448#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */
449#define LDIR_Attr 11 /* LFN attribute (1) */
450#define LDIR_Type 12 /* LFN type (1) */
451#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */
452#define LDIR_FstClusLO 26 /* Filled by zero (0) */
453#define SZ_DIR 32 /* Size of a directory entry */
454#define LLE 0x40 /* Last long entry flag in LDIR_Ord */
455#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */
456#define NDDE 0x05 /* Replacement of the character collides with DDE */
457
458
459/*------------------------------------------------------------*/
460/* Module private work area */
461/*------------------------------------------------------------*/
462/* Note that uninitialized variables with static duration are
463/ zeroed/nulled at start-up. If not, the compiler or start-up
464/ routine is out of ANSI-C standard.
465*/
466
467#if _VOLUMES
468static
469FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
470#else
471#error Number of volumes must not be 0.
472#endif
473
474static
475WORD Fsid; /* File system mount ID */
476
477#if _FS_RPATH
478static
479BYTE CurrVol; /* Current drive */
480#endif
481
482#if _FS_LOCK
483static
484FILESEM Files[_FS_LOCK]; /* File lock semaphores */
485#endif
486
487#if _USE_LFN == 0 /* No LFN feature */
488#define DEF_NAMEBUF BYTE sfn[12]
489#define INIT_BUF(dobj) (dobj).fn = sfn
490#define FREE_BUF()
491
492#elif _USE_LFN == 1 /* LFN feature with static working buffer */
493static WCHAR LfnBuf[_MAX_LFN+1];
494#define DEF_NAMEBUF BYTE sfn[12]
495#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
496#define FREE_BUF()
497
498#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */
499#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
500#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
501#define FREE_BUF()
502
503#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */
504#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn
505#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
506 if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
507 (dobj).lfn = lfn; (dobj).fn = sfn; }
508#define FREE_BUF() ff_memfree(lfn)
509
510#else
511#error Wrong LFN configuration.
512#endif
513
514
515
516
517/*--------------------------------------------------------------------------
518
519 Module Private Functions
520
521---------------------------------------------------------------------------*/
522
523
524/*-----------------------------------------------------------------------*/
525/* String functions */
526/*-----------------------------------------------------------------------*/
527
528/* Copy memory to memory */
529static
530void mem_cpy (void* dst, const void* src, UINT cnt) {
531 BYTE *d = (BYTE*)dst;
532 const BYTE *s = (const BYTE*)src;
533
534#if _WORD_ACCESS == 1
535 while (cnt >= sizeof (int)) {
536 *(int*)d = *(int*)s;
537 d += sizeof (int); s += sizeof (int);
538 cnt -= sizeof (int);
539 }
540#endif
541 while (cnt--)
542 *d++ = *s++;
543}
544
545/* Fill memory */
546static
547void mem_set (void* dst, int val, UINT cnt) {
548 BYTE *d = (BYTE*)dst;
549
550 while (cnt--)
551 *d++ = (BYTE)val;
552}
553
554/* Compare memory to memory */
555static
556int mem_cmp (const void* dst, const void* src, UINT cnt) {
557 const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
558 int r = 0;
559
560 while (cnt-- && (r = *d++ - *s++) == 0) ;
561 return r;
562}
563
564/* Check if chr is contained in the string */
565static
566int chk_chr (const char* str, int chr) {
567 while (*str && *str != chr) str++;
568 return *str;
569}
570
571
572
573/*-----------------------------------------------------------------------*/
574/* Request/Release grant to access the volume */
575/*-----------------------------------------------------------------------*/
576#if _FS_REENTRANT
577
578static
579int lock_fs (
580 FATFS *fs /* File system object */
581)
582{
583 return ff_req_grant(fs->sobj);
584}
585
586
587static
588void unlock_fs (
589 FATFS *fs, /* File system object */
590 FRESULT res /* Result code to be returned */
591)
592{
593 if (fs &&
594 res != FR_NOT_ENABLED &&
595 res != FR_INVALID_DRIVE &&
596 res != FR_INVALID_OBJECT &&
597 res != FR_TIMEOUT) {
598 ff_rel_grant(fs->sobj);
599 }
600}
601#endif
602
603
604
605/*-----------------------------------------------------------------------*/
606/* File lock control functions */
607/*-----------------------------------------------------------------------*/
608#if _FS_LOCK
609
610static
611FRESULT chk_lock ( /* Check if the file can be accessed */
612 DIR* dj, /* Directory object pointing the file to be checked */
613 int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
614)
615{
616 UINT i, be;
617
618 /* Search file semaphore table */
619 for (i = be = 0; i < _FS_LOCK; i++) {
620 if (Files[i].fs) { /* Existing entry */
621 if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */
622 Files[i].clu == dj->sclust &&
623 Files[i].idx == dj->index) break;
624 } else { /* Blank entry */
625 be++;
626 }
627 }
628 if (i == _FS_LOCK) /* The file is not opened */
629 return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */
630
631 /* The file has been opened. Reject any open against writing file and all write mode open */
632 return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
633}
634
635
636static
637int enq_lock (void) /* Check if an entry is available for a new file */
638{
639 UINT i;
640
641 for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
642 return (i == _FS_LOCK) ? 0 : 1;
643}
644
645
646static
647UINT inc_lock ( /* Increment file open counter and returns its index (0:int error) */
648 DIR* dj, /* Directory object pointing the file to register or increment */
649 int acc /* Desired access mode (0:Read, !0:Write) */
650)
651{
652 UINT i;
653
654
655 for (i = 0; i < _FS_LOCK; i++) { /* Find the file */
656 if (Files[i].fs == dj->fs &&
657 Files[i].clu == dj->sclust &&
658 Files[i].idx == dj->index) break;
659 }
660
661 if (i == _FS_LOCK) { /* Not opened. Register it as new. */
662 for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
663 if (i == _FS_LOCK) return 0; /* No space to register (int err) */
664 Files[i].fs = dj->fs;
665 Files[i].clu = dj->sclust;
666 Files[i].idx = dj->index;
667 Files[i].ctr = 0;
668 }
669
670 if (acc && Files[i].ctr) return 0; /* Access violation (int err) */
671
672 Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */
673
674 return i + 1;
675}
676
677
678static
679FRESULT dec_lock ( /* Decrement file open counter */
680 UINT i /* Semaphore index */
681)
682{
683 WORD n;
684 FRESULT res;
685
686
687 if (--i < _FS_LOCK) {
688 n = Files[i].ctr;
689 if (n == 0x100) n = 0;
690 if (n) n--;
691 Files[i].ctr = n;
692 if (!n) Files[i].fs = 0;
693 res = FR_OK;
694 } else {
695 res = FR_INT_ERR;
696 }
697 return res;
698}
699
700
701static
702void clear_lock ( /* Clear lock entries of the volume */
703 FATFS *fs
704)
705{
706 UINT i;
707
708 for (i = 0; i < _FS_LOCK; i++) {
709 if (Files[i].fs == fs) Files[i].fs = 0;
710 }
711}
712#endif
713
714
715
716/*-----------------------------------------------------------------------*/
717/* Change window offset */
718/*-----------------------------------------------------------------------*/
719
720static
721FRESULT move_window (
722 FATFS *fs, /* File system object */
723 DWORD sector /* Sector number to make appearance in the fs->win[] */
724) /* Move to zero only writes back dirty window */
725{
726 DWORD wsect;
727
728
729 wsect = fs->winsect;
730 if (wsect != sector) { /* Changed current window */
731#if !_FS_READONLY
732 if (fs->wflag) { /* Write back dirty window if needed */
733 if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK)
734 return FR_DISK_ERR;
735 fs->wflag = 0;
736 if (wsect < (fs->fatbase + fs->fsize)) { /* In FAT area */
737 BYTE nf;
738 for (nf = fs->n_fats; nf > 1; nf--) { /* Reflect the change to all FAT copies */
739 wsect += fs->fsize;
740 disk_write(fs->drv, fs->win, wsect, 1);
741 }
742 }
743 }
744#endif
745 if (sector) {
746 if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK)
747 return FR_DISK_ERR;
748 fs->winsect = sector;
749 }
750 }
751
752 return FR_OK;
753}
754
755
756
757
758/*-----------------------------------------------------------------------*/
759/* Clean-up cached data */
760/*-----------------------------------------------------------------------*/
761#if !_FS_READONLY
762static
763FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */
764 FATFS *fs /* File system object */
765)
766{
767 FRESULT res;
768
769
770 res = move_window(fs, 0);
771 if (res == FR_OK) {
772 /* Update FSInfo sector if needed */
773 if (fs->fs_type == FS_FAT32 && fs->fsi_flag) {
774 fs->winsect = 0;
775 /* Create FSInfo structure */
776 mem_set(fs->win, 0, 512);
777 ST_WORD(fs->win+BS_55AA, 0xAA55);
778 ST_DWORD(fs->win+FSI_LeadSig, 0x41615252);
779 ST_DWORD(fs->win+FSI_StrucSig, 0x61417272);
780 ST_DWORD(fs->win+FSI_Free_Count, fs->free_clust);
781 ST_DWORD(fs->win+FSI_Nxt_Free, fs->last_clust);
782 /* Write it into the FSInfo sector */
783 disk_write(fs->drv, fs->win, fs->fsi_sector, 1);
784 fs->fsi_flag = 0;
785 }
786 /* Make sure that no pending write process in the physical drive */
787 if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
788 res = FR_DISK_ERR;
789 }
790
791 return res;
792}
793#endif
794
795
796
797
798/*-----------------------------------------------------------------------*/
799/* Get sector# from cluster# */
800/*-----------------------------------------------------------------------*/
801
802
803DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */
804 FATFS *fs, /* File system object */
805 DWORD clst /* Cluster# to be converted */
806)
807{
808 clst -= 2;
809 if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */
810 return clst * fs->csize + fs->database;
811}
812
813
814
815
816/*-----------------------------------------------------------------------*/
817/* FAT access - Read value of a FAT entry */
818/*-----------------------------------------------------------------------*/
819
820
821DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */
822 FATFS *fs, /* File system object */
823 DWORD clst /* Cluster# to get the link information */
824)
825{
826 UINT wc, bc;
827 BYTE *p;
828
829
830 if (clst < 2 || clst >= fs->n_fatent) /* Check range */
831 return 1;
832
833 switch (fs->fs_type) {
834 case FS_FAT12 :
835 bc = (UINT)clst; bc += bc / 2;
836 if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
837 wc = fs->win[bc % SS(fs)]; bc++;
838 if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break;
839 wc |= fs->win[bc % SS(fs)] << 8;
840 return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
841
842 case FS_FAT16 :
843 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break;
844 p = &fs->win[clst * 2 % SS(fs)];
845 return LD_WORD(p);
846
847 case FS_FAT32 :
848 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break;
849 p = &fs->win[clst * 4 % SS(fs)];
850 return LD_DWORD(p) & 0x0FFFFFFF;
851 }
852
853 return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */
854}
855
856
857
858
859/*-----------------------------------------------------------------------*/
860/* FAT access - Change value of a FAT entry */
861/*-----------------------------------------------------------------------*/
862#if !_FS_READONLY
863
864FRESULT put_fat (
865 FATFS *fs, /* File system object */
866 DWORD clst, /* Cluster# to be changed in range of 2 to fs->n_fatent - 1 */
867 DWORD val /* New value to mark the cluster */
868)
869{
870 UINT bc;
871 BYTE *p;
872 FRESULT res;
873
874
875 if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
876 res = FR_INT_ERR;
877
878 } else {
879 switch (fs->fs_type) {
880 case FS_FAT12 :
881 bc = (UINT)clst; bc += bc / 2;
882 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
883 if (res != FR_OK) break;
884 p = &fs->win[bc % SS(fs)];
885 *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;
886 bc++;
887 fs->wflag = 1;
888 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
889 if (res != FR_OK) break;
890 p = &fs->win[bc % SS(fs)];
891 *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));
892 break;
893
894 case FS_FAT16 :
895 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
896 if (res != FR_OK) break;
897 p = &fs->win[clst * 2 % SS(fs)];
898 ST_WORD(p, (WORD)val);
899 break;
900
901 case FS_FAT32 :
902 res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
903 if (res != FR_OK) break;
904 p = &fs->win[clst * 4 % SS(fs)];
905 val |= LD_DWORD(p) & 0xF0000000;
906 ST_DWORD(p, val);
907 break;
908
909 default :
910 res = FR_INT_ERR;
911 }
912 fs->wflag = 1;
913 }
914
915 return res;
916}
917#endif /* !_FS_READONLY */
918
919
920
921
922/*-----------------------------------------------------------------------*/
923/* FAT handling - Remove a cluster chain */
924/*-----------------------------------------------------------------------*/
925#if !_FS_READONLY
926static
927FRESULT remove_chain (
928 FATFS *fs, /* File system object */
929 DWORD clst /* Cluster# to remove a chain from */
930)
931{
932 FRESULT res;
933 DWORD nxt;
934#if _USE_ERASE
935 DWORD scl = clst, ecl = clst, rt[2];
936#endif
937
938 if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
939 res = FR_INT_ERR;
940
941 } else {
942 res = FR_OK;
943 while (clst < fs->n_fatent) { /* Not a last link? */
944 nxt = get_fat(fs, clst); /* Get cluster status */
945 if (nxt == 0) break; /* Empty cluster? */
946 if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */
947 if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */
948 res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */
949 if (res != FR_OK) break;
950 if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */
951 fs->free_clust++;
952 fs->fsi_flag = 1;
953 }
954#if _USE_ERASE
955 if (ecl + 1 == nxt) { /* Is next cluster contiguous? */
956 ecl = nxt;
957 } else { /* End of contiguous clusters */
958 rt[0] = clust2sect(fs, scl); /* Start sector */
959 rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
960 disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */
961 scl = ecl = nxt;
962 }
963#endif
964 clst = nxt; /* Next cluster */
965 }
966 }
967
968 return res;
969}
970#endif
971
972
973
974
975/*-----------------------------------------------------------------------*/
976/* FAT handling - Stretch or Create a cluster chain */
977/*-----------------------------------------------------------------------*/
978#if !_FS_READONLY
979static
980DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
981 FATFS *fs, /* File system object */
982 DWORD clst /* Cluster# to stretch. 0 means create a new chain. */
983)
984{
985 DWORD cs, ncl, scl;
986 FRESULT res;
987
988
989 if (clst == 0) { /* Create a new chain */
990 scl = fs->last_clust; /* Get suggested start point */
991 if (!scl || scl >= fs->n_fatent) scl = 1;
992 }
993 else { /* Stretch the current chain */
994 cs = get_fat(fs, clst); /* Check the cluster status */
995 if (cs < 2) return 1; /* It is an invalid cluster */
996 if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */
997 scl = clst;
998 }
999
1000 ncl = scl; /* Start cluster */
1001 for (;;) {
1002 ncl++; /* Next cluster */
1003 if (ncl >= fs->n_fatent) { /* Wrap around */
1004 ncl = 2;
1005 if (ncl > scl) return 0; /* No free cluster */
1006 }
1007 cs = get_fat(fs, ncl); /* Get the cluster status */
1008 if (cs == 0) break; /* Found a free cluster */
1009 if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */
1010 return cs;
1011 if (ncl == scl) return 0; /* No free cluster */
1012 }
1013
1014 res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */
1015 if (res == FR_OK && clst != 0) {
1016 res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */
1017 }
1018 if (res == FR_OK) {
1019 fs->last_clust = ncl; /* Update FSINFO */
1020 if (fs->free_clust != 0xFFFFFFFF) {
1021 fs->free_clust--;
1022 fs->fsi_flag = 1;
1023 }
1024 } else {
1025 ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
1026 }
1027
1028 return ncl; /* Return new cluster number or error code */
1029}
1030#endif /* !_FS_READONLY */
1031
1032
1033
1034/*-----------------------------------------------------------------------*/
1035/* FAT handling - Convert offset into cluster with link map table */
1036/*-----------------------------------------------------------------------*/
1037
1038#if _USE_FASTSEEK
1039static
1040DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
1041 FIL* fp, /* Pointer to the file object */
1042 DWORD ofs /* File offset to be converted to cluster# */
1043)
1044{
1045 DWORD cl, ncl, *tbl;
1046
1047
1048 tbl = fp->cltbl + 1; /* Top of CLMT */
1049 cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */
1050 for (;;) {
1051 ncl = *tbl++; /* Number of cluters in the fragment */
1052 if (!ncl) return 0; /* End of table? (error) */
1053 if (cl < ncl) break; /* In this fragment? */
1054 cl -= ncl; tbl++; /* Next fragment */
1055 }
1056 return cl + *tbl; /* Return the cluster number */
1057}
1058#endif /* _USE_FASTSEEK */
1059
1060
1061
1062/*-----------------------------------------------------------------------*/
1063/* Directory handling - Set directory index */
1064/*-----------------------------------------------------------------------*/
1065
1066static
1067FRESULT dir_sdi (
1068 DIR *dj, /* Pointer to directory object */
1069 WORD idx /* Index of directory table */
1070)
1071{
1072 DWORD clst;
1073 WORD ic;
1074
1075
1076 dj->index = idx;
1077 clst = dj->sclust;
1078 if (clst == 1 || clst >= dj->fs->n_fatent) /* Check start cluster range */
1079 return FR_INT_ERR;
1080 if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */
1081 clst = dj->fs->dirbase;
1082
1083 if (clst == 0) { /* Static table (root-dir in FAT12/16) */
1084 dj->clust = clst;
1085 if (idx >= dj->fs->n_rootdir) /* Index is out of range */
1086 return FR_INT_ERR;
1087 dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */
1088 }
1089 else { /* Dynamic table (sub-dirs or root-dir in FAT32) */
1090 ic = SS(dj->fs) / SZ_DIR * dj->fs->csize; /* Entries per cluster */
1091 while (idx >= ic) { /* Follow cluster chain */
1092 clst = get_fat(dj->fs, clst); /* Get next cluster */
1093 if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */
1094 if (clst < 2 || clst >= dj->fs->n_fatent) /* Reached to end of table or int error */
1095 return FR_INT_ERR;
1096 idx -= ic;
1097 }
1098 dj->clust = clst;
1099 dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / SZ_DIR); /* Sector# */
1100 }
1101
1102 dj->dir = dj->fs->win + (idx % (SS(dj->fs) / SZ_DIR)) * SZ_DIR; /* Ptr to the entry in the sector */
1103
1104 return FR_OK; /* Seek succeeded */
1105}
1106
1107
1108
1109
1110/*-----------------------------------------------------------------------*/
1111/* Directory handling - Move directory table index next */
1112/*-----------------------------------------------------------------------*/
1113
1114static
1115FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT and could not stretch */
1116 DIR *dj, /* Pointer to directory object */
1117 int stretch /* 0: Do not stretch table, 1: Stretch table if needed */
1118)
1119{
1120 DWORD clst;
1121 WORD i;
1122
1123
1124 stretch = stretch; /* To suppress warning on read-only cfg. */
1125 i = dj->index + 1;
1126 if (!i || !dj->sect) /* Report EOT when index has reached 65535 */
1127 return FR_NO_FILE;
1128
1129 if (!(i % (SS(dj->fs) / SZ_DIR))) { /* Sector changed? */
1130 dj->sect++; /* Next sector */
1131
1132 if (dj->clust == 0) { /* Static table */
1133 if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */
1134 return FR_NO_FILE;
1135 }
1136 else { /* Dynamic table */
1137 if (((i / (SS(dj->fs) / SZ_DIR)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */
1138 clst = get_fat(dj->fs, dj->clust); /* Get next cluster */
1139 if (clst <= 1) return FR_INT_ERR;
1140 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
1141 if (clst >= dj->fs->n_fatent) { /* When it reached end of dynamic table */
1142#if !_FS_READONLY
1143 BYTE c;
1144 if (!stretch) return FR_NO_FILE; /* When do not stretch, report EOT */
1145 clst = create_chain(dj->fs, dj->clust); /* Stretch cluster chain */
1146 if (clst == 0) return FR_DENIED; /* No free cluster */
1147 if (clst == 1) return FR_INT_ERR;
1148 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
1149 /* Clean-up stretched table */
1150 if (move_window(dj->fs, 0)) return FR_DISK_ERR; /* Flush active window */
1151 mem_set(dj->fs->win, 0, SS(dj->fs)); /* Clear window buffer */
1152 dj->fs->winsect = clust2sect(dj->fs, clst); /* Cluster start sector */
1153 for (c = 0; c < dj->fs->csize; c++) { /* Fill the new cluster with 0 */
1154 dj->fs->wflag = 1;
1155 if (move_window(dj->fs, 0)) return FR_DISK_ERR;
1156 dj->fs->winsect++;
1157 }
1158 dj->fs->winsect -= c; /* Rewind window address */
1159#else
1160 return FR_NO_FILE; /* Report EOT */
1161#endif
1162 }
1163 dj->clust = clst; /* Initialize data for new cluster */
1164 dj->sect = clust2sect(dj->fs, clst);
1165 }
1166 }
1167 }
1168
1169 dj->index = i;
1170 dj->dir = dj->fs->win + (i % (SS(dj->fs) / SZ_DIR)) * SZ_DIR;
1171
1172 return FR_OK;
1173}
1174
1175
1176
1177
1178/*-----------------------------------------------------------------------*/
1179/* Directory handling - Load/Store start cluster number */
1180/*-----------------------------------------------------------------------*/
1181
1182static
1183DWORD ld_clust (
1184 FATFS *fs, /* Pointer to the fs object */
1185 BYTE *dir /* Pointer to the directory entry */
1186)
1187{
1188 DWORD cl;
1189
1190 cl = LD_WORD(dir+DIR_FstClusLO);
1191 if (fs->fs_type == FS_FAT32)
1192 cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16;
1193
1194 return cl;
1195}
1196
1197
1198#if !_FS_READONLY
1199static
1200void st_clust (
1201 BYTE *dir, /* Pointer to the directory entry */
1202 DWORD cl /* Value to be set */
1203)
1204{
1205 ST_WORD(dir+DIR_FstClusLO, cl);
1206 ST_WORD(dir+DIR_FstClusHI, cl >> 16);
1207}
1208#endif
1209
1210
1211
1212/*-----------------------------------------------------------------------*/
1213/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
1214/*-----------------------------------------------------------------------*/
1215#if _USE_LFN
1216static
1217const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN chars in the directory entry */
1218
1219
1220static
1221int cmp_lfn ( /* 1:Matched, 0:Not matched */
1222 WCHAR *lfnbuf, /* Pointer to the LFN to be compared */
1223 BYTE *dir /* Pointer to the directory entry containing a part of LFN */
1224)
1225{
1226 UINT i, s;
1227 WCHAR wc, uc;
1228
1229
1230 i = ((dir[LDIR_Ord] & ~LLE) - 1) * 13; /* Get offset in the LFN buffer */
1231 s = 0; wc = 1;
1232 do {
1233 uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */
1234 if (wc) { /* Last char has not been processed */
1235 wc = ff_wtoupper(uc); /* Convert it to upper case */
1236 if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */
1237 return 0; /* Not matched */
1238 } else {
1239 if (uc != 0xFFFF) return 0; /* Check filler */
1240 }
1241 } while (++s < 13); /* Repeat until all chars in the entry are checked */
1242
1243 if ((dir[LDIR_Ord] & LLE) && wc && lfnbuf[i]) /* Last segment matched but different length */
1244 return 0;
1245
1246 return 1; /* The part of LFN matched */
1247}
1248
1249
1250
1251static
1252int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */
1253 WCHAR *lfnbuf, /* Pointer to the Unicode-LFN buffer */
1254 BYTE *dir /* Pointer to the directory entry */
1255)
1256{
1257 UINT i, s;
1258 WCHAR wc, uc;
1259
1260
1261 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
1262
1263 s = 0; wc = 1;
1264 do {
1265 uc = LD_WORD(dir+LfnOfs[s]); /* Pick an LFN character from the entry */
1266 if (wc) { /* Last char has not been processed */
1267 if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
1268 lfnbuf[i++] = wc = uc; /* Store it */
1269 } else {
1270 if (uc != 0xFFFF) return 0; /* Check filler */
1271 }
1272 } while (++s < 13); /* Read all character in the entry */
1273
1274 if (dir[LDIR_Ord] & LLE) { /* Put terminator if it is the last LFN part */
1275 if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
1276 lfnbuf[i] = 0;
1277 }
1278
1279 return 1;
1280}
1281
1282
1283#if !_FS_READONLY
1284static
1285void fit_lfn (
1286 const WCHAR *lfnbuf, /* Pointer to the LFN buffer */
1287 BYTE *dir, /* Pointer to the directory entry */
1288 BYTE ord, /* LFN order (1-20) */
1289 BYTE sum /* SFN sum */
1290)
1291{
1292 UINT i, s;
1293 WCHAR wc;
1294
1295
1296 dir[LDIR_Chksum] = sum; /* Set check sum */
1297 dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */
1298 dir[LDIR_Type] = 0;
1299 ST_WORD(dir+LDIR_FstClusLO, 0);
1300
1301 i = (ord - 1) * 13; /* Get offset in the LFN buffer */
1302 s = wc = 0;
1303 do {
1304 if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */
1305 ST_WORD(dir+LfnOfs[s], wc); /* Put it */
1306 if (!wc) wc = 0xFFFF; /* Padding chars following last char */
1307 } while (++s < 13);
1308 if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLE; /* Bottom LFN part is the start of LFN sequence */
1309 dir[LDIR_Ord] = ord; /* Set the LFN order */
1310}
1311
1312#endif
1313#endif
1314
1315
1316
1317/*-----------------------------------------------------------------------*/
1318/* Create numbered name */
1319/*-----------------------------------------------------------------------*/
1320#if _USE_LFN
1321void gen_numname (
1322 BYTE *dst, /* Pointer to generated SFN */
1323 const BYTE *src, /* Pointer to source SFN to be modified */
1324 const WCHAR *lfn, /* Pointer to LFN */
1325 WORD seq /* Sequence number */
1326)
1327{
1328 BYTE ns[8], c;
1329 UINT i, j;
1330
1331
1332 mem_cpy(dst, src, 11);
1333
1334 if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */
1335 do seq = (seq >> 1) + (seq << 15) + (WORD)*lfn++; while (*lfn);
1336 }
1337
1338 /* itoa (hexdecimal) */
1339 i = 7;
1340 do {
1341 c = (seq % 16) + '0';
1342 if (c > '9') c += 7;
1343 ns[i--] = c;
1344 seq /= 16;
1345 } while (seq);
1346 ns[i] = '~';
1347
1348 /* Append the number */
1349 for (j = 0; j < i && dst[j] != ' '; j++) {
1350 if (IsDBCS1(dst[j])) {
1351 if (j == i - 1) break;
1352 j++;
1353 }
1354 }
1355 do {
1356 dst[j++] = (i < 8) ? ns[i++] : ' ';
1357 } while (j < 8);
1358}
1359#endif
1360
1361
1362
1363
1364/*-----------------------------------------------------------------------*/
1365/* Calculate sum of an SFN */
1366/*-----------------------------------------------------------------------*/
1367#if _USE_LFN
1368static
1369BYTE sum_sfn (
1370 const BYTE *dir /* Ptr to directory entry */
1371)
1372{
1373 BYTE sum = 0;
1374 UINT n = 11;
1375
1376 do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
1377 return sum;
1378}
1379#endif
1380
1381
1382
1383
1384/*-----------------------------------------------------------------------*/
1385/* Directory handling - Find an object in the directory */
1386/*-----------------------------------------------------------------------*/
1387
1388static
1389FRESULT dir_find (
1390 DIR *dj /* Pointer to the directory object linked to the file name */
1391)
1392{
1393 FRESULT res;
1394 BYTE c, *dir;
1395#if _USE_LFN
1396 BYTE a, ord, sum;
1397#endif
1398
1399 res = dir_sdi(dj, 0); /* Rewind directory object */
1400 if (res != FR_OK) return res;
1401
1402#if _USE_LFN
1403 ord = sum = 0xFF;
1404#endif
1405 do {
1406 res = move_window(dj->fs, dj->sect);
1407 if (res != FR_OK) break;
1408 dir = dj->dir; /* Ptr to the directory entry of current index */
1409 c = dir[DIR_Name];
1410 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
1411#if _USE_LFN /* LFN configuration */
1412 a = dir[DIR_Attr] & AM_MASK;
1413 if (c == DDE || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
1414 ord = 0xFF;
1415 } else {
1416 if (a == AM_LFN) { /* An LFN entry is found */
1417 if (dj->lfn) {
1418 if (c & LLE) { /* Is it start of LFN sequence? */
1419 sum = dir[LDIR_Chksum];
1420 c &= ~LLE; ord = c; /* LFN start order */
1421 dj->lfn_idx = dj->index;
1422 }
1423 /* Check validity of the LFN entry and compare it with given name */
1424 ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
1425 }
1426 } else { /* An SFN entry is found */
1427 if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */
1428 ord = 0xFF; dj->lfn_idx = 0xFFFF; /* Reset LFN sequence */
1429 if (!(dj->fn[NS] & NS_LOSS) && !mem_cmp(dir, dj->fn, 11)) break; /* SFN matched? */
1430 }
1431 }
1432#else /* Non LFN configuration */
1433 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */
1434 break;
1435#endif
1436 res = dir_next(dj, 0); /* Next entry */
1437 } while (res == FR_OK);
1438
1439 return res;
1440}
1441
1442
1443
1444
1445/*-----------------------------------------------------------------------*/
1446/* Read an object from the directory */
1447/*-----------------------------------------------------------------------*/
1448#if _FS_MINIMIZE <= 1
1449static
1450FRESULT dir_read (
1451 DIR *dj /* Pointer to the directory object that pointing the entry to be read */
1452)
1453{
1454 FRESULT res;
1455 BYTE c, *dir;
1456#if _USE_LFN
1457 BYTE a, ord = 0xFF, sum = 0xFF;
1458#endif
1459
1460 res = FR_NO_FILE;
1461 while (dj->sect) {
1462 res = move_window(dj->fs, dj->sect);
1463 if (res != FR_OK) break;
1464 dir = dj->dir; /* Ptr to the directory entry of current index */
1465 c = dir[DIR_Name];
1466 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
1467#if _USE_LFN /* LFN configuration */
1468 a = dir[DIR_Attr] & AM_MASK;
1469 if (c == DDE || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
1470 ord = 0xFF;
1471 } else {
1472 if (a == AM_LFN) { /* An LFN entry is found */
1473 if (c & LLE) { /* Is it start of LFN sequence? */
1474 sum = dir[LDIR_Chksum];
1475 c &= ~LLE; ord = c;
1476 dj->lfn_idx = dj->index;
1477 }
1478 /* Check LFN validity and capture it */
1479 ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dj->lfn, dir)) ? ord - 1 : 0xFF;
1480 } else { /* An SFN entry is found */
1481 if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */
1482 dj->lfn_idx = 0xFFFF; /* It has no LFN. */
1483 break;
1484 }
1485 }
1486#else /* Non LFN configuration */
1487 if (c != DDE && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */
1488 break;
1489#endif
1490 res = dir_next(dj, 0); /* Next entry */
1491 if (res != FR_OK) break;
1492 }
1493
1494 if (res != FR_OK) dj->sect = 0;
1495
1496 return res;
1497}
1498#endif
1499
1500
1501
1502/*-----------------------------------------------------------------------*/
1503/* Register an object to the directory */
1504/*-----------------------------------------------------------------------*/
1505#if !_FS_READONLY
1506static
1507FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */
1508 DIR *dj /* Target directory with object name to be created */
1509)
1510{
1511 FRESULT res;
1512 BYTE c, *dir;
1513#if _USE_LFN /* LFN configuration */
1514 WORD n, ne, is;
1515 BYTE sn[12], *fn, sum;
1516 WCHAR *lfn;
1517
1518
1519 fn = dj->fn; lfn = dj->lfn;
1520 mem_cpy(sn, fn, 12);
1521
1522 if (_FS_RPATH && (sn[NS] & NS_DOT)) /* Cannot create dot entry */
1523 return FR_INVALID_NAME;
1524
1525 if (sn[NS] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */
1526 fn[NS] = 0; dj->lfn = 0; /* Find only SFN */
1527 for (n = 1; n < 100; n++) {
1528 gen_numname(fn, sn, lfn, n); /* Generate a numbered name */
1529 res = dir_find(dj); /* Check if the name collides with existing SFN */
1530 if (res != FR_OK) break;
1531 }
1532 if (n == 100) return FR_DENIED; /* Abort if too many collisions */
1533 if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */
1534 fn[NS] = sn[NS]; dj->lfn = lfn;
1535 }
1536
1537 if (sn[NS] & NS_LFN) { /* When LFN is to be created, reserve an SFN + LFN entries. */
1538 for (ne = 0; lfn[ne]; ne++) ;
1539 ne = (ne + 25) / 13;
1540 } else { /* Otherwise reserve only an SFN entry. */
1541 ne = 1;
1542 }
1543
1544 /* Reserve contiguous entries */
1545 res = dir_sdi(dj, 0);
1546 if (res != FR_OK) return res;
1547 n = is = 0;
1548 do {
1549 res = move_window(dj->fs, dj->sect);
1550 if (res != FR_OK) break;
1551 c = *dj->dir; /* Check the entry status */
1552 if (c == DDE || c == 0) { /* Is it a blank entry? */
1553 if (n == 0) is = dj->index; /* First index of the contiguous entry */
1554 if (++n == ne) break; /* A contiguous entry that required count is found */
1555 } else {
1556 n = 0; /* Not a blank entry. Restart to search */
1557 }
1558 res = dir_next(dj, 1); /* Next entry with table stretch */
1559 } while (res == FR_OK);
1560
1561 if (res == FR_OK && ne > 1) { /* Initialize LFN entry if needed */
1562 res = dir_sdi(dj, is);
1563 if (res == FR_OK) {
1564 sum = sum_sfn(dj->fn); /* Sum of the SFN tied to the LFN */
1565 ne--;
1566 do { /* Store LFN entries in bottom first */
1567 res = move_window(dj->fs, dj->sect);
1568 if (res != FR_OK) break;
1569 fit_lfn(dj->lfn, dj->dir, (BYTE)ne, sum);
1570 dj->fs->wflag = 1;
1571 res = dir_next(dj, 0); /* Next entry */
1572 } while (res == FR_OK && --ne);
1573 }
1574 }
1575
1576#else /* Non LFN configuration */
1577 res = dir_sdi(dj, 0);
1578 if (res == FR_OK) {
1579 do { /* Find a blank entry for the SFN */
1580 res = move_window(dj->fs, dj->sect);
1581 if (res != FR_OK) break;
1582 c = *dj->dir;
1583 if (c == DDE || c == 0) break; /* Is it a blank entry? */
1584 res = dir_next(dj, 1); /* Next entry with table stretch */
1585 } while (res == FR_OK);
1586 }
1587#endif
1588
1589 if (res == FR_OK) { /* Initialize the SFN entry */
1590 res = move_window(dj->fs, dj->sect);
1591 if (res == FR_OK) {
1592 dir = dj->dir;
1593 mem_set(dir, 0, SZ_DIR); /* Clean the entry */
1594 mem_cpy(dir, dj->fn, 11); /* Put SFN */
1595#if _USE_LFN
1596 dir[DIR_NTres] = *(dj->fn+NS) & (NS_BODY | NS_EXT); /* Put NT flag */
1597#endif
1598 dj->fs->wflag = 1;
1599 }
1600 }
1601
1602 return res;
1603}
1604#endif /* !_FS_READONLY */
1605
1606
1607
1608
1609/*-----------------------------------------------------------------------*/
1610/* Remove an object from the directory */
1611/*-----------------------------------------------------------------------*/
1612#if !_FS_READONLY && !_FS_MINIMIZE
1613static
1614FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */
1615 DIR *dj /* Directory object pointing the entry to be removed */
1616)
1617{
1618 FRESULT res;
1619#if _USE_LFN /* LFN configuration */
1620 WORD i;
1621
1622 i = dj->index; /* SFN index */
1623 res = dir_sdi(dj, (WORD)((dj->lfn_idx == 0xFFFF) ? i : dj->lfn_idx)); /* Goto the SFN or top of the LFN entries */
1624 if (res == FR_OK) {
1625 do {
1626 res = move_window(dj->fs, dj->sect);
1627 if (res != FR_OK) break;
1628 *dj->dir = DDE; /* Mark the entry "deleted" */
1629 dj->fs->wflag = 1;
1630 if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */
1631 res = dir_next(dj, 0); /* Next entry */
1632 } while (res == FR_OK);
1633 if (res == FR_NO_FILE) res = FR_INT_ERR;
1634 }
1635
1636#else /* Non LFN configuration */
1637 res = dir_sdi(dj, dj->index);
1638 if (res == FR_OK) {
1639 res = move_window(dj->fs, dj->sect);
1640 if (res == FR_OK) {
1641 *dj->dir = DDE; /* Mark the entry "deleted" */
1642 dj->fs->wflag = 1;
1643 }
1644 }
1645#endif
1646
1647 return res;
1648}
1649#endif /* !_FS_READONLY */
1650
1651
1652
1653
1654/*-----------------------------------------------------------------------*/
1655/* Pick a segment and create the object name in directory form */
1656/*-----------------------------------------------------------------------*/
1657
1658static
1659FRESULT create_name (
1660 DIR *dj, /* Pointer to the directory object */
1661 const TCHAR **path /* Pointer to pointer to the segment in the path string */
1662)
1663{
1664#ifdef _EXCVT
1665 static const BYTE excvt[] = _EXCVT; /* Upper conversion table for extended chars */
1666#endif
1667
1668#if _USE_LFN /* LFN configuration */
1669 BYTE b, cf;
1670 WCHAR w, *lfn;
1671 UINT i, ni, si, di;
1672 const TCHAR *p;
1673
1674 /* Create LFN in Unicode */
1675 for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
1676 lfn = dj->lfn;
1677 si = di = 0;
1678 for (;;) {
1679 w = p[si++]; /* Get a character */
1680 if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */
1681 if (di >= _MAX_LFN) /* Reject too long name */
1682 return FR_INVALID_NAME;
1683#if !_LFN_UNICODE
1684 w &= 0xFF;
1685 if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
1686 b = (BYTE)p[si++]; /* Get 2nd byte */
1687 if (!IsDBCS2(b))
1688 return FR_INVALID_NAME; /* Reject invalid sequence */
1689 w = (w << 8) + b; /* Create a DBC */
1690 }
1691 w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */
1692 if (!w) return FR_INVALID_NAME; /* Reject invalid code */
1693#endif
1694 if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal chars for LFN */
1695 return FR_INVALID_NAME;
1696 lfn[di++] = w; /* Store the Unicode char */
1697 }
1698 *path = &p[si]; /* Return pointer to the next segment */
1699 cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
1700#if _FS_RPATH
1701 if ((di == 1 && lfn[di-1] == '.') || /* Is this a dot entry? */
1702 (di == 2 && lfn[di-1] == '.' && lfn[di-2] == '.')) {
1703 lfn[di] = 0;
1704 for (i = 0; i < 11; i++)
1705 dj->fn[i] = (i < di) ? '.' : ' ';
1706 dj->fn[i] = cf | NS_DOT; /* This is a dot entry */
1707 return FR_OK;
1708 }
1709#endif
1710 while (di) { /* Strip trailing spaces and dots */
1711 w = lfn[di-1];
1712 if (w != ' ' && w != '.') break;
1713 di--;
1714 }
1715 if (!di) return FR_INVALID_NAME; /* Reject nul string */
1716
1717 lfn[di] = 0; /* LFN is created */
1718
1719 /* Create SFN in directory form */
1720 mem_set(dj->fn, ' ', 11);
1721 for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */
1722 if (si) cf |= NS_LOSS | NS_LFN;
1723 while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
1724
1725 b = i = 0; ni = 8;
1726 for (;;) {
1727 w = lfn[si++]; /* Get an LFN char */
1728 if (!w) break; /* Break on end of the LFN */
1729 if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */
1730 cf |= NS_LOSS | NS_LFN; continue;
1731 }
1732
1733 if (i >= ni || si == di) { /* Extension or end of SFN */
1734 if (ni == 11) { /* Long extension */
1735 cf |= NS_LOSS | NS_LFN; break;
1736 }
1737 if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */
1738 if (si > di) break; /* No extension */
1739 si = di; i = 8; ni = 11; /* Enter extension section */
1740 b <<= 2; continue;
1741 }
1742
1743 if (w >= 0x80) { /* Non ASCII char */
1744#ifdef _EXCVT
1745 w = ff_convert(w, 0); /* Unicode -> OEM code */
1746 if (w) w = excvt[w - 0x80]; /* Convert extended char to upper (SBCS) */
1747#else
1748 w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */
1749#endif
1750 cf |= NS_LFN; /* Force create LFN entry */
1751 }
1752
1753 if (_DF1S && w >= 0x100) { /* Double byte char (always false on SBCS cfg) */
1754 if (i >= ni - 1) {
1755 cf |= NS_LOSS | NS_LFN; i = ni; continue;
1756 }
1757 dj->fn[i++] = (BYTE)(w >> 8);
1758 } else { /* Single byte char */
1759 if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal chars for SFN */
1760 w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
1761 } else {
1762 if (IsUpper(w)) { /* ASCII large capital */
1763 b |= 2;
1764 } else {
1765 if (IsLower(w)) { /* ASCII small capital */
1766 b |= 1; w -= 0x20;
1767 }
1768 }
1769 }
1770 }
1771 dj->fn[i++] = (BYTE)w;
1772 }
1773
1774 if (dj->fn[0] == DDE) dj->fn[0] = NDDE; /* If the first char collides with deleted mark, replace it with 0x05 */
1775
1776 if (ni == 8) b <<= 2;
1777 if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */
1778 cf |= NS_LFN;
1779 if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */
1780 if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */
1781 if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */
1782 }
1783
1784 dj->fn[NS] = cf; /* SFN is created */
1785
1786 return FR_OK;
1787
1788
1789#else /* Non-LFN configuration */
1790 BYTE b, c, d, *sfn;
1791 UINT ni, si, i;
1792 const char *p;
1793
1794 /* Create file name in directory form */
1795 for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
1796 sfn = dj->fn;
1797 mem_set(sfn, ' ', 11);
1798 si = i = b = 0; ni = 8;
1799#if _FS_RPATH
1800 if (p[si] == '.') { /* Is this a dot entry? */
1801 for (;;) {
1802 c = (BYTE)p[si++];
1803 if (c != '.' || si >= 3) break;
1804 sfn[i++] = c;
1805 }
1806 if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
1807 *path = &p[si]; /* Return pointer to the next segment */
1808 sfn[NS] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */
1809 return FR_OK;
1810 }
1811#endif
1812 for (;;) {
1813 c = (BYTE)p[si++];
1814 if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */
1815 if (c == '.' || i >= ni) {
1816 if (ni != 8 || c != '.') return FR_INVALID_NAME;
1817 i = 8; ni = 11;
1818 b <<= 2; continue;
1819 }
1820 if (c >= 0x80) { /* Extended char? */
1821 b |= 3; /* Eliminate NT flag */
1822#ifdef _EXCVT
1823 c = excvt[c - 0x80]; /* Upper conversion (SBCS) */
1824#else
1825#if !_DF1S /* ASCII only cfg */
1826 return FR_INVALID_NAME;
1827#endif
1828#endif
1829 }
1830 if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
1831 d = (BYTE)p[si++]; /* Get 2nd byte */
1832 if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
1833 return FR_INVALID_NAME;
1834 sfn[i++] = c;
1835 sfn[i++] = d;
1836 } else { /* Single byte code */
1837 if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */
1838 return FR_INVALID_NAME;
1839 if (IsUpper(c)) { /* ASCII large capital? */
1840 b |= 2;
1841 } else {
1842 if (IsLower(c)) { /* ASCII small capital? */
1843 b |= 1; c -= 0x20;
1844 }
1845 }
1846 sfn[i++] = c;
1847 }
1848 }
1849 *path = &p[si]; /* Return pointer to the next segment */
1850 c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
1851
1852 if (!i) return FR_INVALID_NAME; /* Reject nul string */
1853 if (sfn[0] == DDE) sfn[0] = NDDE; /* When first char collides with DDE, replace it with 0x05 */
1854
1855 if (ni == 8) b <<= 2;
1856 if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */
1857 if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */
1858
1859 sfn[NS] = c; /* Store NT flag, File name is created */
1860
1861 return FR_OK;
1862#endif
1863}
1864
1865
1866
1867
1868/*-----------------------------------------------------------------------*/
1869/* Get file information from directory entry */
1870/*-----------------------------------------------------------------------*/
1871#if _FS_MINIMIZE <= 1
1872static
1873void get_fileinfo ( /* No return code */
1874 DIR *dj, /* Pointer to the directory object */
1875 FILINFO *fno /* Pointer to the file information to be filled */
1876)
1877{
1878 UINT i;
1879 BYTE nt, *dir;
1880 TCHAR *p, c;
1881
1882
1883 p = fno->fname;
1884 if (dj->sect) {
1885 dir = dj->dir;
1886 nt = dir[DIR_NTres]; /* NT flag */
1887 for (i = 0; i < 8; i++) { /* Copy name body */
1888 c = dir[i];
1889 if (c == ' ') break;
1890 if (c == NDDE) c = (TCHAR)DDE;
1891 if (_USE_LFN && (nt & NS_BODY) && IsUpper(c)) c += 0x20;
1892#if _LFN_UNICODE
1893 if (IsDBCS1(c) && i < 7 && IsDBCS2(dir[i+1]))
1894 c = (c << 8) | dir[++i];
1895 c = ff_convert(c, 1);
1896 if (!c) c = '?';
1897#endif
1898 *p++ = c;
1899 }
1900 if (dir[8] != ' ') { /* Copy name extension */
1901 *p++ = '.';
1902 for (i = 8; i < 11; i++) {
1903 c = dir[i];
1904 if (c == ' ') break;
1905 if (_USE_LFN && (nt & NS_EXT) && IsUpper(c)) c += 0x20;
1906#if _LFN_UNICODE
1907 if (IsDBCS1(c) && i < 10 && IsDBCS2(dir[i+1]))
1908 c = (c << 8) | dir[++i];
1909 c = ff_convert(c, 1);
1910 if (!c) c = '?';
1911#endif
1912 *p++ = c;
1913 }
1914 }
1915 fno->fattrib = dir[DIR_Attr]; /* Attribute */
1916 fno->fsize = LD_DWORD(dir+DIR_FileSize); /* Size */
1917 fno->fdate = LD_WORD(dir+DIR_WrtDate); /* Date */
1918 fno->ftime = LD_WORD(dir+DIR_WrtTime); /* Time */
1919 }
1920 *p = 0; /* Terminate SFN str by a \0 */
1921
1922#if _USE_LFN
1923 if (fno->lfname && fno->lfsize) {
1924 TCHAR *tp = fno->lfname;
1925 WCHAR w, *lfn;
1926
1927 i = 0;
1928 if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */
1929 lfn = dj->lfn;
1930 while ((w = *lfn++) != 0) { /* Get an LFN char */
1931#if !_LFN_UNICODE
1932 w = ff_convert(w, 0); /* Unicode -> OEM conversion */
1933 if (!w) { i = 0; break; } /* Could not convert, no LFN */
1934 if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */
1935 tp[i++] = (TCHAR)(w >> 8);
1936#endif
1937 if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overflow, no LFN */
1938 tp[i++] = (TCHAR)w;
1939 }
1940 }
1941 tp[i] = 0; /* Terminate the LFN str by a \0 */
1942 }
1943#endif
1944}
1945#endif /* _FS_MINIMIZE <= 1 */
1946
1947
1948
1949
1950/*-----------------------------------------------------------------------*/
1951/* Follow a file path */
1952/*-----------------------------------------------------------------------*/
1953
1954static
1955FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
1956 DIR *dj, /* Directory object to return last directory and found object */
1957 const TCHAR *path /* Full-path string to find a file or directory */
1958)
1959{
1960 FRESULT res;
1961 BYTE *dir, ns;
1962
1963
1964#if _FS_RPATH
1965 if (*path == '/' || *path == '\\') { /* There is a heading separator */
1966 path++; dj->sclust = 0; /* Strip it and start from the root dir */
1967 } else { /* No heading separator */
1968 dj->sclust = dj->fs->cdir; /* Start from the current dir */
1969 }
1970#else
1971 if (*path == '/' || *path == '\\') /* Strip heading separator if exist */
1972 path++;
1973 dj->sclust = 0; /* Start from the root dir */
1974#endif
1975
1976 if ((UINT)*path < ' ') { /* Nul path means the start directory itself */
1977 res = dir_sdi(dj, 0);
1978 dj->dir = 0;
1979 } else { /* Follow path */
1980 for (;;) {
1981 res = create_name(dj, &path); /* Get a segment */
1982 if (res != FR_OK) break;
1983 res = dir_find(dj); /* Find it */
1984 ns = *(dj->fn+NS);
1985 if (res != FR_OK) { /* Failed to find the object */
1986 if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */
1987 /* Object not found */
1988 if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */
1989 dj->sclust = 0; dj->dir = 0; /* It is the root dir */
1990 res = FR_OK;
1991 if (!(ns & NS_LAST)) continue;
1992 } else { /* Could not find the object */
1993 if (!(ns & NS_LAST)) res = FR_NO_PATH;
1994 }
1995 break;
1996 }
1997 if (ns & NS_LAST) break; /* Last segment match. Function completed. */
1998 dir = dj->dir; /* There is next segment. Follow the sub directory */
1999 if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
2000 res = FR_NO_PATH; break;
2001 }
2002 dj->sclust = ld_clust(dj->fs, dir);
2003 }
2004 }
2005
2006 return res;
2007}
2008
2009
2010
2011
2012/*-----------------------------------------------------------------------*/
2013/* Load a sector and check if it is an FAT Volume Boot Record */
2014/*-----------------------------------------------------------------------*/
2015
2016static
2017BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */
2018 FATFS *fs, /* File system object */
2019 DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
2020)
2021{
2022 if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) /* Load boot record */
2023 return 3;
2024 if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */
2025 return 2;
2026
2027 if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */
2028 return 0;
2029 if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)
2030 return 0;
2031
2032 return 1;
2033}
2034
2035
2036
2037
2038/*-----------------------------------------------------------------------*/
2039/* Check if the file system object is valid or not */
2040/*-----------------------------------------------------------------------*/
2041
2042static
2043FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
2044 const TCHAR **path, /* Pointer to pointer to the path name (drive number) */
2045 FATFS **rfs, /* Pointer to pointer to the found file system object */
2046 BYTE wmode /* !=0: Check write protection for write access */
2047)
2048{
2049 BYTE fmt, b, pi, *tbl;
2050 UINT vol;
2051 DSTATUS stat;
2052 DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
2053 WORD nrsv;
2054 const TCHAR *p = *path;
2055 FATFS *fs;
2056
2057
2058 /* Get logical drive number from the path name */
2059 vol = p[0] - '0'; /* Is there a drive number? */
2060 if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */
2061 p += 2; *path = p; /* Return pointer to the path name */
2062 } else { /* No drive number is given */
2063#if _FS_RPATH
2064 vol = CurrVol; /* Use current drive */
2065#else
2066 vol = 0; /* Use drive 0 */
2067#endif
2068 }
2069
2070 /* Check if the file system object is valid or not */
2071 *rfs = 0;
2072 if (vol >= _VOLUMES) /* Is the drive number valid? */
2073 return FR_INVALID_DRIVE;
2074 fs = FatFs[vol]; /* Get corresponding file system object */
2075 if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
2076
2077 ENTER_FF(fs); /* Lock file system */
2078
2079 *rfs = fs; /* Return pointer to the corresponding file system object */
2080 if (fs->fs_type) { /* If the volume has been mounted */
2081 stat = disk_status(fs->drv);
2082 if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */
2083 if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */
2084 return FR_WRITE_PROTECTED;
2085 return FR_OK; /* The file system object is valid */
2086 }
2087 }
2088
2089 /* The file system object is not valid. */
2090 /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
2091
2092 fs->fs_type = 0; /* Clear the file system object */
2093 fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
2094 stat = disk_initialize(fs->drv); /* Initialize the physical drive */
2095 if (stat & STA_NOINIT) /* Check if the initialization succeeded */
2096 return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
2097 if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */
2098 return FR_WRITE_PROTECTED;
2099#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */
2100 if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
2101 return FR_DISK_ERR;
2102#endif
2103 /* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */
2104 fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */
2105 if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */
2106 if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */
2107 /* Check the partition listed in the partition table */
2108 pi = LD2PT(vol);
2109 if (pi) pi--;
2110 tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
2111 if (tbl[4]) { /* Is the partition existing? */
2112 bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */
2113 fmt = check_fs(fs, bsect); /* Check the partition */
2114 }
2115 }
2116 if (fmt == 3) return FR_DISK_ERR;
2117 if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
2118
2119 /* An FAT volume is found. Following code initializes the file system object */
2120
2121 if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */
2122 return FR_NO_FILESYSTEM;
2123
2124 fasize = LD_WORD(fs->win+BPB_FATSz16); /* Number of sectors per FAT */
2125 if (!fasize) fasize = LD_DWORD(fs->win+BPB_FATSz32);
2126 fs->fsize = fasize;
2127
2128 fs->n_fats = b = fs->win[BPB_NumFATs]; /* Number of FAT copies */
2129 if (b != 1 && b != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
2130 fasize *= b; /* Number of sectors for FAT area */
2131
2132 fs->csize = b = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
2133 if (!b || (b & (b - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */
2134
2135 fs->n_rootdir = LD_WORD(fs->win+BPB_RootEntCnt); /* Number of root directory entries */
2136 if (fs->n_rootdir % (SS(fs) / SZ_DIR)) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be sector aligned) */
2137
2138 tsect = LD_WORD(fs->win+BPB_TotSec16); /* Number of sectors on the volume */
2139 if (!tsect) tsect = LD_DWORD(fs->win+BPB_TotSec32);
2140
2141 nrsv = LD_WORD(fs->win+BPB_RsvdSecCnt); /* Number of reserved sectors */
2142 if (!nrsv) return FR_NO_FILESYSTEM; /* (BPB_RsvdSecCnt must not be 0) */
2143
2144 /* Determine the FAT sub type */
2145 sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIR); /* RSV+FAT+DIR */
2146 if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
2147 nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
2148 if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
2149 fmt = FS_FAT12;
2150 if (nclst >= MIN_FAT16) fmt = FS_FAT16;
2151 if (nclst >= MIN_FAT32) fmt = FS_FAT32;
2152
2153 /* Boundaries and Limits */
2154 fs->n_fatent = nclst + 2; /* Number of FAT entries */
2155 fs->database = bsect + sysect; /* Data start sector */
2156 fs->fatbase = bsect + nrsv; /* FAT start sector */
2157 if (fmt == FS_FAT32) {
2158 if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
2159 fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */
2160 szbfat = fs->n_fatent * 4; /* (Required FAT size) */
2161 } else {
2162 if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
2163 fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
2164 szbfat = (fmt == FS_FAT16) ? /* (Required FAT size) */
2165 fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
2166 }
2167 if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than required) */
2168 return FR_NO_FILESYSTEM;
2169
2170#if !_FS_READONLY
2171 /* Initialize cluster allocation information */
2172 fs->free_clust = 0xFFFFFFFF;
2173 fs->last_clust = 0;
2174
2175 /* Get fsinfo if available */
2176 if (fmt == FS_FAT32) {
2177 fs->fsi_flag = 0;
2178 fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo);
2179 if (disk_read(fs->drv, fs->win, fs->fsi_sector, 1) == RES_OK &&
2180 LD_WORD(fs->win+BS_55AA) == 0xAA55 &&
2181 LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 &&
2182 LD_DWORD(fs->win+FSI_StrucSig) == 0x61417272) {
2183 fs->last_clust = LD_DWORD(fs->win+FSI_Nxt_Free);
2184 fs->free_clust = LD_DWORD(fs->win+FSI_Free_Count);
2185 }
2186 }
2187#endif
2188 fs->fs_type = fmt; /* FAT sub-type */
2189 fs->id = ++Fsid; /* File system mount ID */
2190 fs->winsect = 0; /* Invalidate sector cache */
2191 fs->wflag = 0;
2192#if _FS_RPATH
2193 fs->cdir = 0; /* Current directory (root dir) */
2194#endif
2195#if _FS_LOCK /* Clear file lock semaphores */
2196 clear_lock(fs);
2197#endif
2198
2199 return FR_OK;
2200}
2201
2202
2203
2204
2205/*-----------------------------------------------------------------------*/
2206/* Check if the file/dir object is valid or not */
2207/*-----------------------------------------------------------------------*/
2208
2209static
2210FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
2211 void* obj /* Pointer to the object FIL/DIR to check validity */
2212)
2213{
2214 FIL *fil;
2215
2216
2217 fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */
2218 if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
2219 return FR_INVALID_OBJECT;
2220
2221 ENTER_FF(fil->fs); /* Lock file system */
2222
2223 if (disk_status(fil->fs->drv) & STA_NOINIT)
2224 return FR_NOT_READY;
2225
2226 return FR_OK;
2227}
2228
2229
2230
2231
2232/*--------------------------------------------------------------------------
2233
2234 Public Functions
2235
2236--------------------------------------------------------------------------*/
2237
2238
2239
2240/*-----------------------------------------------------------------------*/
2241/* Mount/Unmount a Logical Drive */
2242/*-----------------------------------------------------------------------*/
2243
2244FRESULT f_mount (
2245 BYTE vol, /* Logical drive number to be mounted/unmounted */
2246 FATFS *fs /* Pointer to new file system object (NULL for unmount)*/
2247)
2248{
2249 FATFS *rfs;
2250
2251
2252 if (vol >= _VOLUMES) /* Check if the drive number is valid */
2253 return FR_INVALID_DRIVE;
2254 rfs = FatFs[vol]; /* Get current fs object */
2255
2256 if (rfs) {
2257#if _FS_LOCK
2258 clear_lock(rfs);
2259#endif
2260#if _FS_REENTRANT /* Discard sync object of the current volume */
2261 if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
2262#endif
2263 rfs->fs_type = 0; /* Clear old fs object */
2264 }
2265
2266 if (fs) {
2267 fs->fs_type = 0; /* Clear new fs object */
2268#if _FS_REENTRANT /* Create sync object for the new volume */
2269 if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
2270#endif
2271 }
2272 FatFs[vol] = fs; /* Register new fs object */
2273
2274 return FR_OK;
2275}
2276
2277
2278
2279
2280/*-----------------------------------------------------------------------*/
2281/* Open or Create a File */
2282/*-----------------------------------------------------------------------*/
2283
2284FRESULT f_open (
2285 FIL *fp, /* Pointer to the blank file object */
2286 const TCHAR *path, /* Pointer to the file name */
2287 BYTE mode /* Access mode and file open mode flags */
2288)
2289{
2290 FRESULT res;
2291 DIR dj;
2292 BYTE *dir;
2293 DEF_NAMEBUF;
2294
2295
2296 if (!fp) return FR_INVALID_OBJECT;
2297 fp->fs = 0; /* Clear file object */
2298
2299#if !_FS_READONLY
2300 mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW;
2301 res = chk_mounted(&path, &dj.fs, (BYTE)(mode & ~FA_READ));
2302#else
2303 mode &= FA_READ;
2304 res = chk_mounted(&path, &dj.fs, 0);
2305#endif
2306 if (res == FR_OK) {
2307 INIT_BUF(dj);
2308 res = follow_path(&dj, path); /* Follow the file path */
2309 dir = dj.dir;
2310#if !_FS_READONLY /* R/W configuration */
2311 if (res == FR_OK) {
2312 if (!dir) /* Current dir itself */
2313 res = FR_INVALID_NAME;
2314#if _FS_LOCK
2315 else
2316 res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
2317#endif
2318 }
2319 /* Create or Open a file */
2320 if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
2321 DWORD dw, cl;
2322
2323 if (res != FR_OK) { /* No file, create new */
2324 if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
2325#if _FS_LOCK
2326 res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
2327#else
2328 res = dir_register(&dj);
2329#endif
2330 mode |= FA_CREATE_ALWAYS; /* File is created */
2331 dir = dj.dir; /* New entry */
2332 }
2333 else { /* Any object is already existing */
2334 if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
2335 res = FR_DENIED;
2336 } else {
2337 if (mode & FA_CREATE_NEW) /* Cannot create as new file */
2338 res = FR_EXIST;
2339 }
2340 }
2341 if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
2342 dw = get_fattime(); /* Created time */
2343 ST_DWORD(dir+DIR_CrtTime, dw);
2344 dir[DIR_Attr] = 0; /* Reset attribute */
2345 ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */
2346 cl = ld_clust(dj.fs, dir); /* Get start cluster */
2347 st_clust(dir, 0); /* cluster = 0 */
2348 dj.fs->wflag = 1;
2349 if (cl) { /* Remove the cluster chain if exist */
2350 dw = dj.fs->winsect;
2351 res = remove_chain(dj.fs, cl);
2352 if (res == FR_OK) {
2353 dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
2354 res = move_window(dj.fs, dw);
2355 }
2356 }
2357 }
2358 }
2359 else { /* Open an existing file */
2360 if (res == FR_OK) { /* Follow succeeded */
2361 if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
2362 res = FR_NO_FILE;
2363 } else {
2364 if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
2365 res = FR_DENIED;
2366 }
2367 }
2368 }
2369 if (res == FR_OK) {
2370 if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
2371 mode |= FA__WRITTEN;
2372 fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
2373 fp->dir_ptr = dir;
2374#if _FS_LOCK
2375 fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
2376 if (!fp->lockid) res = FR_INT_ERR;
2377#endif
2378 }
2379
2380#else /* R/O configuration */
2381 if (res == FR_OK) { /* Follow succeeded */
2382 dir = dj.dir;
2383 if (!dir) { /* Current dir itself */
2384 res = FR_INVALID_NAME;
2385 } else {
2386 if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
2387 res = FR_NO_FILE;
2388 }
2389 }
2390#endif
2391 FREE_BUF();
2392
2393 if (res == FR_OK) {
2394 fp->flag = mode; /* File access mode */
2395 fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */
2396 fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
2397 fp->fptr = 0; /* File pointer */
2398 fp->dsect = 0;
2399#if _USE_FASTSEEK
2400 fp->cltbl = 0; /* Normal seek mode */
2401#endif
2402 fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
2403 }
2404 }
2405
2406 LEAVE_FF(dj.fs, res);
2407}
2408
2409
2410
2411
2412/*-----------------------------------------------------------------------*/
2413/* Read File */
2414/*-----------------------------------------------------------------------*/
2415
2416FRESULT f_read (
2417 FIL *fp, /* Pointer to the file object */
2418 void *buff, /* Pointer to data buffer */
2419 UINT btr, /* Number of bytes to read */
2420 UINT *br /* Pointer to number of bytes read */
2421)
2422{
2423 FRESULT res;
2424 DWORD clst, sect, remain;
2425 UINT rcnt, cc;
2426 BYTE csect, *rbuff = buff;
2427
2428
2429 *br = 0; /* Clear read byte counter */
2430
2431 res = validate(fp); /* Check validity */
2432 if (res != FR_OK) LEAVE_FF(fp->fs, res);
2433 if (fp->flag & FA__ERROR) /* Aborted file? */
2434 LEAVE_FF(fp->fs, FR_INT_ERR);
2435 if (!(fp->flag & FA_READ)) /* Check access mode */
2436 LEAVE_FF(fp->fs, FR_DENIED);
2437 remain = fp->fsize - fp->fptr;
2438 if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
2439
2440 for ( ; btr; /* Repeat until all data read */
2441 rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
2442 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
2443 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
2444 if (!csect) { /* On the cluster boundary? */
2445 if (fp->fptr == 0) { /* On the top of the file? */
2446 clst = fp->sclust; /* Follow from the origin */
2447 } else { /* Middle or end of the file */
2448#if _USE_FASTSEEK
2449 if (fp->cltbl)
2450 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
2451 else
2452#endif
2453 clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */
2454 }
2455 if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
2456 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
2457 fp->clust = clst; /* Update current cluster */
2458 }
2459 sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
2460 if (!sect) ABORT(fp->fs, FR_INT_ERR);
2461 sect += csect;
2462 cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */
2463 if (cc) { /* Read maximum contiguous sectors directly */
2464 if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
2465 cc = fp->fs->csize - csect;
2466 if (disk_read(fp->fs->drv, rbuff, sect, (BYTE)cc) != RES_OK)
2467 ABORT(fp->fs, FR_DISK_ERR);
2468#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
2469#if _FS_TINY
2470 if (fp->fs->wflag && fp->fs->winsect - sect < cc)
2471 mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
2472#else
2473 if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
2474 mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs));
2475#endif
2476#endif
2477 rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
2478 continue;
2479 }
2480#if !_FS_TINY
2481 if (fp->dsect != sect) { /* Load data sector if not in cache */
2482#if !_FS_READONLY
2483 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
2484 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2485 ABORT(fp->fs, FR_DISK_ERR);
2486 fp->flag &= ~FA__DIRTY;
2487 }
2488#endif
2489 if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */
2490 ABORT(fp->fs, FR_DISK_ERR);
2491 }
2492#endif
2493 fp->dsect = sect;
2494 }
2495 rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
2496 if (rcnt > btr) rcnt = btr;
2497#if _FS_TINY
2498 if (move_window(fp->fs, fp->dsect)) /* Move sector window */
2499 ABORT(fp->fs, FR_DISK_ERR);
2500 mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
2501#else
2502 mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
2503#endif
2504 }
2505
2506 LEAVE_FF(fp->fs, FR_OK);
2507}
2508
2509
2510
2511
2512#if !_FS_READONLY
2513/*-----------------------------------------------------------------------*/
2514/* Write File */
2515/*-----------------------------------------------------------------------*/
2516
2517FRESULT f_write (
2518 FIL *fp, /* Pointer to the file object */
2519 const void *buff, /* Pointer to the data to be written */
2520 UINT btw, /* Number of bytes to write */
2521 UINT *bw /* Pointer to number of bytes written */
2522)
2523{
2524 FRESULT res;
2525 DWORD clst, sect;
2526 UINT wcnt, cc;
2527 const BYTE *wbuff = buff;
2528 BYTE csect;
2529
2530
2531 *bw = 0; /* Clear write byte counter */
2532
2533 res = validate(fp); /* Check validity */
2534 if (res != FR_OK) LEAVE_FF(fp->fs, res);
2535 if (fp->flag & FA__ERROR) /* Aborted file? */
2536 LEAVE_FF(fp->fs, FR_INT_ERR);
2537 if (!(fp->flag & FA_WRITE)) /* Check access mode */
2538 LEAVE_FF(fp->fs, FR_DENIED);
2539 if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */
2540
2541 for ( ; btw; /* Repeat until all data written */
2542 wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
2543 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
2544 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
2545 if (!csect) { /* On the cluster boundary? */
2546 if (fp->fptr == 0) { /* On the top of the file? */
2547 clst = fp->sclust; /* Follow from the origin */
2548 if (clst == 0) /* When no cluster is allocated, */
2549 fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */
2550 } else { /* Middle or end of the file */
2551#if _USE_FASTSEEK
2552 if (fp->cltbl)
2553 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
2554 else
2555#endif
2556 clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */
2557 }
2558 if (clst == 0) break; /* Could not allocate a new cluster (disk full) */
2559 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
2560 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
2561 fp->clust = clst; /* Update current cluster */
2562 }
2563#if _FS_TINY
2564 if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write-back sector cache */
2565 ABORT(fp->fs, FR_DISK_ERR);
2566#else
2567 if (fp->flag & FA__DIRTY) { /* Write-back sector cache */
2568 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2569 ABORT(fp->fs, FR_DISK_ERR);
2570 fp->flag &= ~FA__DIRTY;
2571 }
2572#endif
2573 sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
2574 if (!sect) ABORT(fp->fs, FR_INT_ERR);
2575 sect += csect;
2576 cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */
2577 if (cc) { /* Write maximum contiguous sectors directly */
2578 if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
2579 cc = fp->fs->csize - csect;
2580 if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK)
2581 ABORT(fp->fs, FR_DISK_ERR);
2582#if _FS_TINY
2583 if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
2584 mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
2585 fp->fs->wflag = 0;
2586 }
2587#else
2588 if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
2589 mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
2590 fp->flag &= ~FA__DIRTY;
2591 }
2592#endif
2593 wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
2594 continue;
2595 }
2596#if _FS_TINY
2597 if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */
2598 if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR);
2599 fp->fs->winsect = sect;
2600 }
2601#else
2602 if (fp->dsect != sect) { /* Fill sector cache with file data */
2603 if (fp->fptr < fp->fsize &&
2604 disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
2605 ABORT(fp->fs, FR_DISK_ERR);
2606 }
2607#endif
2608 fp->dsect = sect;
2609 }
2610 wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
2611 if (wcnt > btw) wcnt = btw;
2612#if _FS_TINY
2613 if (move_window(fp->fs, fp->dsect)) /* Move sector window */
2614 ABORT(fp->fs, FR_DISK_ERR);
2615 mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
2616 fp->fs->wflag = 1;
2617#else
2618 mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
2619 fp->flag |= FA__DIRTY;
2620#endif
2621 }
2622
2623 if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
2624 fp->flag |= FA__WRITTEN; /* Set file change flag */
2625
2626 LEAVE_FF(fp->fs, FR_OK);
2627}
2628
2629
2630
2631
2632/*-----------------------------------------------------------------------*/
2633/* Synchronize the File Object */
2634/*-----------------------------------------------------------------------*/
2635
2636FRESULT f_sync (
2637 FIL *fp /* Pointer to the file object */
2638)
2639{
2640 FRESULT res;
2641 DWORD tim;
2642 BYTE *dir;
2643
2644
2645 res = validate(fp); /* Check validity of the object */
2646 if (res == FR_OK) {
2647 if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
2648#if !_FS_TINY /* Write-back dirty buffer */
2649 if (fp->flag & FA__DIRTY) {
2650 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2651 LEAVE_FF(fp->fs, FR_DISK_ERR);
2652 fp->flag &= ~FA__DIRTY;
2653 }
2654#endif
2655 /* Update the directory entry */
2656 res = move_window(fp->fs, fp->dir_sect);
2657 if (res == FR_OK) {
2658 dir = fp->dir_ptr;
2659 dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
2660 ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */
2661 st_clust(dir, fp->sclust); /* Update start cluster */
2662 tim = get_fattime(); /* Update updated time */
2663 ST_DWORD(dir+DIR_WrtTime, tim);
2664 ST_WORD(dir+DIR_LstAccDate, 0);
2665 fp->flag &= ~FA__WRITTEN;
2666 fp->fs->wflag = 1;
2667 res = sync(fp->fs);
2668 }
2669 }
2670 }
2671
2672 LEAVE_FF(fp->fs, res);
2673}
2674
2675#endif /* !_FS_READONLY */
2676
2677
2678
2679
2680/*-----------------------------------------------------------------------*/
2681/* Close File */
2682/*-----------------------------------------------------------------------*/
2683
2684FRESULT f_close (
2685 FIL *fp /* Pointer to the file object to be closed */
2686)
2687{
2688 FRESULT res;
2689
2690
2691#if _FS_READONLY
2692 res = validate(fp);
2693 {
2694#if _FS_REENTRANT
2695 FATFS *fs = fp->fs;
2696#endif
2697 if (res == FR_OK) fp->fs = 0; /* Discard file object */
2698 LEAVE_FF(fs, res);
2699 }
2700#else
2701 res = f_sync(fp); /* Flush cached data */
2702#if _FS_LOCK
2703 if (res == FR_OK) { /* Decrement open counter */
2704#if _FS_REENTRANT
2705 FATFS *fs = fp->fs;;
2706 res = validate(fp);
2707 if (res == FR_OK) {
2708 res = dec_lock(fp->lockid);
2709 unlock_fs(fs, FR_OK);
2710 }
2711#else
2712 res = dec_lock(fp->lockid);
2713#endif
2714 }
2715#endif
2716 if (res == FR_OK) fp->fs = 0; /* Discard file object */
2717 return res;
2718#endif
2719}
2720
2721
2722
2723
2724/*-----------------------------------------------------------------------*/
2725/* Current Drive/Directory Handlings */
2726/*-----------------------------------------------------------------------*/
2727
2728#if _FS_RPATH >= 1
2729
2730FRESULT f_chdrive (
2731 BYTE drv /* Drive number */
2732)
2733{
2734 if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
2735
2736 CurrVol = drv;
2737
2738 return FR_OK;
2739}
2740
2741
2742
2743FRESULT f_chdir (
2744 const TCHAR *path /* Pointer to the directory path */
2745)
2746{
2747 FRESULT res;
2748 DIR dj;
2749 DEF_NAMEBUF;
2750
2751
2752 res = chk_mounted(&path, &dj.fs, 0);
2753 if (res == FR_OK) {
2754 INIT_BUF(dj);
2755 res = follow_path(&dj, path); /* Follow the path */
2756 FREE_BUF();
2757 if (res == FR_OK) { /* Follow completed */
2758 if (!dj.dir) {
2759 dj.fs->cdir = dj.sclust; /* Start directory itself */
2760 } else {
2761 if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */
2762 dj.fs->cdir = ld_clust(dj.fs, dj.dir);
2763 else
2764 res = FR_NO_PATH; /* Reached but a file */
2765 }
2766 }
2767 if (res == FR_NO_FILE) res = FR_NO_PATH;
2768 }
2769
2770 LEAVE_FF(dj.fs, res);
2771}
2772
2773
2774#if _FS_RPATH >= 2
2775FRESULT f_getcwd (
2776 TCHAR *path, /* Pointer to the directory path */
2777 UINT sz_path /* Size of path */
2778)
2779{
2780 FRESULT res;
2781 DIR dj;
2782 UINT i, n;
2783 DWORD ccl;
2784 TCHAR *tp;
2785 FILINFO fno;
2786 DEF_NAMEBUF;
2787
2788
2789 *path = 0;
2790 res = chk_mounted((const TCHAR**)&path, &dj.fs, 0); /* Get current volume */
2791 if (res == FR_OK) {
2792 INIT_BUF(dj);
2793 i = sz_path; /* Bottom of buffer (dir stack base) */
2794 dj.sclust = dj.fs->cdir; /* Start to follow upper dir from current dir */
2795 while ((ccl = dj.sclust) != 0) { /* Repeat while current dir is a sub-dir */
2796 res = dir_sdi(&dj, 1); /* Get parent dir */
2797 if (res != FR_OK) break;
2798 res = dir_read(&dj);
2799 if (res != FR_OK) break;
2800 dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */
2801 res = dir_sdi(&dj, 0);
2802 if (res != FR_OK) break;
2803 do { /* Find the entry links to the child dir */
2804 res = dir_read(&dj);
2805 if (res != FR_OK) break;
2806 if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */
2807 res = dir_next(&dj, 0);
2808 } while (res == FR_OK);
2809 if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
2810 if (res != FR_OK) break;
2811#if _USE_LFN
2812 fno.lfname = path;
2813 fno.lfsize = i;
2814#endif
2815 get_fileinfo(&dj, &fno); /* Get the dir name and push it to the buffer */
2816 tp = fno.fname;
2817 if (_USE_LFN && *path) tp = path;
2818 for (n = 0; tp[n]; n++) ;
2819 if (i < n + 3) {
2820 res = FR_NOT_ENOUGH_CORE; break;
2821 }
2822 while (n) path[--i] = tp[--n];
2823 path[--i] = '/';
2824 }
2825 tp = path;
2826 if (res == FR_OK) {
2827 *tp++ = '0' + CurrVol; /* Put drive number */
2828 *tp++ = ':';
2829 if (i == sz_path) { /* Root-dir */
2830 *tp++ = '/';
2831 } else { /* Sub-dir */
2832 do /* Add stacked path str */
2833 *tp++ = path[i++];
2834 while (i < sz_path);
2835 }
2836 }
2837 *tp = 0;
2838 FREE_BUF();
2839 }
2840
2841 LEAVE_FF(dj.fs, res);
2842}
2843#endif /* _FS_RPATH >= 2 */
2844#endif /* _FS_RPATH >= 1 */
2845
2846
2847
2848#if _FS_MINIMIZE <= 2
2849/*-----------------------------------------------------------------------*/
2850/* Seek File R/W Pointer */
2851/*-----------------------------------------------------------------------*/
2852
2853FRESULT f_lseek (
2854 FIL *fp, /* Pointer to the file object */
2855 DWORD ofs /* File pointer from top of file */
2856)
2857{
2858 FRESULT res;
2859
2860
2861 res = validate(fp); /* Check validity of the object */
2862 if (res != FR_OK) LEAVE_FF(fp->fs, res);
2863 if (fp->flag & FA__ERROR) /* Check abort flag */
2864 LEAVE_FF(fp->fs, FR_INT_ERR);
2865
2866#if _USE_FASTSEEK
2867 if (fp->cltbl) { /* Fast seek */
2868 DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
2869
2870 if (ofs == CREATE_LINKMAP) { /* Create CLMT */
2871 tbl = fp->cltbl;
2872 tlen = *tbl++; ulen = 2; /* Given table size and required table size */
2873 cl = fp->sclust; /* Top of the chain */
2874 if (cl) {
2875 do {
2876 /* Get a fragment */
2877 tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */
2878 do {
2879 pcl = cl; ncl++;
2880 cl = get_fat(fp->fs, cl);
2881 if (cl <= 1) ABORT(fp->fs, FR_INT_ERR);
2882 if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
2883 } while (cl == pcl + 1);
2884 if (ulen <= tlen) { /* Store the length and top of the fragment */
2885 *tbl++ = ncl; *tbl++ = tcl;
2886 }
2887 } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */
2888 }
2889 *fp->cltbl = ulen; /* Number of items used */
2890 if (ulen <= tlen)
2891 *tbl = 0; /* Terminate table */
2892 else
2893 res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */
2894
2895 } else { /* Fast seek */
2896 if (ofs > fp->fsize) /* Clip offset at the file size */
2897 ofs = fp->fsize;
2898 fp->fptr = ofs; /* Set file pointer */
2899 if (ofs) {
2900 fp->clust = clmt_clust(fp, ofs - 1);
2901 dsc = clust2sect(fp->fs, fp->clust);
2902 if (!dsc) ABORT(fp->fs, FR_INT_ERR);
2903 dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1);
2904 if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */
2905#if !_FS_TINY
2906#if !_FS_READONLY
2907 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
2908 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2909 ABORT(fp->fs, FR_DISK_ERR);
2910 fp->flag &= ~FA__DIRTY;
2911 }
2912#endif
2913 if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */
2914 ABORT(fp->fs, FR_DISK_ERR);
2915#endif
2916 fp->dsect = dsc;
2917 }
2918 }
2919 }
2920 } else
2921#endif
2922
2923 /* Normal Seek */
2924 {
2925 DWORD clst, bcs, nsect, ifptr;
2926
2927 if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */
2928#if !_FS_READONLY
2929 && !(fp->flag & FA_WRITE)
2930#endif
2931 ) ofs = fp->fsize;
2932
2933 ifptr = fp->fptr;
2934 fp->fptr = nsect = 0;
2935 if (ofs) {
2936 bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */
2937 if (ifptr > 0 &&
2938 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
2939 fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */
2940 ofs -= fp->fptr;
2941 clst = fp->clust;
2942 } else { /* When seek to back cluster, */
2943 clst = fp->sclust; /* start from the first cluster */
2944#if !_FS_READONLY
2945 if (clst == 0) { /* If no cluster chain, create a new chain */
2946 clst = create_chain(fp->fs, 0);
2947 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
2948 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
2949 fp->sclust = clst;
2950 }
2951#endif
2952 fp->clust = clst;
2953 }
2954 if (clst != 0) {
2955 while (ofs > bcs) { /* Cluster following loop */
2956#if !_FS_READONLY
2957 if (fp->flag & FA_WRITE) { /* Check if in write mode or not */
2958 clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */
2959 if (clst == 0) { /* When disk gets full, clip file size */
2960 ofs = bcs; break;
2961 }
2962 } else
2963#endif
2964 clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */
2965 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
2966 if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
2967 fp->clust = clst;
2968 fp->fptr += bcs;
2969 ofs -= bcs;
2970 }
2971 fp->fptr += ofs;
2972 if (ofs % SS(fp->fs)) {
2973 nsect = clust2sect(fp->fs, clst); /* Current sector */
2974 if (!nsect) ABORT(fp->fs, FR_INT_ERR);
2975 nsect += ofs / SS(fp->fs);
2976 }
2977 }
2978 }
2979 if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */
2980#if !_FS_TINY
2981#if !_FS_READONLY
2982 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
2983 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2984 ABORT(fp->fs, FR_DISK_ERR);
2985 fp->flag &= ~FA__DIRTY;
2986 }
2987#endif
2988 if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */
2989 ABORT(fp->fs, FR_DISK_ERR);
2990#endif
2991 fp->dsect = nsect;
2992 }
2993#if !_FS_READONLY
2994 if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */
2995 fp->fsize = fp->fptr;
2996 fp->flag |= FA__WRITTEN;
2997 }
2998#endif
2999 }
3000
3001 LEAVE_FF(fp->fs, res);
3002}
3003
3004
3005
3006#if _FS_MINIMIZE <= 1
3007/*-----------------------------------------------------------------------*/
3008/* Create a Directory Object */
3009/*-----------------------------------------------------------------------*/
3010
3011FRESULT f_opendir (
3012 DIR *dj, /* Pointer to directory object to create */
3013 const TCHAR *path /* Pointer to the directory path */
3014)
3015{
3016 FRESULT res;
3017 FATFS *fs;
3018 DEF_NAMEBUF;
3019
3020
3021 if (!dj) return FR_INVALID_OBJECT;
3022
3023 res = chk_mounted(&path, &dj->fs, 0);
3024 fs = dj->fs;
3025 if (res == FR_OK) {
3026 INIT_BUF(*dj);
3027 res = follow_path(dj, path); /* Follow the path to the directory */
3028 FREE_BUF();
3029 if (res == FR_OK) { /* Follow completed */
3030 if (dj->dir) { /* It is not the root dir */
3031 if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */
3032 dj->sclust = ld_clust(fs, dj->dir);
3033 } else { /* The object is not a directory */
3034 res = FR_NO_PATH;
3035 }
3036 }
3037 if (res == FR_OK) {
3038 dj->id = fs->id;
3039 res = dir_sdi(dj, 0); /* Rewind dir */
3040 }
3041 }
3042 if (res == FR_NO_FILE) res = FR_NO_PATH;
3043 if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function faild */
3044 } else {
3045 dj->fs = 0;
3046 }
3047
3048 LEAVE_FF(fs, res);
3049}
3050
3051
3052
3053
3054/*-----------------------------------------------------------------------*/
3055/* Read Directory Entry in Sequence */
3056/*-----------------------------------------------------------------------*/
3057
3058FRESULT f_readdir (
3059 DIR *dj, /* Pointer to the open directory object */
3060 FILINFO *fno /* Pointer to file information to return */
3061)
3062{
3063 FRESULT res;
3064 DEF_NAMEBUF;
3065
3066
3067 res = validate(dj); /* Check validity of the object */
3068 if (res == FR_OK) {
3069 if (!fno) {
3070 res = dir_sdi(dj, 0); /* Rewind the directory object */
3071 } else {
3072 INIT_BUF(*dj);
3073 res = dir_read(dj); /* Read an directory item */
3074 if (res == FR_NO_FILE) { /* Reached end of dir */
3075 dj->sect = 0;
3076 res = FR_OK;
3077 }
3078 if (res == FR_OK) { /* A valid entry is found */
3079 get_fileinfo(dj, fno); /* Get the object information */
3080 res = dir_next(dj, 0); /* Increment index for next */
3081 if (res == FR_NO_FILE) {
3082 dj->sect = 0;
3083 res = FR_OK;
3084 }
3085 }
3086 FREE_BUF();
3087 }
3088 }
3089
3090 LEAVE_FF(dj->fs, res);
3091}
3092
3093
3094
3095#if _FS_MINIMIZE == 0
3096/*-----------------------------------------------------------------------*/
3097/* Get File Status */
3098/*-----------------------------------------------------------------------*/
3099
3100FRESULT f_stat (
3101 const TCHAR *path, /* Pointer to the file path */
3102 FILINFO *fno /* Pointer to file information to return */
3103)
3104{
3105 FRESULT res;
3106 DIR dj;
3107 DEF_NAMEBUF;
3108
3109
3110 res = chk_mounted(&path, &dj.fs, 0);
3111 if (res == FR_OK) {
3112 INIT_BUF(dj);
3113 res = follow_path(&dj, path); /* Follow the file path */
3114 if (res == FR_OK) { /* Follow completed */
3115 if (dj.dir) /* Found an object */
3116 get_fileinfo(&dj, fno);
3117 else /* It is root dir */
3118 res = FR_INVALID_NAME;
3119 }
3120 FREE_BUF();
3121 }
3122
3123 LEAVE_FF(dj.fs, res);
3124}
3125
3126
3127
3128#if !_FS_READONLY
3129/*-----------------------------------------------------------------------*/
3130/* Get Number of Free Clusters */
3131/*-----------------------------------------------------------------------*/
3132
3133FRESULT f_getfree (
3134 const TCHAR *path, /* Pointer to the logical drive number (root dir) */
3135 DWORD *nclst, /* Pointer to the variable to return number of free clusters */
3136 FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */
3137)
3138{
3139 FRESULT res;
3140 FATFS *fs;
3141 DWORD n, clst, sect, stat;
3142 UINT i;
3143 BYTE fat, *p;
3144
3145
3146 /* Get drive number */
3147 res = chk_mounted(&path, fatfs, 0);
3148 fs = *fatfs;
3149 if (res == FR_OK) {
3150 /* If free_clust is valid, return it without full cluster scan */
3151 if (fs->free_clust <= fs->n_fatent - 2) {
3152 *nclst = fs->free_clust;
3153 } else {
3154 /* Get number of free clusters */
3155 fat = fs->fs_type;
3156 n = 0;
3157 if (fat == FS_FAT12) {
3158 clst = 2;
3159 do {
3160 stat = get_fat(fs, clst);
3161 if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
3162 if (stat == 1) { res = FR_INT_ERR; break; }
3163 if (stat == 0) n++;
3164 } while (++clst < fs->n_fatent);
3165 } else {
3166 clst = fs->n_fatent;
3167 sect = fs->fatbase;
3168 i = 0; p = 0;
3169 do {
3170 if (!i) {
3171 res = move_window(fs, sect++);
3172 if (res != FR_OK) break;
3173 p = fs->win;
3174 i = SS(fs);
3175 }
3176 if (fat == FS_FAT16) {
3177 if (LD_WORD(p) == 0) n++;
3178 p += 2; i -= 2;
3179 } else {
3180 if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++;
3181 p += 4; i -= 4;
3182 }
3183 } while (--clst);
3184 }
3185 fs->free_clust = n;
3186 if (fat == FS_FAT32) fs->fsi_flag = 1;
3187 *nclst = n;
3188 }
3189 }
3190 LEAVE_FF(fs, res);
3191}
3192
3193
3194
3195
3196/*-----------------------------------------------------------------------*/
3197/* Truncate File */
3198/*-----------------------------------------------------------------------*/
3199
3200FRESULT f_truncate (
3201 FIL *fp /* Pointer to the file object */
3202)
3203{
3204 FRESULT res;
3205 DWORD ncl;
3206
3207
3208 if (!fp) return FR_INVALID_OBJECT;
3209
3210 res = validate(fp); /* Check validity of the object */
3211 if (res == FR_OK) {
3212 if (fp->flag & FA__ERROR) { /* Check abort flag */
3213 res = FR_INT_ERR;
3214 } else {
3215 if (!(fp->flag & FA_WRITE)) /* Check access mode */
3216 res = FR_DENIED;
3217 }
3218 }
3219 if (res == FR_OK) {
3220 if (fp->fsize > fp->fptr) {
3221 fp->fsize = fp->fptr; /* Set file size to current R/W point */
3222 fp->flag |= FA__WRITTEN;
3223 if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */
3224 res = remove_chain(fp->fs, fp->sclust);
3225 fp->sclust = 0;
3226 } else { /* When truncate a part of the file, remove remaining clusters */
3227 ncl = get_fat(fp->fs, fp->clust);
3228 res = FR_OK;
3229 if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
3230 if (ncl == 1) res = FR_INT_ERR;
3231 if (res == FR_OK && ncl < fp->fs->n_fatent) {
3232 res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF);
3233 if (res == FR_OK) res = remove_chain(fp->fs, ncl);
3234 }
3235 }
3236 }
3237 if (res != FR_OK) fp->flag |= FA__ERROR;
3238 }
3239
3240 LEAVE_FF(fp->fs, res);
3241}
3242
3243
3244
3245
3246/*-----------------------------------------------------------------------*/
3247/* Delete a File or Directory */
3248/*-----------------------------------------------------------------------*/
3249
3250FRESULT f_unlink (
3251 const TCHAR *path /* Pointer to the file or directory path */
3252)
3253{
3254 FRESULT res;
3255 DIR dj, sdj;
3256 BYTE *dir;
3257 DWORD dclst;
3258 DEF_NAMEBUF;
3259
3260
3261 res = chk_mounted(&path, &dj.fs, 1);
3262 if (res == FR_OK) {
3263 INIT_BUF(dj);
3264 res = follow_path(&dj, path); /* Follow the file path */
3265 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
3266 res = FR_INVALID_NAME; /* Cannot remove dot entry */
3267#if _FS_LOCK
3268 if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */
3269#endif
3270 if (res == FR_OK) { /* The object is accessible */
3271 dir = dj.dir;
3272 if (!dir) {
3273 res = FR_INVALID_NAME; /* Cannot remove the start directory */
3274 } else {
3275 if (dir[DIR_Attr] & AM_RDO)
3276 res = FR_DENIED; /* Cannot remove R/O object */
3277 }
3278 dclst = ld_clust(dj.fs, dir);
3279 if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */
3280 if (dclst < 2) {
3281 res = FR_INT_ERR;
3282 } else {
3283 mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */
3284 sdj.sclust = dclst;
3285 res = dir_sdi(&sdj, 2); /* Exclude dot entries */
3286 if (res == FR_OK) {
3287 res = dir_read(&sdj);
3288 if (res == FR_OK /* Not empty dir */
3289#if _FS_RPATH
3290 || dclst == dj.fs->cdir /* Current dir */
3291#endif
3292 ) res = FR_DENIED;
3293 if (res == FR_NO_FILE) res = FR_OK; /* Empty */
3294 }
3295 }
3296 }
3297 if (res == FR_OK) {
3298 res = dir_remove(&dj); /* Remove the directory entry */
3299 if (res == FR_OK) {
3300 if (dclst) /* Remove the cluster chain if exist */
3301 res = remove_chain(dj.fs, dclst);
3302 if (res == FR_OK) res = sync(dj.fs);
3303 }
3304 }
3305 }
3306 FREE_BUF();
3307 }
3308 LEAVE_FF(dj.fs, res);
3309}
3310
3311
3312
3313
3314/*-----------------------------------------------------------------------*/
3315/* Create a Directory */
3316/*-----------------------------------------------------------------------*/
3317
3318FRESULT f_mkdir (
3319 const TCHAR *path /* Pointer to the directory path */
3320)
3321{
3322 FRESULT res;
3323 DIR dj;
3324 BYTE *dir, n;
3325 DWORD dsc, dcl, pcl, tim = get_fattime();
3326 DEF_NAMEBUF;
3327
3328
3329 res = chk_mounted(&path, &dj.fs, 1);
3330 if (res == FR_OK) {
3331 INIT_BUF(dj);
3332 res = follow_path(&dj, path); /* Follow the file path */
3333 if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
3334 if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NS] & NS_DOT))
3335 res = FR_INVALID_NAME;
3336 if (res == FR_NO_FILE) { /* Can create a new directory */
3337 dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */
3338 res = FR_OK;
3339 if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
3340 if (dcl == 1) res = FR_INT_ERR;
3341 if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
3342 if (res == FR_OK) /* Flush FAT */
3343 res = move_window(dj.fs, 0);
3344 if (res == FR_OK) { /* Initialize the new directory table */
3345 dsc = clust2sect(dj.fs, dcl);
3346 dir = dj.fs->win;
3347 mem_set(dir, 0, SS(dj.fs));
3348 mem_set(dir+DIR_Name, ' ', 8+3); /* Create "." entry */
3349 dir[DIR_Name] = '.';
3350 dir[DIR_Attr] = AM_DIR;
3351 ST_DWORD(dir+DIR_WrtTime, tim);
3352 st_clust(dir, dcl);
3353 mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */
3354 dir[33] = '.'; pcl = dj.sclust;
3355 if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
3356 pcl = 0;
3357 st_clust(dir+SZ_DIR, pcl);
3358 for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */
3359 dj.fs->winsect = dsc++;
3360 dj.fs->wflag = 1;
3361 res = move_window(dj.fs, 0);
3362 if (res != FR_OK) break;
3363 mem_set(dir, 0, SS(dj.fs));
3364 }
3365 }
3366 if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */
3367 if (res != FR_OK) {
3368 remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */
3369 } else {
3370 dir = dj.dir;
3371 dir[DIR_Attr] = AM_DIR; /* Attribute */
3372 ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */
3373 st_clust(dir, dcl); /* Table start cluster */
3374 dj.fs->wflag = 1;
3375 res = sync(dj.fs);
3376 }
3377 }
3378 FREE_BUF();
3379 }
3380
3381 LEAVE_FF(dj.fs, res);
3382}
3383
3384
3385
3386
3387/*-----------------------------------------------------------------------*/
3388/* Change Attribute */
3389/*-----------------------------------------------------------------------*/
3390
3391FRESULT f_chmod (
3392 const TCHAR *path, /* Pointer to the file path */
3393 BYTE value, /* Attribute bits */
3394 BYTE mask /* Attribute mask to change */
3395)
3396{
3397 FRESULT res;
3398 DIR dj;
3399 BYTE *dir;
3400 DEF_NAMEBUF;
3401
3402
3403 res = chk_mounted(&path, &dj.fs, 1);
3404 if (res == FR_OK) {
3405 INIT_BUF(dj);
3406 res = follow_path(&dj, path); /* Follow the file path */
3407 FREE_BUF();
3408 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
3409 res = FR_INVALID_NAME;
3410 if (res == FR_OK) {
3411 dir = dj.dir;
3412 if (!dir) { /* Is it a root directory? */
3413 res = FR_INVALID_NAME;
3414 } else { /* File or sub directory */
3415 mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */
3416 dir[DIR_Attr] = (value & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
3417 dj.fs->wflag = 1;
3418 res = sync(dj.fs);
3419 }
3420 }
3421 }
3422
3423 LEAVE_FF(dj.fs, res);
3424}
3425
3426
3427
3428
3429/*-----------------------------------------------------------------------*/
3430/* Change Timestamp */
3431/*-----------------------------------------------------------------------*/
3432
3433FRESULT f_utime (
3434 const TCHAR *path, /* Pointer to the file/directory name */
3435 const FILINFO *fno /* Pointer to the time stamp to be set */
3436)
3437{
3438 FRESULT res;
3439 DIR dj;
3440 BYTE *dir;
3441 DEF_NAMEBUF;
3442
3443
3444 res = chk_mounted(&path, &dj.fs, 1);
3445 if (res == FR_OK) {
3446 INIT_BUF(dj);
3447 res = follow_path(&dj, path); /* Follow the file path */
3448 FREE_BUF();
3449 if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
3450 res = FR_INVALID_NAME;
3451 if (res == FR_OK) {
3452 dir = dj.dir;
3453 if (!dir) { /* Root directory */
3454 res = FR_INVALID_NAME;
3455 } else { /* File or sub-directory */
3456 ST_WORD(dir+DIR_WrtTime, fno->ftime);
3457 ST_WORD(dir+DIR_WrtDate, fno->fdate);
3458 dj.fs->wflag = 1;
3459 res = sync(dj.fs);
3460 }
3461 }
3462 }
3463
3464 LEAVE_FF(dj.fs, res);
3465}
3466
3467
3468
3469
3470/*-----------------------------------------------------------------------*/
3471/* Rename File/Directory */
3472/*-----------------------------------------------------------------------*/
3473
3474FRESULT f_rename (
3475 const TCHAR *path_old, /* Pointer to the old name */
3476 const TCHAR *path_new /* Pointer to the new name */
3477)
3478{
3479 FRESULT res;
3480 DIR djo, djn;
3481 BYTE buf[21], *dir;
3482 DWORD dw;
3483 DEF_NAMEBUF;
3484
3485
3486 res = chk_mounted(&path_old, &djo.fs, 1);
3487 if (res == FR_OK) {
3488 djn.fs = djo.fs;
3489 INIT_BUF(djo);
3490 res = follow_path(&djo, path_old); /* Check old object */
3491 if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
3492 res = FR_INVALID_NAME;
3493#if _FS_LOCK
3494 if (res == FR_OK) res = chk_lock(&djo, 2);
3495#endif
3496 if (res == FR_OK) { /* Old object is found */
3497 if (!djo.dir) { /* Is root dir? */
3498 res = FR_NO_FILE;
3499 } else {
3500 mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */
3501 mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */
3502 res = follow_path(&djn, path_new);
3503 if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */
3504 if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */
3505/* Start critical section that an interruption or error can cause cross-link */
3506 res = dir_register(&djn); /* Register the new entry */
3507 if (res == FR_OK) {
3508 dir = djn.dir; /* Copy object information except for name */
3509 mem_cpy(dir+13, buf+2, 19);
3510 dir[DIR_Attr] = buf[0] | AM_ARC;
3511 djo.fs->wflag = 1;
3512 if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */
3513 dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
3514 if (!dw) {
3515 res = FR_INT_ERR;
3516 } else {
3517 res = move_window(djo.fs, dw);
3518 dir = djo.fs->win+SZ_DIR; /* .. entry */
3519 if (res == FR_OK && dir[1] == '.') {
3520 dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;
3521 st_clust(dir, dw);
3522 djo.fs->wflag = 1;
3523 }
3524 }
3525 }
3526 if (res == FR_OK) {
3527 res = dir_remove(&djo); /* Remove old entry */
3528 if (res == FR_OK)
3529 res = sync(djo.fs);
3530 }
3531 }
3532/* End critical section */
3533 }
3534 }
3535 }
3536 FREE_BUF();
3537 }
3538 LEAVE_FF(djo.fs, res);
3539}
3540
3541#endif /* !_FS_READONLY */
3542#endif /* _FS_MINIMIZE == 0 */
3543#endif /* _FS_MINIMIZE <= 1 */
3544#endif /* _FS_MINIMIZE <= 2 */
3545
3546
3547
3548/*-----------------------------------------------------------------------*/
3549/* Forward data to the stream directly (available on only tiny cfg) */
3550/*-----------------------------------------------------------------------*/
3551#if _USE_FORWARD && _FS_TINY
3552
3553FRESULT f_forward (
3554 FIL *fp, /* Pointer to the file object */
3555 UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */
3556 UINT btr, /* Number of bytes to forward */
3557 UINT *bf /* Pointer to number of bytes forwarded */
3558)
3559{
3560 FRESULT res;
3561 DWORD remain, clst, sect;
3562 UINT rcnt;
3563 BYTE csect;
3564
3565
3566 *bf = 0; /* Clear transfer byte counter */
3567
3568 if (!fp) return FR_INVALID_OBJECT;
3569
3570 res = validate(fp); /* Check validity of the object */
3571 if (res != FR_OK) LEAVE_FF(fp->fs, res);
3572 if (fp->flag & FA__ERROR) /* Check error flag */
3573 LEAVE_FF(fp->fs, FR_INT_ERR);
3574 if (!(fp->flag & FA_READ)) /* Check access mode */
3575 LEAVE_FF(fp->fs, FR_DENIED);
3576
3577 remain = fp->fsize - fp->fptr;
3578 if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
3579
3580 for ( ; btr && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */
3581 fp->fptr += rcnt, *bf += rcnt, btr -= rcnt) {
3582 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
3583 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
3584 if (!csect) { /* On the cluster boundary? */
3585 clst = (fp->fptr == 0) ? /* On the top of the file? */
3586 fp->sclust : get_fat(fp->fs, fp->clust);
3587 if (clst <= 1) ABORT(fp->fs, FR_INT_ERR);
3588 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
3589 fp->clust = clst; /* Update current cluster */
3590 }
3591 }
3592 sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */
3593 if (!sect) ABORT(fp->fs, FR_INT_ERR);
3594 sect += csect;
3595 if (move_window(fp->fs, sect)) /* Move sector window */
3596 ABORT(fp->fs, FR_DISK_ERR);
3597 fp->dsect = sect;
3598 rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */
3599 if (rcnt > btr) rcnt = btr;
3600 rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt);
3601 if (!rcnt) ABORT(fp->fs, FR_INT_ERR);
3602 }
3603
3604 LEAVE_FF(fp->fs, FR_OK);
3605}
3606#endif /* _USE_FORWARD */
3607
3608
3609
3610#if _USE_MKFS && !_FS_READONLY
3611/*-----------------------------------------------------------------------*/
3612/* Create File System on the Drive */
3613/*-----------------------------------------------------------------------*/
3614#define N_ROOTDIR 512 /* Number of root dir entries for FAT12/16 */
3615#define N_FATS 1 /* Number of FAT copies (1 or 2) */
3616
3617
3618FRESULT f_mkfs (
3619 BYTE drv, /* Logical drive number */
3620 BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */
3621 UINT au /* Allocation unit size [bytes] */
3622)
3623{
3624 static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
3625 static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
3626 BYTE fmt, md, sys, *tbl, pdrv, part;
3627 DWORD n_clst, vs, n, wsect;
3628 UINT i;
3629 DWORD b_vol, b_fat, b_dir, b_data; /* LBA */
3630 DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
3631 FATFS *fs;
3632 DSTATUS stat;
3633
3634
3635 /* Check mounted drive and clear work area */
3636 if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
3637 if (sfd > 1) return FR_INVALID_PARAMETER;
3638 if (au & (au - 1)) return FR_INVALID_PARAMETER;
3639 fs = FatFs[drv];
3640 if (!fs) return FR_NOT_ENABLED;
3641 fs->fs_type = 0;
3642 pdrv = LD2PD(drv); /* Physical drive */
3643 part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/
3644
3645 /* Get disk statics */
3646 stat = disk_initialize(pdrv);
3647 if (stat & STA_NOINIT) return FR_NOT_READY;
3648 if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
3649#if _MAX_SS != 512 /* Get disk sector size */
3650 if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
3651 return FR_DISK_ERR;
3652#endif
3653 if (_MULTI_PARTITION && part) {
3654 /* Get partition information from partition table in the MBR */
3655 if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
3656 if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
3657 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
3658 if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */
3659 b_vol = LD_DWORD(tbl+8); /* Volume start sector */
3660 n_vol = LD_DWORD(tbl+12); /* Volume size */
3661 } else {
3662 /* Create a partition in this function */
3663 if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
3664 return FR_DISK_ERR;
3665 b_vol = (sfd) ? 0 : 63; /* Volume start sector */
3666 n_vol -= b_vol; /* Volume size */
3667 }
3668
3669 if (!au) { /* AU auto selection */
3670 vs = n_vol / (2000 / (SS(fs) / 512));
3671 for (i = 0; vs < vst[i]; i++) ;
3672 au = cst[i];
3673 }
3674 au /= SS(fs); /* Number of sectors per cluster */
3675 if (au == 0) au = 1;
3676 if (au > 128) au = 128;
3677
3678 /* Pre-compute number of clusters and FAT sub-type */
3679 n_clst = n_vol / au;
3680 fmt = FS_FAT12;
3681 if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
3682 if (n_clst >= MIN_FAT32) fmt = FS_FAT32;
3683
3684 /* Determine offset and size of FAT structure */
3685 if (fmt == FS_FAT32) {
3686 n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
3687 n_rsv = 32;
3688 n_dir = 0;
3689 } else {
3690 n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
3691 n_fat = (n_fat + SS(fs) - 1) / SS(fs);
3692 n_rsv = 1;
3693 n_dir = (DWORD)N_ROOTDIR * SZ_DIR / SS(fs);
3694 }
3695 b_fat = b_vol + n_rsv; /* FAT area start sector */
3696 b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
3697 b_data = b_dir + n_dir; /* Data area start sector */
3698 if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */
3699
3700 /* Align data start sector to erase block boundary (for flash memory media) */
3701 if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
3702 n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */
3703 n = (n - b_data) / N_FATS;
3704 if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */
3705 n_rsv += n;
3706 b_fat += n;
3707 } else { /* FAT12/16: Expand FAT size */
3708 n_fat += n;
3709 }
3710
3711 /* Determine number of clusters and final check of validity of the FAT sub-type */
3712 n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
3713 if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16)
3714 || (fmt == FS_FAT32 && n_clst < MIN_FAT32))
3715 return FR_MKFS_ABORTED;
3716
3717 switch (fmt) { /* Determine system ID for partition table */
3718 case FS_FAT12: sys = 0x01; break;
3719 case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;
3720 default: sys = 0x0C;
3721 }
3722
3723 if (_MULTI_PARTITION && part) {
3724 /* Update system ID in the partition table */
3725 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
3726 tbl[4] = sys;
3727 if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
3728 md = 0xF8;
3729 } else {
3730 if (sfd) { /* No partition table (SFD) */
3731 md = 0xF0;
3732 } else { /* Create partition table (FDISK) */
3733 mem_set(fs->win, 0, SS(fs));
3734 tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */
3735 tbl[1] = 1; /* Partition start head */
3736 tbl[2] = 1; /* Partition start sector */
3737 tbl[3] = 0; /* Partition start cylinder */
3738 tbl[4] = sys; /* System type */
3739 tbl[5] = 254; /* Partition end head */
3740 n = (b_vol + n_vol) / 63 / 255;
3741 tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */
3742 tbl[7] = (BYTE)n; /* End cylinder */
3743 ST_DWORD(tbl+8, 63); /* Partition start in LBA */
3744 ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */
3745 ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */
3746 if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */
3747 return FR_DISK_ERR;
3748 md = 0xF8;
3749 }
3750 }
3751
3752 /* Create BPB in the VBR */
3753 tbl = fs->win; /* Clear sector */
3754 mem_set(tbl, 0, SS(fs));
3755 mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
3756 i = SS(fs); /* Sector size */
3757 ST_WORD(tbl+BPB_BytsPerSec, i);
3758 tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */
3759 ST_WORD(tbl+BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */
3760 tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */
3761 i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of rootdir entries */
3762 ST_WORD(tbl+BPB_RootEntCnt, i);
3763 if (n_vol < 0x10000) { /* Number of total sectors */
3764 ST_WORD(tbl+BPB_TotSec16, n_vol);
3765 } else {
3766 ST_DWORD(tbl+BPB_TotSec32, n_vol);
3767 }
3768 tbl[BPB_Media] = md; /* Media descriptor */
3769 ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */
3770 ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */
3771 ST_DWORD(tbl+BPB_HiddSec, b_vol); /* Hidden sectors */
3772 n = get_fattime(); /* Use current time as VSN */
3773 if (fmt == FS_FAT32) {
3774 ST_DWORD(tbl+BS_VolID32, n); /* VSN */
3775 ST_DWORD(tbl+BPB_FATSz32, n_fat); /* Number of sectors per FAT */
3776 ST_DWORD(tbl+BPB_RootClus, 2); /* Root directory start cluster (2) */
3777 ST_WORD(tbl+BPB_FSInfo, 1); /* FSInfo record offset (VBR+1) */
3778 ST_WORD(tbl+BPB_BkBootSec, 6); /* Backup boot record offset (VBR+6) */
3779 tbl[BS_DrvNum32] = 0x80; /* Drive number */
3780 tbl[BS_BootSig32] = 0x29; /* Extended boot signature */
3781 mem_cpy(tbl+BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
3782 } else {
3783 ST_DWORD(tbl+BS_VolID, n); /* VSN */
3784 ST_WORD(tbl+BPB_FATSz16, n_fat); /* Number of sectors per FAT */
3785 tbl[BS_DrvNum] = 0x80; /* Drive number */
3786 tbl[BS_BootSig] = 0x29; /* Extended boot signature */
3787 mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
3788 }
3789 ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */
3790 if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */
3791 return FR_DISK_ERR;
3792 if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */
3793 disk_write(pdrv, tbl, b_vol + 6, 1);
3794
3795 /* Initialize FAT area */
3796 wsect = b_fat;
3797 for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */
3798 mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */
3799 n = md; /* Media descriptor byte */
3800 if (fmt != FS_FAT32) {
3801 n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
3802 ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT12/16) */
3803 } else {
3804 n |= 0xFFFFFF00;
3805 ST_DWORD(tbl+0, n); /* Reserve cluster #0-1 (FAT32) */
3806 ST_DWORD(tbl+4, 0xFFFFFFFF);
3807 ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */
3808 }
3809 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
3810 return FR_DISK_ERR;
3811 mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */
3812 for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */
3813 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
3814 return FR_DISK_ERR;
3815 }
3816 }
3817
3818 /* Initialize root directory */
3819 i = (fmt == FS_FAT32) ? au : n_dir;
3820 do {
3821 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
3822 return FR_DISK_ERR;
3823 } while (--i);
3824
3825#if _USE_ERASE /* Erase data area if needed */
3826 {
3827 DWORD eb[2];
3828
3829 eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
3830 disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
3831 }
3832#endif
3833
3834 /* Create FSInfo if needed */
3835 if (fmt == FS_FAT32) {
3836 ST_DWORD(tbl+FSI_LeadSig, 0x41615252);
3837 ST_DWORD(tbl+FSI_StrucSig, 0x61417272);
3838 ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */
3839 ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */
3840 ST_WORD(tbl+BS_55AA, 0xAA55);
3841 disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */
3842 disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */
3843 }
3844
3845 return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
3846}
3847
3848
3849#if _MULTI_PARTITION == 2
3850/*-----------------------------------------------------------------------*/
3851/* Divide Physical Drive */
3852/*-----------------------------------------------------------------------*/
3853
3854FRESULT f_fdisk (
3855 BYTE pdrv, /* Physical drive number */
3856 const DWORD szt[], /* Pointer to the size table for each partitions */
3857 void* work /* Pointer to the working buffer */
3858)
3859{
3860 UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
3861 BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
3862 DSTATUS stat;
3863 DWORD sz_disk, sz_part, s_part;
3864
3865
3866 stat = disk_initialize(pdrv);
3867 if (stat & STA_NOINIT) return FR_NOT_READY;
3868 if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
3869 if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
3870
3871 /* Determine CHS in the table regardless of the drive geometry */
3872 for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
3873 if (n == 256) n--;
3874 e_hd = n - 1;
3875 sz_cyl = 63 * n;
3876 tot_cyl = sz_disk / sz_cyl;
3877
3878 /* Create partition table */
3879 mem_set(buf, 0, _MAX_SS);
3880 p = buf + MBR_Table; b_cyl = 0;
3881 for (i = 0; i < 4; i++, p += SZ_PTE) {
3882 p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
3883 if (!p_cyl) continue;
3884 s_part = (DWORD)sz_cyl * b_cyl;
3885 sz_part = (DWORD)sz_cyl * p_cyl;
3886 if (i == 0) { /* Exclude first track of cylinder 0 */
3887 s_hd = 1;
3888 s_part += 63; sz_part -= 63;
3889 } else {
3890 s_hd = 0;
3891 }
3892 e_cyl = b_cyl + p_cyl - 1;
3893 if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
3894
3895 /* Set partition table */
3896 p[1] = s_hd; /* Start head */
3897 p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */
3898 p[3] = (BYTE)b_cyl; /* Start cylinder */
3899 p[4] = 0x06; /* System type (temporary setting) */
3900 p[5] = e_hd; /* End head */
3901 p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */
3902 p[7] = (BYTE)e_cyl; /* End cylinder */
3903 ST_DWORD(p + 8, s_part); /* Start sector in LBA */
3904 ST_DWORD(p + 12, sz_part); /* Partition size */
3905
3906 /* Next partition */
3907 b_cyl += p_cyl;
3908 }
3909 ST_WORD(p, 0xAA55);
3910
3911 /* Write it to the MBR */
3912 return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;
3913}
3914
3915
3916#endif /* _MULTI_PARTITION == 2 */
3917#endif /* _USE_MKFS && !_FS_READONLY */
3918
3919
3920
3921
3922#if _USE_STRFUNC
3923/*-----------------------------------------------------------------------*/
3924/* Get a string from the file */
3925/*-----------------------------------------------------------------------*/
3926TCHAR* f_gets (
3927 TCHAR* buff, /* Pointer to the string buffer to read */
3928 int len, /* Size of string buffer (characters) */
3929 FIL* fil /* Pointer to the file object */
3930)
3931{
3932 int n = 0;
3933 TCHAR c, *p = buff;
3934 BYTE s[2];
3935 UINT rc;
3936
3937
3938 while (n < len - 1) { /* Read bytes until buffer gets filled */
3939 f_read(fil, s, 1, &rc);
3940 if (rc != 1) break; /* Break on EOF or error */
3941 c = s[0];
3942#if _LFN_UNICODE /* Read a character in UTF-8 encoding */
3943 if (c >= 0x80) {
3944 if (c < 0xC0) continue; /* Skip stray trailer */
3945 if (c < 0xE0) { /* Two-byte sequence */
3946 f_read(fil, s, 1, &rc);
3947 if (rc != 1) break;
3948 c = ((c & 0x1F) << 6) | (s[0] & 0x3F);
3949 if (c < 0x80) c = '?';
3950 } else {
3951 if (c < 0xF0) { /* Three-byte sequence */
3952 f_read(fil, s, 2, &rc);
3953 if (rc != 2) break;
3954 c = (c << 12) | ((s[0] & 0x3F) << 6) | (s[1] & 0x3F);
3955 if (c < 0x800) c = '?';
3956 } else { /* Reject four-byte sequence */
3957 c = '?';
3958 }
3959 }
3960 }
3961#endif
3962#if _USE_STRFUNC >= 2
3963 if (c == '\r') continue; /* Strip '\r' */
3964#endif
3965 *p++ = c;
3966 n++;
3967 if (c == '\n') break; /* Break on EOL */
3968 }
3969 *p = 0;
3970 return n ? buff : 0; /* When no data read (eof or error), return with error. */
3971}
3972
3973
3974
3975#if !_FS_READONLY
3976#include <stdarg.h>
3977/*-----------------------------------------------------------------------*/
3978/* Put a character to the file */
3979/*-----------------------------------------------------------------------*/
3980int f_putc (
3981 TCHAR c, /* A character to be output */
3982 FIL* fil /* Pointer to the file object */
3983)
3984{
3985 UINT bw, btw;
3986 BYTE s[3];
3987
3988
3989#if _USE_STRFUNC >= 2
3990 if (c == '\n') f_putc ('\r', fil); /* LF -> CRLF conversion */
3991#endif
3992
3993#if _LFN_UNICODE /* Write the character in UTF-8 encoding */
3994 if (c < 0x80) { /* 7-bit */
3995 s[0] = (BYTE)c;
3996 btw = 1;
3997 } else {
3998 if (c < 0x800) { /* 11-bit */
3999 s[0] = (BYTE)(0xC0 | (c >> 6));
4000 s[1] = (BYTE)(0x80 | (c & 0x3F));
4001 btw = 2;
4002 } else { /* 16-bit */
4003 s[0] = (BYTE)(0xE0 | (c >> 12));
4004 s[1] = (BYTE)(0x80 | ((c >> 6) & 0x3F));
4005 s[2] = (BYTE)(0x80 | (c & 0x3F));
4006 btw = 3;
4007 }
4008 }
4009#else /* Write the character without conversion */
4010 s[0] = (BYTE)c;
4011 btw = 1;
4012#endif
4013 f_write(fil, s, btw, &bw); /* Write the char to the file */
4014 return (bw == btw) ? 1 : EOF; /* Return the result */
4015}
4016
4017
4018
4019
4020/*-----------------------------------------------------------------------*/
4021/* Put a string to the file */
4022/*-----------------------------------------------------------------------*/
4023int f_puts (
4024 const TCHAR* str, /* Pointer to the string to be output */
4025 FIL* fil /* Pointer to the file object */
4026)
4027{
4028 int n;
4029
4030
4031 for (n = 0; *str; str++, n++) {
4032 if (f_putc(*str, fil) == EOF) return EOF;
4033 }
4034 return n;
4035}
4036
4037
4038
4039
4040/*-----------------------------------------------------------------------*/
4041/* Put a formatted string to the file */
4042/*-----------------------------------------------------------------------*/
4043int f_printf (
4044 FIL* fil, /* Pointer to the file object */
4045 const TCHAR* str, /* Pointer to the format string */
4046 ... /* Optional arguments... */
4047)
4048{
4049 va_list arp;
4050 BYTE f, r;
4051 UINT i, j, w;
4052 ULONG v;
4053 TCHAR c, d, s[16], *p;
4054 int res, chc, cc;
4055
4056
4057 va_start(arp, str);
4058
4059 for (cc = res = 0; cc != EOF; res += cc) {
4060 c = *str++;
4061 if (c == 0) break; /* End of string */
4062 if (c != '%') { /* Non escape character */
4063 cc = f_putc(c, fil);
4064 if (cc != EOF) cc = 1;
4065 continue;
4066 }
4067 w = f = 0;
4068 c = *str++;
4069 if (c == '0') { /* Flag: '0' padding */
4070 f = 1; c = *str++;
4071 } else {
4072 if (c == '-') { /* Flag: left justified */
4073 f = 2; c = *str++;
4074 }
4075 }
4076 while (IsDigit(c)) { /* Precision */
4077 w = w * 10 + c - '0';
4078 c = *str++;
4079 }
4080 if (c == 'l' || c == 'L') { /* Prefix: Size is long int */
4081 f |= 4; c = *str++;
4082 }
4083 if (!c) break;
4084 d = c;
4085 if (IsLower(d)) d -= 0x20;
4086 switch (d) { /* Type is... */
4087 case 'S' : /* String */
4088 p = va_arg(arp, TCHAR*);
4089 for (j = 0; p[j]; j++) ;
4090 chc = 0;
4091 if (!(f & 2)) {
4092 while (j++ < w) chc += (cc = f_putc(' ', fil));
4093 }
4094 chc += (cc = f_puts(p, fil));
4095 while (j++ < w) chc += (cc = f_putc(' ', fil));
4096 if (cc != EOF) cc = chc;
4097 continue;
4098 case 'C' : /* Character */
4099 cc = f_putc((TCHAR)va_arg(arp, int), fil); continue;
4100 case 'B' : /* Binary */
4101 r = 2; break;
4102 case 'O' : /* Octal */
4103 r = 8; break;
4104 case 'D' : /* Signed decimal */
4105 case 'U' : /* Unsigned decimal */
4106 r = 10; break;
4107 case 'X' : /* Hexdecimal */
4108 r = 16; break;
4109 default: /* Unknown type (pass-through) */
4110 cc = f_putc(c, fil); continue;
4111 }
4112
4113 /* Get an argument and put it in numeral */
4114 v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int));
4115 if (d == 'D' && (v & 0x80000000)) {
4116 v = 0 - v;
4117 f |= 8;
4118 }
4119 i = 0;
4120 do {
4121 d = (TCHAR)(v % r); v /= r;
4122 if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
4123 s[i++] = d + '0';
4124 } while (v && i < sizeof s / sizeof s[0]);
4125 if (f & 8) s[i++] = '-';
4126 j = i; d = (f & 1) ? '0' : ' ';
4127 res = 0;
4128 while (!(f & 2) && j++ < w) res += (cc = f_putc(d, fil));
4129 do res += (cc = f_putc(s[--i], fil)); while(i);
4130 while (j++ < w) res += (cc = f_putc(' ', fil));
4131 if (cc != EOF) cc = res;
4132 }
4133
4134 va_end(arp);
4135 return (cc == EOF) ? cc : res;
4136}
4137
4138#endif /* !_FS_READONLY */
4139#endif /* _USE_STRFUNC */
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.h b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.h
new file mode 100644
index 000000000..627cbaabe
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ff.h
@@ -0,0 +1,337 @@
1/*---------------------------------------------------------------------------/
2/ FatFs - FAT file system module include file R0.09a (C)ChaN, 2012
3/----------------------------------------------------------------------------/
4/ FatFs module is a generic FAT file system module for small embedded systems.
5/ This is a free software that opened for education, research and commercial
6/ developments under license policy of following terms.
7/
8/ Copyright (C) 2012, ChaN, all right reserved.
9/
10/ * The FatFs module is a free software and there is NO WARRANTY.
11/ * No restriction on use. You can use, modify and redistribute it for
12/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
13/ * Redistributions of source code must retain the above copyright notice.
14/
15/----------------------------------------------------------------------------*/
16
17#ifndef _FATFS
18#define _FATFS 4004 /* Revision ID */
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24#include "integer.h" /* Basic integer types */
25#include "ffconf.h" /* FatFs configuration options */
26
27#if _FATFS != _FFCONF
28#error Wrong configuration file (ffconf.h).
29#endif
30
31
32
33/* Definitions of volume management */
34
35#if _MULTI_PARTITION /* Multiple partition configuration */
36typedef struct {
37 BYTE pd; /* Physical drive number */
38 BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
39} PARTITION;
40extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
41#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
42#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
43
44#else /* Single partition configuration */
45#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
46#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */
47
48#endif
49
50
51
52/* Type of path name strings on FatFs API */
53
54#if _LFN_UNICODE /* Unicode string */
55#if !_USE_LFN
56#error _LFN_UNICODE must be 0 in non-LFN cfg.
57#endif
58#ifndef _INC_TCHAR
59typedef WCHAR TCHAR;
60#define _T(x) L ## x
61#define _TEXT(x) L ## x
62#endif
63
64#else /* ANSI/OEM string */
65#ifndef _INC_TCHAR
66typedef char TCHAR;
67#define _T(x) x
68#define _TEXT(x) x
69#endif
70
71#endif
72
73
74
75/* File system object structure (FATFS) */
76
77typedef struct {
78 BYTE fs_type; /* FAT sub-type (0:Not mounted) */
79 BYTE drv; /* Physical drive number */
80 BYTE csize; /* Sectors per cluster (1,2,4...128) */
81 BYTE n_fats; /* Number of FAT copies (1,2) */
82 BYTE wflag; /* win[] dirty flag (1:must be written back) */
83 BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */
84 WORD id; /* File system mount ID */
85 WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
86#if _MAX_SS != 512
87 WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
88#endif
89#if _FS_REENTRANT
90 _SYNC_t sobj; /* Identifier of sync object */
91#endif
92#if !_FS_READONLY
93 DWORD last_clust; /* Last allocated cluster */
94 DWORD free_clust; /* Number of free clusters */
95 DWORD fsi_sector; /* fsinfo sector (FAT32) */
96#endif
97#if _FS_RPATH
98 DWORD cdir; /* Current directory start cluster (0:root) */
99#endif
100 DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */
101 DWORD fsize; /* Sectors per FAT */
102 DWORD fatbase; /* FAT start sector */
103 DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
104 DWORD database; /* Data start sector */
105 DWORD winsect; /* Current sector appearing in the win[] */
106 BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */
107} FATFS;
108
109
110
111/* File object structure (FIL) */
112
113typedef struct {
114 FATFS* fs; /* Pointer to the related file system object */
115 WORD id; /* File system mount ID of the related file system object */
116 BYTE flag; /* File status flags */
117 BYTE pad1;
118 DWORD fptr; /* File read/write pointer (0ed on file open) */
119 DWORD fsize; /* File size */
120 DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
121 DWORD clust; /* Current cluster of fpter */
122 DWORD dsect; /* Current data sector of fpter */
123#if !_FS_READONLY
124 DWORD dir_sect; /* Sector containing the directory entry */
125 BYTE* dir_ptr; /* Pointer to the directory entry in the window */
126#endif
127#if _USE_FASTSEEK
128 DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
129#endif
130#if _FS_LOCK
131 UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
132#endif
133#if !_FS_TINY
134 BYTE buf[_MAX_SS]; /* File data read/write buffer */
135#endif
136} FIL;
137
138
139
140/* Directory object structure (DIR) */
141
142typedef struct {
143 FATFS* fs; /* Pointer to the owner file system object */
144 WORD id; /* Owner file system mount ID */
145 WORD index; /* Current read/write index number */
146 DWORD sclust; /* Table start cluster (0:Root dir) */
147 DWORD clust; /* Current cluster */
148 DWORD sect; /* Current sector */
149 BYTE* dir; /* Pointer to the current SFN entry in the win[] */
150 BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
151#if _USE_LFN
152 WCHAR* lfn; /* Pointer to the LFN working buffer */
153 WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
154#endif
155} DIR;
156
157
158
159/* File status structure (FILINFO) */
160
161typedef struct {
162 DWORD fsize; /* File size */
163 WORD fdate; /* Last modified date */
164 WORD ftime; /* Last modified time */
165 BYTE fattrib; /* Attribute */
166 TCHAR fname[13]; /* Short file name (8.3 format) */
167#if _USE_LFN
168 TCHAR* lfname; /* Pointer to the LFN buffer */
169 UINT lfsize; /* Size of LFN buffer in TCHAR */
170#endif
171} FILINFO;
172
173
174
175/* File function return code (FRESULT) */
176
177typedef enum {
178 FR_OK = 0, /* (0) Succeeded */
179 FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
180 FR_INT_ERR, /* (2) Assertion failed */
181 FR_NOT_READY, /* (3) The physical drive cannot work */
182 FR_NO_FILE, /* (4) Could not find the file */
183 FR_NO_PATH, /* (5) Could not find the path */
184 FR_INVALID_NAME, /* (6) The path name format is invalid */
185 FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
186 FR_EXIST, /* (8) Access denied due to prohibited access */
187 FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
188 FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
189 FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
190 FR_NOT_ENABLED, /* (12) The volume has no work area */
191 FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
192 FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
193 FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
194 FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
195 FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
196 FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
197 FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
198} FRESULT;
199
200
201
202/*--------------------------------------------------------------*/
203/* FatFs module application interface */
204
205FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */
206FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */
207FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */
208FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */
209FRESULT f_close (FIL*); /* Close an open file object */
210FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */
211FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */
212FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */
213FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */
214FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */
215FRESULT f_truncate (FIL*); /* Truncate file */
216FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
217FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
218FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
219FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */
220FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change times-tamp of the file/dir */
221FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
222FRESULT f_chdrive (BYTE); /* Change current drive */
223FRESULT f_chdir (const TCHAR*); /* Change current directory */
224FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
225FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
226FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
227FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */
228int f_putc (TCHAR, FIL*); /* Put a character to the file */
229int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
230int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
231TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
232
233#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
234#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
235#define f_tell(fp) ((fp)->fptr)
236#define f_size(fp) ((fp)->fsize)
237
238#ifndef EOF
239#define EOF (-1)
240#endif
241
242
243
244
245/*--------------------------------------------------------------*/
246/* Additional user defined functions */
247
248/* RTC function */
249#if !_FS_READONLY
250DWORD get_fattime (void);
251#endif
252
253/* Unicode support functions */
254#if _USE_LFN /* Unicode - OEM code conversion */
255WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */
256WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */
257#if _USE_LFN == 3 /* Memory functions */
258void* ff_memalloc (UINT); /* Allocate memory block */
259void ff_memfree (void*); /* Free memory block */
260#endif
261#endif
262
263/* Sync functions */
264#if _FS_REENTRANT
265int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */
266int ff_req_grant (_SYNC_t); /* Lock sync object */
267void ff_rel_grant (_SYNC_t); /* Unlock sync object */
268int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
269#endif
270
271
272
273
274/*--------------------------------------------------------------*/
275/* Flags and offset address */
276
277
278/* File access control and file status flags (FIL.flag) */
279
280#define FA_READ 0x01
281#define FA_OPEN_EXISTING 0x00
282#define FA__ERROR 0x80
283
284#if !_FS_READONLY
285#define FA_WRITE 0x02
286#define FA_CREATE_NEW 0x04
287#define FA_CREATE_ALWAYS 0x08
288#define FA_OPEN_ALWAYS 0x10
289#define FA__WRITTEN 0x20
290#define FA__DIRTY 0x40
291#endif
292
293
294/* FAT sub type (FATFS.fs_type) */
295
296#define FS_FAT12 1
297#define FS_FAT16 2
298#define FS_FAT32 3
299
300
301/* File attribute bits for directory entry */
302
303#define AM_RDO 0x01 /* Read only */
304#define AM_HID 0x02 /* Hidden */
305#define AM_SYS 0x04 /* System */
306#define AM_VOL 0x08 /* Volume label */
307#define AM_LFN 0x0F /* LFN entry */
308#define AM_DIR 0x10 /* Directory */
309#define AM_ARC 0x20 /* Archive */
310#define AM_MASK 0x3F /* Mask of defined bits */
311
312
313/* Fast seek feature */
314#define CREATE_LINKMAP 0xFFFFFFFF
315
316
317
318/*--------------------------------*/
319/* Multi-byte word access macros */
320
321#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
322#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
323#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
324#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
325#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
326#else /* Use byte-by-byte access to the FAT structure */
327#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
328#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
329#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
330#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
331#endif
332
333#ifdef __cplusplus
334}
335#endif
336
337#endif /* _FATFS */
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ffconf.h b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ffconf.h
new file mode 100644
index 000000000..63a4e7823
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/ffconf.h
@@ -0,0 +1,191 @@
1/*---------------------------------------------------------------------------/
2/ FatFs - FAT file system module configuration file R0.09a (C)ChaN, 2012
3/----------------------------------------------------------------------------/
4/
5/ CAUTION! Do not forget to make clean the project after any changes to
6/ the configuration options.
7/
8/----------------------------------------------------------------------------*/
9#ifndef _FFCONF
10#define _FFCONF 4004 /* Revision ID */
11
12
13/*---------------------------------------------------------------------------/
14/ Function and Buffer Configurations
15/----------------------------------------------------------------------------*/
16
17#define _FS_TINY 1 /* 0:Normal or 1:Tiny */
18/* When _FS_TINY is set to 1, FatFs uses the sector buffer in the file system
19/ object instead of the sector buffer in the individual file object for file
20/ data transfer. This reduces memory consumption 512 bytes each file object. */
21
22
23#define _FS_READONLY 0 /* 0:Read/Write or 1:Read only */
24/* Setting _FS_READONLY to 1 defines read only configuration. This removes
25/ writing functions, f_write, f_sync, f_unlink, f_mkdir, f_chmod, f_rename,
26/ f_truncate and useless f_getfree. */
27
28
29#define _FS_MINIMIZE 2 /* 0 to 3 */
30/* The _FS_MINIMIZE option defines minimization level to remove some functions.
31/
32/ 0: Full function.
33/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod, f_truncate and f_rename
34/ are removed.
35/ 2: f_opendir and f_readdir are removed in addition to 1.
36/ 3: f_lseek is removed in addition to 2. */
37
38
39#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */
40/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
41
42
43#define _USE_MKFS 0 /* 0:Disable or 1:Enable */
44/* To enable f_mkfs function, set _USE_MKFS to 1 and set _FS_READONLY to 0 */
45
46
47#define _USE_FORWARD 0 /* 0:Disable or 1:Enable */
48/* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */
49
50
51#define _USE_FASTSEEK 0 /* 0:Disable or 1:Enable */
52/* To enable fast seek feature, set _USE_FASTSEEK to 1. */
53
54
55
56/*---------------------------------------------------------------------------/
57/ Locale and Namespace Configurations
58/----------------------------------------------------------------------------*/
59
60#define _CODE_PAGE 932
61/* The _CODE_PAGE specifies the OEM code page to be used on the target system.
62/ Incorrect setting of the code page can cause a file open failure.
63/
64/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows)
65/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
66/ 949 - Korean (DBCS, OEM, Windows)
67/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
68/ 1250 - Central Europe (Windows)
69/ 1251 - Cyrillic (Windows)
70/ 1252 - Latin 1 (Windows)
71/ 1253 - Greek (Windows)
72/ 1254 - Turkish (Windows)
73/ 1255 - Hebrew (Windows)
74/ 1256 - Arabic (Windows)
75/ 1257 - Baltic (Windows)
76/ 1258 - Vietnam (OEM, Windows)
77/ 437 - U.S. (OEM)
78/ 720 - Arabic (OEM)
79/ 737 - Greek (OEM)
80/ 775 - Baltic (OEM)
81/ 850 - Multilingual Latin 1 (OEM)
82/ 858 - Multilingual Latin 1 + Euro (OEM)
83/ 852 - Latin 2 (OEM)
84/ 855 - Cyrillic (OEM)
85/ 866 - Russian (OEM)
86/ 857 - Turkish (OEM)
87/ 862 - Hebrew (OEM)
88/ 874 - Thai (OEM, Windows)
89/ 1 - ASCII only (Valid for non LFN cfg.)
90*/
91
92
93#define _USE_LFN 0 /* 0 to 3 */
94#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
95/* The _USE_LFN option switches the LFN support.
96/
97/ 0: Disable LFN feature. _MAX_LFN and _LFN_UNICODE have no effect.
98/ 1: Enable LFN with static working buffer on the BSS. Always NOT reentrant.
99/ 2: Enable LFN with dynamic working buffer on the STACK.
100/ 3: Enable LFN with dynamic working buffer on the HEAP.
101/
102/ The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. To enable LFN,
103/ Unicode handling functions ff_convert() and ff_wtoupper() must be added
104/ to the project. When enable to use heap, memory control functions
105/ ff_memalloc() and ff_memfree() must be added to the project. */
106
107
108#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
109/* To switch the character code set on FatFs API to Unicode,
110/ enable LFN feature and set _LFN_UNICODE to 1. */
111
112
113#define _FS_RPATH 0 /* 0 to 2 */
114/* The _FS_RPATH option configures relative path feature.
115/
116/ 0: Disable relative path feature and remove related functions.
117/ 1: Enable relative path. f_chdrive() and f_chdir() are available.
118/ 2: f_getcwd() is available in addition to 1.
119/
120/ Note that output of the f_readdir fnction is affected by this option. */
121
122
123
124/*---------------------------------------------------------------------------/
125/ Physical Drive Configurations
126/----------------------------------------------------------------------------*/
127
128#define _VOLUMES 1
129/* Number of volumes (logical drives) to be used. */
130
131
132#define _MAX_SS 512 /* 512, 1024, 2048 or 4096 */
133/* Maximum sector size to be handled.
134/ Always set 512 for memory card and hard disk but a larger value may be
135/ required for on-board flash memory, floppy disk and optical disk.
136/ When _MAX_SS is larger than 512, it configures FatFs to variable sector size
137/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */
138
139
140#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */
141/* When set to 0, each volume is bound to the same physical drive number and
142/ it can mount only first primaly partition. When it is set to 1, each volume
143/ is tied to the partitions listed in VolToPart[]. */
144
145
146#define _USE_ERASE 0 /* 0:Disable or 1:Enable */
147/* To enable sector erase feature, set _USE_ERASE to 1. CTRL_ERASE_SECTOR command
148/ should be added to the disk_ioctl functio. */
149
150
151
152/*---------------------------------------------------------------------------/
153/ System Configurations
154/----------------------------------------------------------------------------*/
155
156#define _WORD_ACCESS 1 /* 0 or 1 */
157/* Set 0 first and it is always compatible with all platforms. The _WORD_ACCESS
158/ option defines which access method is used to the word data on the FAT volume.
159/
160/ 0: Byte-by-byte access.
161/ 1: Word access. Do not choose this unless following condition is met.
162/
163/ When the byte order on the memory is big-endian or address miss-aligned word
164/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
165/ If it is not the case, the value can also be set to 1 to improve the
166/ performance and code size.
167*/
168
169
170/* A header file that defines sync object types on the O/S, such as
171/ windows.h, ucos_ii.h and semphr.h, must be included prior to ff.h. */
172
173#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */
174#define _FS_TIMEOUT 1000 /* Timeout period in unit of time ticks */
175#define _SYNC_t HANDLE /* O/S dependent type of sync object. e.g. HANDLE, OS_EVENT*, ID and etc.. */
176
177/* The _FS_REENTRANT option switches the reentrancy (thread safe) of the FatFs module.
178/
179/ 0: Disable reentrancy. _SYNC_t and _FS_TIMEOUT have no effect.
180/ 1: Enable reentrancy. Also user provided synchronization handlers,
181/ ff_req_grant, ff_rel_grant, ff_del_syncobj and ff_cre_syncobj
182/ function must be added to the project. */
183
184
185#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
186/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
187 The value defines how many files can be opened simultaneously. */
188
189
190#endif /* _FFCONFIG */
191
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/FATFs/integer.h b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/integer.h
new file mode 100644
index 000000000..5408fe6b3
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/FATFs/integer.h
@@ -0,0 +1,38 @@
1/*-------------------------------------------*/
2/* Integer type definitions for FatFs module */
3/*-------------------------------------------*/
4
5#ifndef _INTEGER
6#define _INTEGER
7
8#ifdef _WIN32 /* FatFs development platform */
9
10#include <windows.h>
11#include <tchar.h>
12
13#else /* Embedded platform */
14
15/* These types must be 16-bit, 32-bit or larger integer */
16typedef int INT;
17typedef unsigned int UINT;
18
19/* These types must be 8-bit integer */
20typedef char CHAR;
21typedef unsigned char UCHAR;
22typedef unsigned char BYTE;
23
24/* These types must be 16-bit integer */
25typedef short SHORT;
26typedef unsigned short USHORT;
27typedef unsigned short WORD;
28typedef unsigned short WCHAR;
29
30/* These types must be 32-bit integer */
31typedef long LONG;
32typedef unsigned long ULONG;
33typedef unsigned long DWORD;
34
35#endif
36
37#endif
38
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/RTC.c b/lib/lufa/Projects/TempDataLogger/Lib/RTC.c
new file mode 100644
index 000000000..a5291eaf3
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/RTC.c
@@ -0,0 +1,159 @@
1/*
2 Copyright (C) Dean Camera, 2017.
3
4 dean [at] fourwalledcubicle [dot] com
5 www.lufa-lib.org
6*/
7
8#include "RTC.h"
9
10#if defined(DUMMY_RTC)
11
12/** Current dummy RTC time and date */
13static volatile TimeDate_t DummyRTC_Count;
14
15void RTC_Init(void)
16{
17 DummyRTC_Count.Hour = 0;
18 DummyRTC_Count.Minute = 0;
19 DummyRTC_Count.Second = 0;
20 DummyRTC_Count.Day = 1;
21 DummyRTC_Count.Month = 1;
22 DummyRTC_Count.Year = 00;
23}
24
25void RTC_Tick500ms(void)
26{
27 static bool HalfSecondElapsed = false;
28
29 HalfSecondElapsed = !HalfSecondElapsed;
30 if (HalfSecondElapsed == false)
31 return;
32
33 if (++DummyRTC_Count.Second < 60)
34 return;
35
36 DummyRTC_Count.Second = 0;
37
38 if (++DummyRTC_Count.Minute < 60)
39 return;
40
41 DummyRTC_Count.Minute = 0;
42
43 if (++DummyRTC_Count.Hour < 24)
44 return;
45
46 DummyRTC_Count.Hour = 0;
47
48 static const char MonthLength[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
49 uint8_t DaysInMonth = MonthLength[DummyRTC_Count.Month - 1];
50
51 /* Check if we need to account for a leap year */
52 if ((DummyRTC_Count.Month == 2) &&
53 ((!(DummyRTC_Count.Year % 400)) || ((DummyRTC_Count.Year % 100) && !(DummyRTC_Count.Year % 4))))
54 {
55 DaysInMonth++;
56 }
57
58 if (++DummyRTC_Count.Day <= DaysInMonth)
59 return;
60
61 DummyRTC_Count.Day = 1;
62
63 if (++DummyRTC_Count.Month <= 12)
64 return;
65
66 DummyRTC_Count.Month = 1;
67 DummyRTC_Count.Year++;
68}
69
70bool RTC_SetTimeDate(const TimeDate_t* NewTimeDate)
71{
72 GlobalInterruptDisable();
73 DummyRTC_Count = *NewTimeDate;
74 GlobalInterruptEnable();
75
76 return true;
77}
78
79bool RTC_GetTimeDate(TimeDate_t* const TimeDate)
80{
81 GlobalInterruptDisable();
82 *TimeDate = DummyRTC_Count;
83 GlobalInterruptEnable();
84
85 return true;
86}
87
88#else
89
90void RTC_Init(void)
91{
92 /* Unused for a real external DS1307 RTC device */
93}
94
95void RTC_Tick500ms(void)
96{
97 /* Unused for a real external DS1307 RTC device */
98}
99
100bool RTC_SetTimeDate(const TimeDate_t* NewTimeDate)
101{
102 DS1307_DateTimeRegs_t NewRegValues;
103 const uint8_t WriteAddress = 0;
104
105 // Convert new time data to the DS1307's time register layout
106 NewRegValues.Byte1.Fields.TenSec = (NewTimeDate->Second / 10);
107 NewRegValues.Byte1.Fields.Sec = (NewTimeDate->Second % 10);
108 NewRegValues.Byte1.Fields.CH = false;
109 NewRegValues.Byte2.Fields.TenMin = (NewTimeDate->Minute / 10);
110 NewRegValues.Byte2.Fields.Min = (NewTimeDate->Minute % 10);
111 NewRegValues.Byte3.Fields.TenHour = (NewTimeDate->Hour / 10);
112 NewRegValues.Byte3.Fields.Hour = (NewTimeDate->Hour % 10);
113 NewRegValues.Byte3.Fields.TwelveHourMode = false;
114
115 // Convert new date data to the DS1307's date register layout
116 NewRegValues.Byte4.Fields.DayOfWeek = 0;
117 NewRegValues.Byte5.Fields.TenDay = (NewTimeDate->Day / 10);
118 NewRegValues.Byte5.Fields.Day = (NewTimeDate->Day % 10);
119 NewRegValues.Byte6.Fields.TenMonth = (NewTimeDate->Month / 10);
120 NewRegValues.Byte6.Fields.Month = (NewTimeDate->Month % 10);
121 NewRegValues.Byte7.Fields.TenYear = (NewTimeDate->Year / 10);
122 NewRegValues.Byte7.Fields.Year = (NewTimeDate->Year % 10);
123
124 // Write the new Time and Date into the DS1307
125 if (TWI_WritePacket(DS1307_ADDRESS, 10, &WriteAddress, sizeof(WriteAddress),
126 (uint8_t*)&NewRegValues, sizeof(DS1307_DateTimeRegs_t)) != TWI_ERROR_NoError)
127 {
128 return false;
129 }
130
131 return true;
132}
133
134bool RTC_GetTimeDate(TimeDate_t* const TimeDate)
135{
136 DS1307_DateTimeRegs_t CurrentRegValues;
137 const uint8_t ReadAddress = 0;
138
139 // Read in the stored Time and Date from the DS1307
140 if (TWI_ReadPacket(DS1307_ADDRESS, 10, &ReadAddress, sizeof(ReadAddress),
141 (uint8_t*)&CurrentRegValues, sizeof(DS1307_DateTimeRegs_t)) != TWI_ERROR_NoError)
142 {
143 return false;
144 }
145
146 // Convert stored time value into decimal
147 TimeDate->Second = (CurrentRegValues.Byte1.Fields.TenSec * 10) + CurrentRegValues.Byte1.Fields.Sec;
148 TimeDate->Minute = (CurrentRegValues.Byte2.Fields.TenMin * 10) + CurrentRegValues.Byte2.Fields.Min;
149 TimeDate->Hour = (CurrentRegValues.Byte3.Fields.TenHour * 10) + CurrentRegValues.Byte3.Fields.Hour;
150
151 // Convert stored date value into decimal
152 TimeDate->Day = (CurrentRegValues.Byte5.Fields.TenDay * 10) + CurrentRegValues.Byte5.Fields.Day;
153 TimeDate->Month = (CurrentRegValues.Byte6.Fields.TenMonth * 10) + CurrentRegValues.Byte6.Fields.Month;
154 TimeDate->Year = (CurrentRegValues.Byte7.Fields.TenYear * 10) + CurrentRegValues.Byte7.Fields.Year;
155
156 return true;
157}
158
159#endif
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/RTC.h b/lib/lufa/Projects/TempDataLogger/Lib/RTC.h
new file mode 100644
index 000000000..f35b8ff1e
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/RTC.h
@@ -0,0 +1,126 @@
1/*
2 Copyright (C) Dean Camera, 2017.
3
4 dean [at] fourwalledcubicle [dot] com
5 www.lufa-lib.org
6*/
7
8#ifndef _RTC_H_
9#define _RTC_H_
10
11 /* Includes: */
12 #include <avr/io.h>
13
14 #include <LUFA/Drivers/Peripheral/TWI.h>
15
16 #include "Config/AppConfig.h"
17
18 /* Type Defines: */
19 typedef struct
20 {
21 uint8_t Hour;
22 uint8_t Minute;
23 uint8_t Second;
24 uint8_t Day;
25 uint8_t Month;
26 uint8_t Year;
27 } TimeDate_t;
28
29 typedef struct
30 {
31 union
32 {
33 struct
34 {
35 unsigned Sec : 4;
36 unsigned TenSec : 3;
37 unsigned CH : 1;
38 } Fields;
39
40 uint8_t IntVal;
41 } Byte1;
42
43 union
44 {
45 struct
46 {
47 unsigned Min : 4;
48 unsigned TenMin : 3;
49 unsigned Reserved : 1;
50 } Fields;
51
52 uint8_t IntVal;
53 } Byte2;
54
55 union
56 {
57 struct
58 {
59 unsigned Hour : 4;
60 unsigned TenHour : 2;
61 unsigned TwelveHourMode : 1;
62 unsigned Reserved : 1;
63 } Fields;
64
65 uint8_t IntVal;
66 } Byte3;
67
68 union
69 {
70 struct
71 {
72 unsigned DayOfWeek : 3;
73 unsigned Reserved : 5;
74 } Fields;
75
76 uint8_t IntVal;
77 } Byte4;
78
79 union
80 {
81 struct
82 {
83 unsigned Day : 4;
84 unsigned TenDay : 2;
85 unsigned Reserved : 2;
86 } Fields;
87
88 uint8_t IntVal;
89 } Byte5;
90
91 union
92 {
93 struct
94 {
95 unsigned Month : 4;
96 unsigned TenMonth : 1;
97 unsigned Reserved : 3;
98 } Fields;
99
100 uint8_t IntVal;
101 } Byte6;
102
103 union
104 {
105 struct
106 {
107 unsigned Year : 4;
108 unsigned TenYear : 4;
109 } Fields;
110
111 uint8_t IntVal;
112 } Byte7;
113 } DS1307_DateTimeRegs_t;
114
115 /* Macros: */
116 /** TWI address of the DS1307 device on the bus. */
117 #define DS1307_ADDRESS 0xD0
118
119 /* Function Prototypes: */
120 void RTC_Init(void);
121 void RTC_Tick500ms(void);
122 bool RTC_SetTimeDate(const TimeDate_t* NewTimeDate);
123 bool RTC_GetTimeDate(TimeDate_t* const TimeDate);
124
125#endif
126
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/SCSI.c b/lib/lufa/Projects/TempDataLogger/Lib/SCSI.c
new file mode 100644
index 000000000..4fbbfd60e
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/SCSI.c
@@ -0,0 +1,344 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 *
33 * SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
34 * devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
35 * which wrap around standard SCSI device commands for controlling the actual storage medium.
36 */
37
38#define INCLUDE_FROM_SCSI_C
39#include "SCSI.h"
40
41/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
42 * features and capabilities.
43 */
44static const SCSI_Inquiry_Response_t InquiryData =
45 {
46 .DeviceType = DEVICE_TYPE_BLOCK,
47 .PeripheralQualifier = 0,
48
49 .Removable = true,
50
51 .Version = 0,
52
53 .ResponseDataFormat = 2,
54 .NormACA = false,
55 .TrmTsk = false,
56 .AERC = false,
57
58 .AdditionalLength = 0x1F,
59
60 .SoftReset = false,
61 .CmdQue = false,
62 .Linked = false,
63 .Sync = false,
64 .WideBus16Bit = false,
65 .WideBus32Bit = false,
66 .RelAddr = false,
67
68 .VendorID = "LUFA",
69 .ProductID = "Dataflash Disk",
70 .RevisionID = {'0','.','0','0'},
71 };
72
73/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
74 * command is issued. This gives information on exactly why the last command failed to complete.
75 */
76static SCSI_Request_Sense_Response_t SenseData =
77 {
78 .ResponseCode = 0x70,
79 .AdditionalLength = 0x0A,
80 };
81
82
83/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
84 * to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
85 * a command failure due to a ILLEGAL REQUEST.
86 *
87 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
88 *
89 * \return Boolean \c true if the command completed successfully, \c false otherwise
90 */
91bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
92{
93 bool CommandSuccess = false;
94
95 /* Run the appropriate SCSI command hander function based on the passed command */
96 switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
97 {
98 case SCSI_CMD_INQUIRY:
99 CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
100 break;
101 case SCSI_CMD_REQUEST_SENSE:
102 CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
103 break;
104 case SCSI_CMD_READ_CAPACITY_10:
105 CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
106 break;
107 case SCSI_CMD_SEND_DIAGNOSTIC:
108 CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
109 break;
110 case SCSI_CMD_WRITE_10:
111 CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
112 break;
113 case SCSI_CMD_READ_10:
114 CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
115 break;
116 case SCSI_CMD_MODE_SENSE_6:
117 CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
118 break;
119 case SCSI_CMD_START_STOP_UNIT:
120 case SCSI_CMD_TEST_UNIT_READY:
121 case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
122 case SCSI_CMD_VERIFY_10:
123 /* These commands should just succeed, no handling required */
124 CommandSuccess = true;
125 MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
126 break;
127 default:
128 /* Update the SENSE key to reflect the invalid command */
129 SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
130 SCSI_ASENSE_INVALID_COMMAND,
131 SCSI_ASENSEQ_NO_QUALIFIER);
132 break;
133 }
134
135 /* Check if command was successfully processed */
136 if (CommandSuccess)
137 {
138 SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
139 SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
140 SCSI_ASENSEQ_NO_QUALIFIER);
141
142 return true;
143 }
144
145 return false;
146}
147
148/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
149 * and capabilities to the host.
150 *
151 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
152 *
153 * \return Boolean \c true if the command completed successfully, \c false otherwise.
154 */
155static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
156{
157 uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
158 uint16_t BytesTransferred = MIN(AllocationLength, sizeof(InquiryData));
159
160 /* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
161 if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
162 MSInterfaceInfo->State.CommandBlock.SCSICommandData[2])
163 {
164 /* Optional but unsupported bits set - update the SENSE key and fail the request */
165 SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
166 SCSI_ASENSE_INVALID_FIELD_IN_CDB,
167 SCSI_ASENSEQ_NO_QUALIFIER);
168
169 return false;
170 }
171
172 Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NULL);
173
174 /* Pad out remaining bytes with 0x00 */
175 Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
176
177 /* Finalize the stream transfer to send the last packet */
178 Endpoint_ClearIN();
179
180 /* Succeed the command and update the bytes transferred counter */
181 MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
182
183 return true;
184}
185
186/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
187 * including the error code and additional error information so that the host can determine why a command failed to complete.
188 *
189 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
190 *
191 * \return Boolean \c true if the command completed successfully, \c false otherwise.
192 */
193static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
194{
195 uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
196 uint8_t BytesTransferred = MIN(AllocationLength, sizeof(SenseData));
197
198 Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NULL);
199 Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
200 Endpoint_ClearIN();
201
202 /* Succeed the command and update the bytes transferred counter */
203 MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
204
205 return true;
206}
207
208/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
209 * on the selected Logical Unit (drive), as a number of OS-sized blocks.
210 *
211 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
212 *
213 * \return Boolean \c true if the command completed successfully, \c false otherwise.
214 */
215static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
216{
217 uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1);
218 uint32_t MediaBlockSize = VIRTUAL_MEMORY_BLOCK_SIZE;
219
220 Endpoint_Write_Stream_BE(&LastBlockAddressInLUN, sizeof(LastBlockAddressInLUN), NULL);
221 Endpoint_Write_Stream_BE(&MediaBlockSize, sizeof(MediaBlockSize), NULL);
222 Endpoint_ClearIN();
223
224 /* Succeed the command and update the bytes transferred counter */
225 MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
226
227 return true;
228}
229
230/** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
231 * board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
232 * supported.
233 *
234 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
235 *
236 * \return Boolean \c true if the command completed successfully, \c false otherwise.
237 */
238static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
239{
240 /* Check to see if the SELF TEST bit is not set */
241 if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
242 {
243 /* Only self-test supported - update SENSE key and fail the command */
244 SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
245 SCSI_ASENSE_INVALID_FIELD_IN_CDB,
246 SCSI_ASENSEQ_NO_QUALIFIER);
247
248 return false;
249 }
250
251 /* Check to see if all attached Dataflash ICs are functional */
252 if (!(DataflashManager_CheckDataflashOperation()))
253 {
254 /* Update SENSE key with a hardware error condition and return command fail */
255 SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
256 SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
257 SCSI_ASENSEQ_NO_QUALIFIER);
258
259 return false;
260 }
261
262 /* Succeed the command and update the bytes transferred counter */
263 MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
264
265 return true;
266}
267
268/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
269 * and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
270 * reading and writing of the data.
271 *
272 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
273 * \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
274 *
275 * \return Boolean \c true if the command completed successfully, \c false otherwise.
276 */
277static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
278 const bool IsDataRead)
279{
280 uint32_t BlockAddress;
281 uint16_t TotalBlocks;
282
283 /* Check if the disk is write protected or not */
284 if ((IsDataRead == DATA_WRITE) && DISK_READ_ONLY)
285 {
286 /* Block address is invalid, update SENSE key and return command fail */
287 SCSI_SET_SENSE(SCSI_SENSE_KEY_DATA_PROTECT,
288 SCSI_ASENSE_WRITE_PROTECTED,
289 SCSI_ASENSEQ_NO_QUALIFIER);
290
291 return false;
292 }
293
294 /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
295 BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
296
297 /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
298 TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
299
300 /* Check if the block address is outside the maximum allowable value for the LUN */
301 if (BlockAddress >= VIRTUAL_MEMORY_BLOCKS)
302 {
303 /* Block address is invalid, update SENSE key and return command fail */
304 SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
305 SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
306 SCSI_ASENSEQ_NO_QUALIFIER);
307
308 return false;
309 }
310
311 /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
312 if (IsDataRead == DATA_READ)
313 DataflashManager_ReadBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
314 else
315 DataflashManager_WriteBlocks(MSInterfaceInfo, BlockAddress, TotalBlocks);
316
317 /* Update the bytes transferred counter and succeed the command */
318 MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
319
320 return true;
321}
322
323/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
324 * the SCSI device, as well as the device's Write Protect status.
325 *
326 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
327 *
328 * \return Boolean \c true if the command completed successfully, \c false otherwise.
329 */
330static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
331{
332 /* Send an empty header response with the Write Protect flag status */
333 Endpoint_Write_8(0x00);
334 Endpoint_Write_8(0x00);
335 Endpoint_Write_8(DISK_READ_ONLY ? 0x80 : 0x00);
336 Endpoint_Write_8(0x00);
337 Endpoint_ClearIN();
338
339 /* Update the bytes transferred counter and succeed the command */
340 MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
341
342 return true;
343}
344
diff --git a/lib/lufa/Projects/TempDataLogger/Lib/SCSI.h b/lib/lufa/Projects/TempDataLogger/Lib/SCSI.h
new file mode 100644
index 000000000..494b31bf8
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/Lib/SCSI.h
@@ -0,0 +1,89 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 *
33 * Header file for SCSI.c.
34 */
35
36#ifndef _SCSI_H_
37#define _SCSI_H_
38
39 /* Includes: */
40 #include <avr/io.h>
41 #include <avr/pgmspace.h>
42
43 #include <LUFA/Drivers/USB/USB.h>
44
45 #include "../TempDataLogger.h"
46 #include "../Descriptors.h"
47 #include "DataflashManager.h"
48 #include "Config/AppConfig.h"
49
50 /* Macros: */
51 /** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
52 * is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
53 * the last command failure) in a quick and easy manner.
54 *
55 * \param[in] Key New SCSI sense key to set the sense code to
56 * \param[in] Acode New SCSI additional sense key to set the additional sense code to
57 * \param[in] Aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
58 */
59 #define SCSI_SET_SENSE(Key, Acode, Aqual) do { SenseData.SenseKey = (Key); \
60 SenseData.AdditionalSenseCode = (Acode); \
61 SenseData.AdditionalSenseQualifier = (Aqual); } while (0)
62
63 /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
64 #define DATA_READ true
65
66 /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
67 #define DATA_WRITE false
68
69 /** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
70 #define DEVICE_TYPE_BLOCK 0x00
71
72 /** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a CD-ROM device. */
73 #define DEVICE_TYPE_CDROM 0x05
74
75 /* Function Prototypes: */
76 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
77
78 #if defined(INCLUDE_FROM_SCSI_C)
79 static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
80 static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
81 static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
82 static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
83 static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
84 const bool IsDataRead);
85 static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
86 #endif
87
88#endif
89
diff --git a/lib/lufa/Projects/TempDataLogger/TempDataLogger.c b/lib/lufa/Projects/TempDataLogger/TempDataLogger.c
new file mode 100644
index 000000000..1dc267a6f
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempDataLogger.c
@@ -0,0 +1,331 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 *
33 * Main source file for the TemperatureDataLogger project. This file contains the main tasks of
34 * the project and is responsible for the initial application hardware configuration.
35 */
36
37#include "TempDataLogger.h"
38
39/** LUFA Mass Storage Class driver interface configuration and state information. This structure is
40 * passed to all Mass Storage Class driver functions, so that multiple instances of the same class
41 * within a device can be differentiated from one another.
42 */
43USB_ClassInfo_MS_Device_t Disk_MS_Interface =
44 {
45 .Config =
46 {
47 .InterfaceNumber = INTERFACE_ID_MassStorage,
48 .DataINEndpoint =
49 {
50 .Address = MASS_STORAGE_IN_EPADDR,
51 .Size = MASS_STORAGE_IO_EPSIZE,
52 .Banks = 1,
53 },
54 .DataOUTEndpoint =
55 {
56 .Address = MASS_STORAGE_OUT_EPADDR,
57 .Size = MASS_STORAGE_IO_EPSIZE,
58 .Banks = 1,
59 },
60 .TotalLUNs = 1,
61 },
62 };
63
64/** Buffer to hold the previously generated HID report, for comparison purposes inside the HID class driver. */
65static uint8_t PrevHIDReportBuffer[GENERIC_REPORT_SIZE];
66
67/** LUFA HID Class driver interface configuration and state information. This structure is
68 * passed to all HID Class driver functions, so that multiple instances of the same class
69 * within a device can be differentiated from one another.
70 */
71USB_ClassInfo_HID_Device_t Generic_HID_Interface =
72 {
73 .Config =
74 {
75 .InterfaceNumber = INTERFACE_ID_HID,
76 .ReportINEndpoint =
77 {
78 .Address = GENERIC_IN_EPADDR,
79 .Size = GENERIC_EPSIZE,
80 .Banks = 1,
81 },
82 .PrevReportINBuffer = PrevHIDReportBuffer,
83 .PrevReportINBufferSize = sizeof(PrevHIDReportBuffer),
84 },
85 };
86
87/** Non-volatile Logging Interval value in EEPROM, stored as a number of 500ms ticks */
88static uint8_t EEMEM LoggingInterval500MS_EEPROM = DEFAULT_LOG_INTERVAL;
89
90/** SRAM Logging Interval value fetched from EEPROM, stored as a number of 500ms ticks */
91static uint8_t LoggingInterval500MS_SRAM;
92
93/** Total number of 500ms logging ticks elapsed since the last log value was recorded */
94static uint16_t CurrentLoggingTicks;
95
96/** FAT Fs structure to hold the internal state of the FAT driver for the Dataflash contents. */
97static FATFS DiskFATState;
98
99/** FAT Fs structure to hold a FAT file handle for the log data write destination. */
100static FIL TempLogFile;
101
102
103/** ISR to handle the 500ms ticks for sampling and data logging */
104ISR(TIMER1_COMPA_vect, ISR_BLOCK)
105{
106 /* Signal a 500ms tick has elapsed to the RTC */
107 RTC_Tick500ms();
108
109 /* Check to see if the logging interval has expired */
110 if (++CurrentLoggingTicks < LoggingInterval500MS_SRAM)
111 return;
112
113 /* Reset log tick counter to prepare for next logging interval */
114 CurrentLoggingTicks = 0;
115
116 uint8_t LEDMask = LEDs_GetLEDs();
117 LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
118
119 /* Only log when not connected to a USB host */
120 if (USB_DeviceState == DEVICE_STATE_Unattached)
121 {
122 TimeDate_t CurrentTimeDate;
123 RTC_GetTimeDate(&CurrentTimeDate);
124
125 char LineBuffer[100];
126 uint16_t BytesWritten;
127
128 BytesWritten = sprintf(LineBuffer, "%02d/%02d/20%02d, %02d:%02d:%02d, %d Degrees\r\n",
129 CurrentTimeDate.Day, CurrentTimeDate.Month, CurrentTimeDate.Year,
130 CurrentTimeDate.Hour, CurrentTimeDate.Minute, CurrentTimeDate.Second,
131 Temperature_GetTemperature());
132
133 f_write(&TempLogFile, LineBuffer, BytesWritten, &BytesWritten);
134 f_sync(&TempLogFile);
135 }
136
137 LEDs_SetAllLEDs(LEDMask);
138}
139
140/** Main program entry point. This routine contains the overall program flow, including initial
141 * setup of all components and the main program loop.
142 */
143int main(void)
144{
145 SetupHardware();
146
147 /* Fetch logging interval from EEPROM */
148 LoggingInterval500MS_SRAM = eeprom_read_byte(&LoggingInterval500MS_EEPROM);
149
150 /* Check if the logging interval is invalid (0xFF) indicating that the EEPROM is blank */
151 if (LoggingInterval500MS_SRAM == 0xFF)
152 LoggingInterval500MS_SRAM = DEFAULT_LOG_INTERVAL;
153
154 /* Mount and open the log file on the Dataflash FAT partition */
155 OpenLogFile();
156
157 LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
158 GlobalInterruptEnable();
159
160 for (;;)
161 {
162 MS_Device_USBTask(&Disk_MS_Interface);
163 HID_Device_USBTask(&Generic_HID_Interface);
164 USB_USBTask();
165 }
166}
167
168/** Opens the log file on the Dataflash's FAT formatted partition according to the current date */
169void OpenLogFile(void)
170{
171 char LogFileName[12];
172
173 /* Get the current date for the filename as "DDMMYY.csv" */
174 TimeDate_t CurrentTimeDate;
175 RTC_GetTimeDate(&CurrentTimeDate);
176 sprintf(LogFileName, "%02d%02d%02d.csv", CurrentTimeDate.Day, CurrentTimeDate.Month, CurrentTimeDate.Year);
177
178 /* Mount the storage device, open the file */
179 f_mount(0, &DiskFATState);
180 f_open(&TempLogFile, LogFileName, FA_OPEN_ALWAYS | FA_WRITE);
181 f_lseek(&TempLogFile, TempLogFile.fsize);
182}
183
184/** Closes the open data log file on the Dataflash's FAT formatted partition */
185void CloseLogFile(void)
186{
187 /* Sync any data waiting to be written, unmount the storage device */
188 f_sync(&TempLogFile);
189 f_close(&TempLogFile);
190}
191
192/** Configures the board hardware and chip peripherals for the demo's functionality. */
193void SetupHardware(void)
194{
195#if (ARCH == ARCH_AVR8)
196 /* Disable watchdog if enabled by bootloader/fuses */
197 MCUSR &= ~(1 << WDRF);
198 wdt_disable();
199
200 /* Disable clock division */
201 clock_prescale_set(clock_div_1);
202#endif
203
204 /* Hardware Initialization */
205 LEDs_Init();
206 ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_128);
207 Temperature_Init();
208 Dataflash_Init();
209 USB_Init();
210 TWI_Init(TWI_BIT_PRESCALE_4, TWI_BITLENGTH_FROM_FREQ(4, 50000));
211 RTC_Init();
212
213 /* 500ms logging interval timer configuration */
214 OCR1A = (((F_CPU / 256) / 2) - 1);
215 TCCR1B = (1 << WGM12) | (1 << CS12);
216 TIMSK1 = (1 << OCIE1A);
217
218 /* Check if the Dataflash is working, abort if not */
219 if (!(DataflashManager_CheckDataflashOperation()))
220 {
221 LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
222 for(;;);
223 }
224
225 /* Clear Dataflash sector protections, if enabled */
226 DataflashManager_ResetDataflashProtections();
227}
228
229/** Event handler for the library USB Connection event. */
230void EVENT_USB_Device_Connect(void)
231{
232 LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
233
234 /* Close the log file so that the host has exclusive file system access */
235 CloseLogFile();
236}
237
238/** Event handler for the library USB Disconnection event. */
239void EVENT_USB_Device_Disconnect(void)
240{
241 LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
242
243 /* Mount and open the log file on the Dataflash FAT partition */
244 OpenLogFile();
245}
246
247/** Event handler for the library USB Configuration Changed event. */
248void EVENT_USB_Device_ConfigurationChanged(void)
249{
250 bool ConfigSuccess = true;
251
252 ConfigSuccess &= HID_Device_ConfigureEndpoints(&Generic_HID_Interface);
253 ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface);
254
255 LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
256}
257
258/** Event handler for the library USB Control Request reception event. */
259void EVENT_USB_Device_ControlRequest(void)
260{
261 MS_Device_ProcessControlRequest(&Disk_MS_Interface);
262 HID_Device_ProcessControlRequest(&Generic_HID_Interface);
263}
264
265/** Mass Storage class driver callback function the reception of SCSI commands from the host, which must be processed.
266 *
267 * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface configuration structure being referenced
268 */
269bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
270{
271 bool CommandSuccess;
272
273 LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
274 CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);
275 LEDs_SetAllLEDs(LEDMASK_USB_READY);
276
277 return CommandSuccess;
278}
279
280/** HID class driver callback function for the creation of HID reports to the host.
281 *
282 * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
283 * \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID
284 * \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature
285 * \param[out] ReportData Pointer to a buffer where the created report should be stored
286 * \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent)
287 *
288 * \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent
289 */
290bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
291 uint8_t* const ReportID,
292 const uint8_t ReportType,
293 void* ReportData,
294 uint16_t* const ReportSize)
295{
296 Device_Report_t* ReportParams = (Device_Report_t*)ReportData;
297
298 RTC_GetTimeDate(&ReportParams->TimeDate);
299
300 ReportParams->LogInterval500MS = LoggingInterval500MS_SRAM;
301
302 *ReportSize = sizeof(Device_Report_t);
303 return true;
304}
305
306/** HID class driver callback function for the processing of HID reports from the host.
307 *
308 * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
309 * \param[in] ReportID Report ID of the received report from the host
310 * \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature
311 * \param[in] ReportData Pointer to a buffer where the received report has been stored
312 * \param[in] ReportSize Size in bytes of the received HID report
313 */
314void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
315 const uint8_t ReportID,
316 const uint8_t ReportType,
317 const void* ReportData,
318 const uint16_t ReportSize)
319{
320 Device_Report_t* ReportParams = (Device_Report_t*)ReportData;
321
322 RTC_SetTimeDate(&ReportParams->TimeDate);
323
324 /* If the logging interval has changed from its current value, write it to EEPROM */
325 if (LoggingInterval500MS_SRAM != ReportParams->LogInterval500MS)
326 {
327 LoggingInterval500MS_SRAM = ReportParams->LogInterval500MS;
328 eeprom_update_byte(&LoggingInterval500MS_EEPROM, LoggingInterval500MS_SRAM);
329 }
330}
331
diff --git a/lib/lufa/Projects/TempDataLogger/TempDataLogger.h b/lib/lufa/Projects/TempDataLogger/TempDataLogger.h
new file mode 100644
index 000000000..90b9b4ea6
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempDataLogger.h
@@ -0,0 +1,112 @@
1/*
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7*/
8
9/*
10 Copyright 2017 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29*/
30
31/** \file
32 *
33 * Header file for TempDataLogger.c.
34 */
35
36#ifndef _TEMP_DATALOGGER_H_
37#define _TEMP_DATALOGGER_H_
38
39 /* Includes: */
40 #include <avr/io.h>
41 #include <avr/wdt.h>
42 #include <avr/power.h>
43 #include <avr/interrupt.h>
44 #include <stdio.h>
45
46 #include "Descriptors.h"
47
48 #include "Lib/SCSI.h"
49 #include "Lib/DataflashManager.h"
50 #include "Lib/FATFs/ff.h"
51 #include "Lib/RTC.h"
52 #include "Config/AppConfig.h"
53
54 #include <LUFA/Drivers/Board/LEDs.h>
55 #include <LUFA/Drivers/Board/Temperature.h>
56 #include <LUFA/Drivers/Peripheral/ADC.h>
57 #include <LUFA/Drivers/USB/USB.h>
58 #include <LUFA/Platform/Platform.h>
59
60 /* Macros: */
61 /** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
62 #define LEDMASK_USB_NOTREADY LEDS_LED1
63
64 /** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
65 #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
66
67 /** LED mask for the library LED driver, to indicate that the USB interface is ready. */
68 #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
69
70 /** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
71 #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
72
73 /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
74 #define LEDMASK_USB_BUSY LEDS_LED2
75
76 /** Default log interval when the EEPROM is blank, in 500ms ticks. */
77 #define DEFAULT_LOG_INTERVAL 10
78
79 /** Indicates if the disk is write protected or not. */
80 #define DISK_READ_ONLY false
81
82 /* Type Defines: */
83 typedef struct
84 {
85 TimeDate_t TimeDate;
86 uint8_t LogInterval500MS;
87 } Device_Report_t;
88
89 /* Function Prototypes: */
90 void SetupHardware(void);
91 void OpenLogFile(void);
92 void CloseLogFile(void);
93
94 void EVENT_USB_Device_Connect(void);
95 void EVENT_USB_Device_Disconnect(void);
96 void EVENT_USB_Device_ConfigurationChanged(void);
97 void EVENT_USB_Device_ControlRequest(void);
98
99 bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
100 bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
101 uint8_t* const ReportID,
102 const uint8_t ReportType,
103 void* ReportData,
104 uint16_t* const ReportSize);
105 void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
106 const uint8_t ReportID,
107 const uint8_t ReportType,
108 const void* ReportData,
109 const uint16_t ReportSize);
110
111#endif
112
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.LESSER.txt b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.LESSER.txt
new file mode 100644
index 000000000..bdf8db0ee
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.LESSER.txt
@@ -0,0 +1,166 @@
1 GNU LESSER GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8
9 This version of the GNU Lesser General Public License incorporates
10the terms and conditions of version 3 of the GNU General Public
11License, supplemented by the additional permissions listed below.
12
13 0. Additional Definitions.
14
15 As used herein, "this License" refers to version 3 of the GNU Lesser
16General Public License, and the "GNU GPL" refers to version 3 of the GNU
17General Public License.
18
19 "The Library" refers to a covered work governed by this License,
20other than an Application or a Combined Work as defined below.
21
22 An "Application" is any work that makes use of an interface provided
23by the Library, but which is not otherwise based on the Library.
24Defining a subclass of a class defined by the Library is deemed a mode
25of using an interface provided by the Library.
26
27 A "Combined Work" is a work produced by combining or linking an
28Application with the Library. The particular version of the Library
29with which the Combined Work was made is also called the "Linked
30Version".
31
32 The "Minimal Corresponding Source" for a Combined Work means the
33Corresponding Source for the Combined Work, excluding any source code
34for portions of the Combined Work that, considered in isolation, are
35based on the Application, and not on the Linked Version.
36
37 The "Corresponding Application Code" for a Combined Work means the
38object code and/or source code for the Application, including any data
39and utility programs needed for reproducing the Combined Work from the
40Application, but excluding the System Libraries of the Combined Work.
41
42 1. Exception to Section 3 of the GNU GPL.
43
44 You may convey a covered work under sections 3 and 4 of this License
45without being bound by section 3 of the GNU GPL.
46
47 2. Conveying Modified Versions.
48
49 If you modify a copy of the Library, and, in your modifications, a
50facility refers to a function or data to be supplied by an Application
51that uses the facility (other than as an argument passed when the
52facility is invoked), then you may convey a copy of the modified
53version:
54
55 a) under this License, provided that you make a good faith effort to
56 ensure that, in the event an Application does not supply the
57 function or data, the facility still operates, and performs
58 whatever part of its purpose remains meaningful, or
59
60 b) under the GNU GPL, with none of the additional permissions of
61 this License applicable to that copy.
62
63 3. Object Code Incorporating Material from Library Header Files.
64
65 The object code form of an Application may incorporate material from
66a header file that is part of the Library. You may convey such object
67code under terms of your choice, provided that, if the incorporated
68material is not limited to numerical parameters, data structure
69layouts and accessors, or small macros, inline functions and templates
70(ten or fewer lines in length), you do both of the following:
71
72 a) Give prominent notice with each copy of the object code that the
73 Library is used in it and that the Library and its use are
74 covered by this License.
75
76 b) Accompany the object code with a copy of the GNU GPL and this license
77 document.
78
79 4. Combined Works.
80
81 You may convey a Combined Work under terms of your choice that,
82taken together, effectively do not restrict modification of the
83portions of the Library contained in the Combined Work and reverse
84engineering for debugging such modifications, if you also do each of
85the following:
86
87 a) Give prominent notice with each copy of the Combined Work that
88 the Library is used in it and that the Library and its use are
89 covered by this License.
90
91 b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 document.
93
94 c) For a Combined Work that displays copyright notices during
95 execution, include the copyright notice for the Library among
96 these notices, as well as a reference directing the user to the
97 copies of the GNU GPL and this license document.
98
99 d) Do one of the following:
100
101 0) Convey the Minimal Corresponding Source under the terms of this
102 License, and the Corresponding Application Code in a form
103 suitable for, and under terms that permit, the user to
104 recombine or relink the Application with a modified version of
105 the Linked Version to produce a modified Combined Work, in the
106 manner specified by section 6 of the GNU GPL for conveying
107 Corresponding Source.
108
109 1) Use a suitable shared library mechanism for linking with the
110 Library. A suitable mechanism is one that (a) uses at run time
111 a copy of the Library already present on the user's computer
112 system, and (b) will operate properly with a modified version
113 of the Library that is interface-compatible with the Linked
114 Version.
115
116 e) Provide Installation Information, but only if you would otherwise
117 be required to provide such information under section 6 of the
118 GNU GPL, and only to the extent that such information is
119 necessary to install and execute a modified version of the
120 Combined Work produced by recombining or relinking the
121 Application with a modified version of the Linked Version. (If
122 you use option 4d0, the Installation Information must accompany
123 the Minimal Corresponding Source and Corresponding Application
124 Code. If you use option 4d1, you must provide the Installation
125 Information in the manner specified by section 6 of the GNU GPL
126 for conveying Corresponding Source.)
127
128 5. Combined Libraries.
129
130 You may place library facilities that are a work based on the
131Library side by side in a single library together with other library
132facilities that are not Applications and are not covered by this
133License, and convey such a combined library under terms of your
134choice, if you do both of the following:
135
136 a) Accompany the combined library with a copy of the same work based
137 on the Library, uncombined with any other library facilities,
138 conveyed under the terms of this License.
139
140 b) Give prominent notice with the combined library that part of it
141 is a work based on the Library, and explaining where to find the
142 accompanying uncombined form of the same work.
143
144 6. Revised Versions of the GNU Lesser General Public License.
145
146 The Free Software Foundation may publish revised and/or new versions
147of the GNU Lesser General Public License from time to time. Such new
148versions will be similar in spirit to the present version, but may
149differ in detail to address new problems or concerns.
150
151 Each version is given a distinguishing version number. If the
152Library as you received it specifies that a certain numbered version
153of the GNU Lesser General Public License "or any later version"
154applies to it, you have the option of following the terms and
155conditions either of that published version or of any later version
156published by the Free Software Foundation. If the Library as you
157received it does not specify a version number of the GNU Lesser
158General Public License, you may choose any version of the GNU Lesser
159General Public License ever published by the Free Software Foundation.
160
161 If the Library as you received it specifies that a proxy can decide
162whether future versions of the GNU Lesser General Public License shall
163apply, that proxy's public statement of acceptance of any version is
164permanent authorization for you to choose that version for the
165Library.
166
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.txt b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.txt
new file mode 100644
index 000000000..10926e87f
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/COPYING.txt
@@ -0,0 +1,675 @@
1 GNU GENERAL PUBLIC LICENSE
2 Version 3, 29 June 2007
3
4 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 Preamble
9
10 The GNU General Public License is a free, copyleft license for
11software and other kinds of works.
12
13 The licenses for most software and other practical works are designed
14to take away your freedom to share and change the works. By contrast,
15the GNU General Public License is intended to guarantee your freedom to
16share and change all versions of a program--to make sure it remains free
17software for all its users. We, the Free Software Foundation, use the
18GNU General Public License for most of our software; it applies also to
19any other work released this way by its authors. You can apply it to
20your programs, too.
21
22 When we speak of free software, we are referring to freedom, not
23price. Our General Public Licenses are designed to make sure that you
24have the freedom to distribute copies of free software (and charge for
25them if you wish), that you receive source code or can get it if you
26want it, that you can change the software or use pieces of it in new
27free programs, and that you know you can do these things.
28
29 To protect your rights, we need to prevent others from denying you
30these rights or asking you to surrender the rights. Therefore, you have
31certain responsibilities if you distribute copies of the software, or if
32you modify it: responsibilities to respect the freedom of others.
33
34 For example, if you distribute copies of such a program, whether
35gratis or for a fee, you must pass on to the recipients the same
36freedoms that you received. You must make sure that they, too, receive
37or can get the source code. And you must show them these terms so they
38know their rights.
39
40 Developers that use the GNU GPL protect your rights with two steps:
41(1) assert copyright on the software, and (2) offer you this License
42giving you legal permission to copy, distribute and/or modify it.
43
44 For the developers' and authors' protection, the GPL clearly explains
45that there is no warranty for this free software. For both users' and
46authors' sake, the GPL requires that modified versions be marked as
47changed, so that their problems will not be attributed erroneously to
48authors of previous versions.
49
50 Some devices are designed to deny users access to install or run
51modified versions of the software inside them, although the manufacturer
52can do so. This is fundamentally incompatible with the aim of
53protecting users' freedom to change the software. The systematic
54pattern of such abuse occurs in the area of products for individuals to
55use, which is precisely where it is most unacceptable. Therefore, we
56have designed this version of the GPL to prohibit the practice for those
57products. If such problems arise substantially in other domains, we
58stand ready to extend this provision to those domains in future versions
59of the GPL, as needed to protect the freedom of users.
60
61 Finally, every program is threatened constantly by software patents.
62States should not allow patents to restrict development and use of
63software on general-purpose computers, but in those that do, we wish to
64avoid the special danger that patents applied to a free program could
65make it effectively proprietary. To prevent this, the GPL assures that
66patents cannot be used to render the program non-free.
67
68 The precise terms and conditions for copying, distribution and
69modification follow.
70
71 TERMS AND CONDITIONS
72
73 0. Definitions.
74
75 "This License" refers to version 3 of the GNU General Public License.
76
77 "Copyright" also means copyright-like laws that apply to other kinds of
78works, such as semiconductor masks.
79
80 "The Program" refers to any copyrightable work licensed under this
81License. Each licensee is addressed as "you". "Licensees" and
82"recipients" may be individuals or organizations.
83
84 To "modify" a work means to copy from or adapt all or part of the work
85in a fashion requiring copyright permission, other than the making of an
86exact copy. The resulting work is called a "modified version" of the
87earlier work or a work "based on" the earlier work.
88
89 A "covered work" means either the unmodified Program or a work based
90on the Program.
91
92 To "propagate" a work means to do anything with it that, without
93permission, would make you directly or secondarily liable for
94infringement under applicable copyright law, except executing it on a
95computer or modifying a private copy. Propagation includes copying,
96distribution (with or without modification), making available to the
97public, and in some countries other activities as well.
98
99 To "convey" a work means any kind of propagation that enables other
100parties to make or receive copies. Mere interaction with a user through
101a computer network, with no transfer of a copy, is not conveying.
102
103 An interactive user interface displays "Appropriate Legal Notices"
104to the extent that it includes a convenient and prominently visible
105feature that (1) displays an appropriate copyright notice, and (2)
106tells the user that there is no warranty for the work (except to the
107extent that warranties are provided), that licensees may convey the
108work under this License, and how to view a copy of this License. If
109the interface presents a list of user commands or options, such as a
110menu, a prominent item in the list meets this criterion.
111
112 1. Source Code.
113
114 The "source code" for a work means the preferred form of the work
115for making modifications to it. "Object code" means any non-source
116form of a work.
117
118 A "Standard Interface" means an interface that either is an official
119standard defined by a recognized standards body, or, in the case of
120interfaces specified for a particular programming language, one that
121is widely used among developers working in that language.
122
123 The "System Libraries" of an executable work include anything, other
124than the work as a whole, that (a) is included in the normal form of
125packaging a Major Component, but which is not part of that Major
126Component, and (b) serves only to enable use of the work with that
127Major Component, or to implement a Standard Interface for which an
128implementation is available to the public in source code form. A
129"Major Component", in this context, means a major essential component
130(kernel, window system, and so on) of the specific operating system
131(if any) on which the executable work runs, or a compiler used to
132produce the work, or an object code interpreter used to run it.
133
134 The "Corresponding Source" for a work in object code form means all
135the source code needed to generate, install, and (for an executable
136work) run the object code and to modify the work, including scripts to
137control those activities. However, it does not include the work's
138System Libraries, or general-purpose tools or generally available free
139programs which are used unmodified in performing those activities but
140which are not part of the work. For example, Corresponding Source
141includes interface definition files associated with source files for
142the work, and the source code for shared libraries and dynamically
143linked subprograms that the work is specifically designed to require,
144such as by intimate data communication or control flow between those
145subprograms and other parts of the work.
146
147 The Corresponding Source need not include anything that users
148can regenerate automatically from other parts of the Corresponding
149Source.
150
151 The Corresponding Source for a work in source code form is that
152same work.
153
154 2. Basic Permissions.
155
156 All rights granted under this License are granted for the term of
157copyright on the Program, and are irrevocable provided the stated
158conditions are met. This License explicitly affirms your unlimited
159permission to run the unmodified Program. The output from running a
160covered work is covered by this License only if the output, given its
161content, constitutes a covered work. This License acknowledges your
162rights of fair use or other equivalent, as provided by copyright law.
163
164 You may make, run and propagate covered works that you do not
165convey, without conditions so long as your license otherwise remains
166in force. You may convey covered works to others for the sole purpose
167of having them make modifications exclusively for you, or provide you
168with facilities for running those works, provided that you comply with
169the terms of this License in conveying all material for which you do
170not control copyright. Those thus making or running the covered works
171for you must do so exclusively on your behalf, under your direction
172and control, on terms that prohibit them from making any copies of
173your copyrighted material outside their relationship with you.
174
175 Conveying under any other circumstances is permitted solely under
176the conditions stated below. Sublicensing is not allowed; section 10
177makes it unnecessary.
178
179 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
181 No covered work shall be deemed part of an effective technological
182measure under any applicable law fulfilling obligations under article
18311 of the WIPO copyright treaty adopted on 20 December 1996, or
184similar laws prohibiting or restricting circumvention of such
185measures.
186
187 When you convey a covered work, you waive any legal power to forbid
188circumvention of technological measures to the extent such circumvention
189is effected by exercising rights under this License with respect to
190the covered work, and you disclaim any intention to limit operation or
191modification of the work as a means of enforcing, against the work's
192users, your or third parties' legal rights to forbid circumvention of
193technological measures.
194
195 4. Conveying Verbatim Copies.
196
197 You may convey verbatim copies of the Program's source code as you
198receive it, in any medium, provided that you conspicuously and
199appropriately publish on each copy an appropriate copyright notice;
200keep intact all notices stating that this License and any
201non-permissive terms added in accord with section 7 apply to the code;
202keep intact all notices of the absence of any warranty; and give all
203recipients a copy of this License along with the Program.
204
205 You may charge any price or no price for each copy that you convey,
206and you may offer support or warranty protection for a fee.
207
208 5. Conveying Modified Source Versions.
209
210 You may convey a work based on the Program, or the modifications to
211produce it from the Program, in the form of source code under the
212terms of section 4, provided that you also meet all of these conditions:
213
214 a) The work must carry prominent notices stating that you modified
215 it, and giving a relevant date.
216
217 b) The work must carry prominent notices stating that it is
218 released under this License and any conditions added under section
219 7. This requirement modifies the requirement in section 4 to
220 "keep intact all notices".
221
222 c) You must license the entire work, as a whole, under this
223 License to anyone who comes into possession of a copy. This
224 License will therefore apply, along with any applicable section 7
225 additional terms, to the whole of the work, and all its parts,
226 regardless of how they are packaged. This License gives no
227 permission to license the work in any other way, but it does not
228 invalidate such permission if you have separately received it.
229
230 d) If the work has interactive user interfaces, each must display
231 Appropriate Legal Notices; however, if the Program has interactive
232 interfaces that do not display Appropriate Legal Notices, your
233 work need not make them do so.
234
235 A compilation of a covered work with other separate and independent
236works, which are not by their nature extensions of the covered work,
237and which are not combined with it such as to form a larger program,
238in or on a volume of a storage or distribution medium, is called an
239"aggregate" if the compilation and its resulting copyright are not
240used to limit the access or legal rights of the compilation's users
241beyond what the individual works permit. Inclusion of a covered work
242in an aggregate does not cause this License to apply to the other
243parts of the aggregate.
244
245 6. Conveying Non-Source Forms.
246
247 You may convey a covered work in object code form under the terms
248of sections 4 and 5, provided that you also convey the
249machine-readable Corresponding Source under the terms of this License,
250in one of these ways:
251
252 a) Convey the object code in, or embodied in, a physical product
253 (including a physical distribution medium), accompanied by the
254 Corresponding Source fixed on a durable physical medium
255 customarily used for software interchange.
256
257 b) Convey the object code in, or embodied in, a physical product
258 (including a physical distribution medium), accompanied by a
259 written offer, valid for at least three years and valid for as
260 long as you offer spare parts or customer support for that product
261 model, to give anyone who possesses the object code either (1) a
262 copy of the Corresponding Source for all the software in the
263 product that is covered by this License, on a durable physical
264 medium customarily used for software interchange, for a price no
265 more than your reasonable cost of physically performing this
266 conveying of source, or (2) access to copy the
267 Corresponding Source from a network server at no charge.
268
269 c) Convey individual copies of the object code with a copy of the
270 written offer to provide the Corresponding Source. This
271 alternative is allowed only occasionally and noncommercially, and
272 only if you received the object code with such an offer, in accord
273 with subsection 6b.
274
275 d) Convey the object code by offering access from a designated
276 place (gratis or for a charge), and offer equivalent access to the
277 Corresponding Source in the same way through the same place at no
278 further charge. You need not require recipients to copy the
279 Corresponding Source along with the object code. If the place to
280 copy the object code is a network server, the Corresponding Source
281 may be on a different server (operated by you or a third party)
282 that supports equivalent copying facilities, provided you maintain
283 clear directions next to the object code saying where to find the
284 Corresponding Source. Regardless of what server hosts the
285 Corresponding Source, you remain obligated to ensure that it is
286 available for as long as needed to satisfy these requirements.
287
288 e) Convey the object code using peer-to-peer transmission, provided
289 you inform other peers where the object code and Corresponding
290 Source of the work are being offered to the general public at no
291 charge under subsection 6d.
292
293 A separable portion of the object code, whose source code is excluded
294from the Corresponding Source as a System Library, need not be
295included in conveying the object code work.
296
297 A "User Product" is either (1) a "consumer product", which means any
298tangible personal property which is normally used for personal, family,
299or household purposes, or (2) anything designed or sold for incorporation
300into a dwelling. In determining whether a product is a consumer product,
301doubtful cases shall be resolved in favor of coverage. For a particular
302product received by a particular user, "normally used" refers to a
303typical or common use of that class of product, regardless of the status
304of the particular user or of the way in which the particular user
305actually uses, or expects or is expected to use, the product. A product
306is a consumer product regardless of whether the product has substantial
307commercial, industrial or non-consumer uses, unless such uses represent
308the only significant mode of use of the product.
309
310 "Installation Information" for a User Product means any methods,
311procedures, authorization keys, or other information required to install
312and execute modified versions of a covered work in that User Product from
313a modified version of its Corresponding Source. The information must
314suffice to ensure that the continued functioning of the modified object
315code is in no case prevented or interfered with solely because
316modification has been made.
317
318 If you convey an object code work under this section in, or with, or
319specifically for use in, a User Product, and the conveying occurs as
320part of a transaction in which the right of possession and use of the
321User Product is transferred to the recipient in perpetuity or for a
322fixed term (regardless of how the transaction is characterized), the
323Corresponding Source conveyed under this section must be accompanied
324by the Installation Information. But this requirement does not apply
325if neither you nor any third party retains the ability to install
326modified object code on the User Product (for example, the work has
327been installed in ROM).
328
329 The requirement to provide Installation Information does not include a
330requirement to continue to provide support service, warranty, or updates
331for a work that has been modified or installed by the recipient, or for
332the User Product in which it has been modified or installed. Access to a
333network may be denied when the modification itself materially and
334adversely affects the operation of the network or violates the rules and
335protocols for communication across the network.
336
337 Corresponding Source conveyed, and Installation Information provided,
338in accord with this section must be in a format that is publicly
339documented (and with an implementation available to the public in
340source code form), and must require no special password or key for
341unpacking, reading or copying.
342
343 7. Additional Terms.
344
345 "Additional permissions" are terms that supplement the terms of this
346License by making exceptions from one or more of its conditions.
347Additional permissions that are applicable to the entire Program shall
348be treated as though they were included in this License, to the extent
349that they are valid under applicable law. If additional permissions
350apply only to part of the Program, that part may be used separately
351under those permissions, but the entire Program remains governed by
352this License without regard to the additional permissions.
353
354 When you convey a copy of a covered work, you may at your option
355remove any additional permissions from that copy, or from any part of
356it. (Additional permissions may be written to require their own
357removal in certain cases when you modify the work.) You may place
358additional permissions on material, added by you to a covered work,
359for which you have or can give appropriate copyright permission.
360
361 Notwithstanding any other provision of this License, for material you
362add to a covered work, you may (if authorized by the copyright holders of
363that material) supplement the terms of this License with terms:
364
365 a) Disclaiming warranty or limiting liability differently from the
366 terms of sections 15 and 16 of this License; or
367
368 b) Requiring preservation of specified reasonable legal notices or
369 author attributions in that material or in the Appropriate Legal
370 Notices displayed by works containing it; or
371
372 c) Prohibiting misrepresentation of the origin of that material, or
373 requiring that modified versions of such material be marked in
374 reasonable ways as different from the original version; or
375
376 d) Limiting the use for publicity purposes of names of licensors or
377 authors of the material; or
378
379 e) Declining to grant rights under trademark law for use of some
380 trade names, trademarks, or service marks; or
381
382 f) Requiring indemnification of licensors and authors of that
383 material by anyone who conveys the material (or modified versions of
384 it) with contractual assumptions of liability to the recipient, for
385 any liability that these contractual assumptions directly impose on
386 those licensors and authors.
387
388 All other non-permissive additional terms are considered "further
389restrictions" within the meaning of section 10. If the Program as you
390received it, or any part of it, contains a notice stating that it is
391governed by this License along with a term that is a further
392restriction, you may remove that term. If a license document contains
393a further restriction but permits relicensing or conveying under this
394License, you may add to a covered work material governed by the terms
395of that license document, provided that the further restriction does
396not survive such relicensing or conveying.
397
398 If you add terms to a covered work in accord with this section, you
399must place, in the relevant source files, a statement of the
400additional terms that apply to those files, or a notice indicating
401where to find the applicable terms.
402
403 Additional terms, permissive or non-permissive, may be stated in the
404form of a separately written license, or stated as exceptions;
405the above requirements apply either way.
406
407 8. Termination.
408
409 You may not propagate or modify a covered work except as expressly
410provided under this License. Any attempt otherwise to propagate or
411modify it is void, and will automatically terminate your rights under
412this License (including any patent licenses granted under the third
413paragraph of section 11).
414
415 However, if you cease all violation of this License, then your
416license from a particular copyright holder is reinstated (a)
417provisionally, unless and until the copyright holder explicitly and
418finally terminates your license, and (b) permanently, if the copyright
419holder fails to notify you of the violation by some reasonable means
420prior to 60 days after the cessation.
421
422 Moreover, your license from a particular copyright holder is
423reinstated permanently if the copyright holder notifies you of the
424violation by some reasonable means, this is the first time you have
425received notice of violation of this License (for any work) from that
426copyright holder, and you cure the violation prior to 30 days after
427your receipt of the notice.
428
429 Termination of your rights under this section does not terminate the
430licenses of parties who have received copies or rights from you under
431this License. If your rights have been terminated and not permanently
432reinstated, you do not qualify to receive new licenses for the same
433material under section 10.
434
435 9. Acceptance Not Required for Having Copies.
436
437 You are not required to accept this License in order to receive or
438run a copy of the Program. Ancillary propagation of a covered work
439occurring solely as a consequence of using peer-to-peer transmission
440to receive a copy likewise does not require acceptance. However,
441nothing other than this License grants you permission to propagate or
442modify any covered work. These actions infringe copyright if you do
443not accept this License. Therefore, by modifying or propagating a
444covered work, you indicate your acceptance of this License to do so.
445
446 10. Automatic Licensing of Downstream Recipients.
447
448 Each time you convey a covered work, the recipient automatically
449receives a license from the original licensors, to run, modify and
450propagate that work, subject to this License. You are not responsible
451for enforcing compliance by third parties with this License.
452
453 An "entity transaction" is a transaction transferring control of an
454organization, or substantially all assets of one, or subdividing an
455organization, or merging organizations. If propagation of a covered
456work results from an entity transaction, each party to that
457transaction who receives a copy of the work also receives whatever
458licenses to the work the party's predecessor in interest had or could
459give under the previous paragraph, plus a right to possession of the
460Corresponding Source of the work from the predecessor in interest, if
461the predecessor has it or can get it with reasonable efforts.
462
463 You may not impose any further restrictions on the exercise of the
464rights granted or affirmed under this License. For example, you may
465not impose a license fee, royalty, or other charge for exercise of
466rights granted under this License, and you may not initiate litigation
467(including a cross-claim or counterclaim in a lawsuit) alleging that
468any patent claim is infringed by making, using, selling, offering for
469sale, or importing the Program or any portion of it.
470
471 11. Patents.
472
473 A "contributor" is a copyright holder who authorizes use under this
474License of the Program or a work on which the Program is based. The
475work thus licensed is called the contributor's "contributor version".
476
477 A contributor's "essential patent claims" are all patent claims
478owned or controlled by the contributor, whether already acquired or
479hereafter acquired, that would be infringed by some manner, permitted
480by this License, of making, using, or selling its contributor version,
481but do not include claims that would be infringed only as a
482consequence of further modification of the contributor version. For
483purposes of this definition, "control" includes the right to grant
484patent sublicenses in a manner consistent with the requirements of
485this License.
486
487 Each contributor grants you a non-exclusive, worldwide, royalty-free
488patent license under the contributor's essential patent claims, to
489make, use, sell, offer for sale, import and otherwise run, modify and
490propagate the contents of its contributor version.
491
492 In the following three paragraphs, a "patent license" is any express
493agreement or commitment, however denominated, not to enforce a patent
494(such as an express permission to practice a patent or covenant not to
495sue for patent infringement). To "grant" such a patent license to a
496party means to make such an agreement or commitment not to enforce a
497patent against the party.
498
499 If you convey a covered work, knowingly relying on a patent license,
500and the Corresponding Source of the work is not available for anyone
501to copy, free of charge and under the terms of this License, through a
502publicly available network server or other readily accessible means,
503then you must either (1) cause the Corresponding Source to be so
504available, or (2) arrange to deprive yourself of the benefit of the
505patent license for this particular work, or (3) arrange, in a manner
506consistent with the requirements of this License, to extend the patent
507license to downstream recipients. "Knowingly relying" means you have
508actual knowledge that, but for the patent license, your conveying the
509covered work in a country, or your recipient's use of the covered work
510in a country, would infringe one or more identifiable patents in that
511country that you have reason to believe are valid.
512
513 If, pursuant to or in connection with a single transaction or
514arrangement, you convey, or propagate by procuring conveyance of, a
515covered work, and grant a patent license to some of the parties
516receiving the covered work authorizing them to use, propagate, modify
517or convey a specific copy of the covered work, then the patent license
518you grant is automatically extended to all recipients of the covered
519work and works based on it.
520
521 A patent license is "discriminatory" if it does not include within
522the scope of its coverage, prohibits the exercise of, or is
523conditioned on the non-exercise of one or more of the rights that are
524specifically granted under this License. You may not convey a covered
525work if you are a party to an arrangement with a third party that is
526in the business of distributing software, under which you make payment
527to the third party based on the extent of your activity of conveying
528the work, and under which the third party grants, to any of the
529parties who would receive the covered work from you, a discriminatory
530patent license (a) in connection with copies of the covered work
531conveyed by you (or copies made from those copies), or (b) primarily
532for and in connection with specific products or compilations that
533contain the covered work, unless you entered into that arrangement,
534or that patent license was granted, prior to 28 March 2007.
535
536 Nothing in this License shall be construed as excluding or limiting
537any implied license or other defenses to infringement that may
538otherwise be available to you under applicable patent law.
539
540 12. No Surrender of Others' Freedom.
541
542 If conditions are imposed on you (whether by court order, agreement or
543otherwise) that contradict the conditions of this License, they do not
544excuse you from the conditions of this License. If you cannot convey a
545covered work so as to satisfy simultaneously your obligations under this
546License and any other pertinent obligations, then as a consequence you may
547not convey it at all. For example, if you agree to terms that obligate you
548to collect a royalty for further conveying from those to whom you convey
549the Program, the only way you could satisfy both those terms and this
550License would be to refrain entirely from conveying the Program.
551
552 13. Use with the GNU Affero General Public License.
553
554 Notwithstanding any other provision of this License, you have
555permission to link or combine any covered work with a work licensed
556under version 3 of the GNU Affero General Public License into a single
557combined work, and to convey the resulting work. The terms of this
558License will continue to apply to the part which is the covered work,
559but the special requirements of the GNU Affero General Public License,
560section 13, concerning interaction through a network will apply to the
561combination as such.
562
563 14. Revised Versions of this License.
564
565 The Free Software Foundation may publish revised and/or new versions of
566the GNU General Public License from time to time. Such new versions will
567be similar in spirit to the present version, but may differ in detail to
568address new problems or concerns.
569
570 Each version is given a distinguishing version number. If the
571Program specifies that a certain numbered version of the GNU General
572Public License "or any later version" applies to it, you have the
573option of following the terms and conditions either of that numbered
574version or of any later version published by the Free Software
575Foundation. If the Program does not specify a version number of the
576GNU General Public License, you may choose any version ever published
577by the Free Software Foundation.
578
579 If the Program specifies that a proxy can decide which future
580versions of the GNU General Public License can be used, that proxy's
581public statement of acceptance of a version permanently authorizes you
582to choose that version for the Program.
583
584 Later license versions may give you additional or different
585permissions. However, no additional obligations are imposed on any
586author or copyright holder as a result of your choosing to follow a
587later version.
588
589 15. Disclaimer of Warranty.
590
591 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
600 16. Limitation of Liability.
601
602 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610SUCH DAMAGES.
611
612 17. Interpretation of Sections 15 and 16.
613
614 If the disclaimer of warranty and limitation of liability provided
615above cannot be given local legal effect according to their terms,
616reviewing courts shall apply local law that most closely approximates
617an absolute waiver of all civil liability in connection with the
618Program, unless a warranty or assumption of liability accompanies a
619copy of the Program in return for a fee.
620
621 END OF TERMS AND CONDITIONS
622
623 How to Apply These Terms to Your New Programs
624
625 If you develop a new program, and you want it to be of the greatest
626possible use to the public, the best way to achieve this is to make it
627free software which everyone can redistribute and change under these terms.
628
629 To do so, attach the following notices to the program. It is safest
630to attach them to the start of each source file to most effectively
631state the exclusion of warranty; and each file should have at least
632the "copyright" line and a pointer to where the full notice is found.
633
634 <one line to give the program's name and a brief idea of what it does.>
635 Copyright (C) <year> <name of author>
636
637 This program is free software: you can redistribute it and/or modify
638 it under the terms of the GNU General Public License as published by
639 the Free Software Foundation, either version 3 of the License, or
640 (at your option) any later version.
641
642 This program is distributed in the hope that it will be useful,
643 but WITHOUT ANY WARRANTY; without even the implied warranty of
644 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 GNU General Public License for more details.
646
647 You should have received a copy of the GNU General Public License
648 along with this program. If not, see <http://www.gnu.org/licenses/>.
649
650Also add information on how to contact you by electronic and paper mail.
651
652 If the program does terminal interaction, make it output a short
653notice like this when it starts in an interactive mode:
654
655 <program> Copyright (C) <year> <name of author>
656 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 This is free software, and you are welcome to redistribute it
658 under certain conditions; type `show c' for details.
659
660The hypothetical commands `show w' and `show c' should show the appropriate
661parts of the General Public License. Of course, your program's commands
662might be different; for a GUI interface, you would use an "about box".
663
664 You should also get your employer (if you work as a programmer) or school,
665if any, to sign a "copyright disclaimer" for the program, if necessary.
666For more information on this, and how to apply and follow the GNU GPL, see
667<http://www.gnu.org/licenses/>.
668
669 The GNU General Public License does not permit incorporating your program
670into proprietary programs. If your program is a subroutine library, you
671may consider it more useful to permit linking proprietary applications with
672the library. If this is what you want to do, use the GNU Lesser General
673Public License instead of this License. But first, please read
674<http://www.gnu.org/philosophy/why-not-lgpl.html>.
675
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.Designer.cs b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.Designer.cs
new file mode 100644
index 000000000..58fac5144
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.Designer.cs
@@ -0,0 +1,181 @@
1namespace Project1HostApp
2{
3 partial class frmDataloggerSettings
4 {
5 /// <summary>
6 /// Required designer variable.
7 /// </summary>
8 private System.ComponentModel.IContainer components = null;
9
10 /// <summary>
11 /// Clean up any resources being used.
12 /// </summary>
13 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
14 protected override void Dispose(bool disposing)
15 {
16 if (disposing && (components != null))
17 {
18 components.Dispose();
19 }
20 base.Dispose(disposing);
21 }
22
23 #region Windows Form Designer generated code
24
25 /// <summary>
26 /// Required method for Designer support - do not modify
27 /// the contents of this method with the code editor.
28 /// </summary>
29 private void InitializeComponent()
30 {
31 this.btnSetValues = new System.Windows.Forms.Button();
32 this.dtpTime = new System.Windows.Forms.DateTimePicker();
33 this.lblTime = new System.Windows.Forms.Label();
34 this.lblLoggingInterval = new System.Windows.Forms.Label();
35 this.nudLogInterval = new System.Windows.Forms.NumericUpDown();
36 this.lblSeconds = new System.Windows.Forms.Label();
37 this.btnGetValues = new System.Windows.Forms.Button();
38 this.lblDate = new System.Windows.Forms.Label();
39 this.dtpDate = new System.Windows.Forms.DateTimePicker();
40 ((System.ComponentModel.ISupportInitialize)(this.nudLogInterval)).BeginInit();
41 this.SuspendLayout();
42 //
43 // btnSetValues
44 //
45 this.btnSetValues.Location = new System.Drawing.Point(168, 136);
46 this.btnSetValues.Name = "btnSetValues";
47 this.btnSetValues.Size = new System.Drawing.Size(90, 35);
48 this.btnSetValues.TabIndex = 0;
49 this.btnSetValues.Text = "Set Values";
50 this.btnSetValues.UseVisualStyleBackColor = true;
51 this.btnSetValues.Click += new System.EventHandler(this.btnSetValues_Click);
52 //
53 // dtpTime
54 //
55 this.dtpTime.CustomFormat = "";
56 this.dtpTime.Format = System.Windows.Forms.DateTimePickerFormat.Time;
57 this.dtpTime.Location = new System.Drawing.Point(148, 61);
58 this.dtpTime.Name = "dtpTime";
59 this.dtpTime.ShowUpDown = true;
60 this.dtpTime.Size = new System.Drawing.Size(110, 20);
61 this.dtpTime.TabIndex = 1;
62 //
63 // lblTime
64 //
65 this.lblTime.AutoSize = true;
66 this.lblTime.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
67 this.lblTime.Location = new System.Drawing.Point(51, 67);
68 this.lblTime.Name = "lblTime";
69 this.lblTime.Size = new System.Drawing.Size(82, 13);
70 this.lblTime.TabIndex = 2;
71 this.lblTime.Text = "Device Time:";
72 //
73 // lblLoggingInterval
74 //
75 this.lblLoggingInterval.AutoSize = true;
76 this.lblLoggingInterval.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
77 this.lblLoggingInterval.Location = new System.Drawing.Point(30, 101);
78 this.lblLoggingInterval.Name = "lblLoggingInterval";
79 this.lblLoggingInterval.Size = new System.Drawing.Size(103, 13);
80 this.lblLoggingInterval.TabIndex = 3;
81 this.lblLoggingInterval.Text = "Logging Interval:";
82 //
83 // nudLogInterval
84 //
85 this.nudLogInterval.Location = new System.Drawing.Point(148, 94);
86 this.nudLogInterval.Maximum = new decimal(new int[] {
87 60,
88 0,
89 0,
90 0});
91 this.nudLogInterval.Minimum = new decimal(new int[] {
92 1,
93 0,
94 0,
95 0});
96 this.nudLogInterval.Name = "nudLogInterval";
97 this.nudLogInterval.Size = new System.Drawing.Size(51, 20);
98 this.nudLogInterval.TabIndex = 5;
99 this.nudLogInterval.Value = new decimal(new int[] {
100 5,
101 0,
102 0,
103 0});
104 //
105 // lblSeconds
106 //
107 this.lblSeconds.AutoSize = true;
108 this.lblSeconds.Location = new System.Drawing.Point(209, 101);
109 this.lblSeconds.Name = "lblSeconds";
110 this.lblSeconds.Size = new System.Drawing.Size(49, 13);
111 this.lblSeconds.TabIndex = 6;
112 this.lblSeconds.Text = "Seconds";
113 //
114 // btnGetValues
115 //
116 this.btnGetValues.Location = new System.Drawing.Point(30, 136);
117 this.btnGetValues.Name = "btnGetValues";
118 this.btnGetValues.Size = new System.Drawing.Size(90, 35);
119 this.btnGetValues.TabIndex = 7;
120 this.btnGetValues.Text = "Get Values";
121 this.btnGetValues.UseVisualStyleBackColor = true;
122 this.btnGetValues.Click += new System.EventHandler(this.btnGetValues_Click);
123 //
124 // lblDate
125 //
126 this.lblDate.AutoSize = true;
127 this.lblDate.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
128 this.lblDate.Location = new System.Drawing.Point(51, 33);
129 this.lblDate.Name = "lblDate";
130 this.lblDate.Size = new System.Drawing.Size(82, 13);
131 this.lblDate.TabIndex = 8;
132 this.lblDate.Text = "Device Date:";
133 //
134 // dtpDate
135 //
136 this.dtpDate.CustomFormat = "dd/MM/yyyy";
137 this.dtpDate.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
138 this.dtpDate.Location = new System.Drawing.Point(148, 27);
139 this.dtpDate.Name = "dtpDate";
140 this.dtpDate.Size = new System.Drawing.Size(110, 20);
141 this.dtpDate.TabIndex = 9;
142 //
143 // frmDataloggerSettings
144 //
145 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
146 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
147 this.ClientSize = new System.Drawing.Size(300, 197);
148 this.Controls.Add(this.dtpDate);
149 this.Controls.Add(this.lblDate);
150 this.Controls.Add(this.btnGetValues);
151 this.Controls.Add(this.lblSeconds);
152 this.Controls.Add(this.nudLogInterval);
153 this.Controls.Add(this.lblLoggingInterval);
154 this.Controls.Add(this.lblTime);
155 this.Controls.Add(this.dtpTime);
156 this.Controls.Add(this.btnSetValues);
157 this.MaximizeBox = false;
158 this.MinimizeBox = false;
159 this.Name = "frmDataloggerSettings";
160 this.Text = "Datalogger";
161 this.Load += new System.EventHandler(this.frmDataloggerSettings_Load);
162 ((System.ComponentModel.ISupportInitialize)(this.nudLogInterval)).EndInit();
163 this.ResumeLayout(false);
164 this.PerformLayout();
165
166 }
167
168 #endregion
169
170 private System.Windows.Forms.Button btnSetValues;
171 private System.Windows.Forms.DateTimePicker dtpTime;
172 private System.Windows.Forms.Label lblTime;
173 private System.Windows.Forms.Label lblLoggingInterval;
174 private System.Windows.Forms.NumericUpDown nudLogInterval;
175 private System.Windows.Forms.Label lblSeconds;
176 private System.Windows.Forms.Button btnGetValues;
177 private System.Windows.Forms.Label lblDate;
178 private System.Windows.Forms.DateTimePicker dtpDate;
179 }
180}
181
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.cs b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.cs
new file mode 100644
index 000000000..c3d1e1564
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.cs
@@ -0,0 +1,179 @@
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Data;
5using System.Drawing;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using Hid;
10
11namespace Project1HostApp
12{
13 public partial class frmDataloggerSettings : Form
14 {
15 private const int DEVICE_VID = 0x03EB;
16 private const int DEVICE_PID = 0x2063;
17
18 private struct Device_Report_t
19 {
20 public Byte Day;
21 public Byte Month;
22 public Byte Year;
23
24 public Byte Hour;
25 public Byte Minute;
26 public Byte Second;
27
28 public Byte LogInterval500MS;
29
30 public Byte[] ToReport()
31 {
32 Byte[] Report = new Byte[7];
33
34 Report[0] = this.Hour;
35 Report[1] = this.Minute;
36 Report[2] = this.Second;
37 Report[3] = this.Day;
38 Report[4] = this.Month;
39 Report[5] = this.Year;
40 Report[6] = this.LogInterval500MS;
41
42 return Report;
43 }
44
45 public void FromReport(Byte[] Report)
46 {
47 this.Hour = Report[0];
48 this.Minute = Report[1];
49 this.Second = Report[2];
50 this.Day = Report[3];
51 this.Month = Report[4];
52 this.Year = Report[5];
53 this.LogInterval500MS = Report[6];
54 }
55 };
56
57 private IDevice GetDeviceConnection()
58 {
59 IDevice[] ConnectedDevices = DeviceFactory.Enumerate(DEVICE_VID, DEVICE_PID);
60 IDevice ConnectionHandle = null;
61
62 if (ConnectedDevices.Count() > 0)
63 ConnectionHandle = ConnectedDevices[0];
64 else
65 return null;
66
67 // Fix report handle under Windows
68 if (ConnectionHandle is Hid.Win32.Win32DeviceSet)
69 {
70 ((Hid.Win32.Win32DeviceSet)ConnectionHandle).AddDevice(0x00,
71 ((Hid.Win32.Win32DeviceSet)ConnectionHandle).UnallocatedDevices[0]);
72 }
73
74 return ConnectionHandle;
75 }
76
77 public frmDataloggerSettings()
78 {
79 InitializeComponent();
80 }
81
82 private void btnSetValues_Click(object sender, EventArgs e)
83 {
84 IDevice ConnectionHandle = GetDeviceConnection();
85
86 if (ConnectionHandle == null)
87 {
88 MessageBox.Show("Error: Cannot connect to Datalogger device.");
89 return;
90 }
91
92 Device_Report_t DeviceReport = new Device_Report_t();
93 DeviceReport.Day = (byte)dtpDate.Value.Day;
94 DeviceReport.Month = (byte)dtpDate.Value.Month;
95 DeviceReport.Year = (byte)((dtpDate.Value.Year < 2000) ? 0 : (dtpDate.Value.Year - 2000));
96 DeviceReport.Hour = (byte)dtpTime.Value.Hour;
97 DeviceReport.Minute = (byte)dtpTime.Value.Minute;
98 DeviceReport.Second = (byte)dtpTime.Value.Second;
99 DeviceReport.LogInterval500MS = (byte)(nudLogInterval.Value * 2);
100
101 try
102 {
103 ConnectionHandle.Write(0x00, DeviceReport.ToReport());
104 MessageBox.Show("Device parameters updated successfully.");
105 }
106 catch (Exception ex)
107 {
108 MessageBox.Show("Error: " + ex.Message);
109 }
110 }
111
112 private void btnGetValues_Click(object sender, EventArgs e)
113 {
114 IDevice ConnectionHandle = GetDeviceConnection();
115
116 if (ConnectionHandle == null)
117 {
118 MessageBox.Show("Error: Cannot connect to Datalogger device.");
119 return;
120 }
121
122 Device_Report_t DeviceReport = new Device_Report_t();
123
124 try
125 {
126 Byte[] Report = new Byte[7];
127
128 ConnectionHandle.Read(0x00, Report);
129 DeviceReport.FromReport(Report);
130 String msgText = "Device parameters retrieved successfully.";
131
132 try
133 {
134 dtpDate.Value = new DateTime(
135 (2000 + DeviceReport.Year),
136 DeviceReport.Month,
137 DeviceReport.Day);
138
139 dtpTime.Value = new DateTime(
140 DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
141 DeviceReport.Hour,
142 DeviceReport.Minute,
143 DeviceReport.Second);
144 }
145 catch (Exception ex)
146 {
147 msgText = "Problem reading device:\n" +
148 ex.Message +
149 "\nY:" + DeviceReport.Year.ToString() +
150 " M:" + DeviceReport.Month.ToString() +
151 " D:" + DeviceReport.Day.ToString() +
152 "\n\nUsing current date and time.";
153 dtpDate.Value = DateTime.Now;
154 dtpTime.Value = DateTime.Now;
155 }
156
157 try
158 {
159 nudLogInterval.Value = (DeviceReport.LogInterval500MS / 2);
160 }
161 catch (Exception ex)
162 {
163 nudLogInterval.Value = nudLogInterval.Minimum;
164 }
165
166 MessageBox.Show(msgText);
167 }
168 catch (Exception ex)
169 {
170 MessageBox.Show("Error: " + ex.Message);
171 }
172 }
173
174 private void frmDataloggerSettings_Load(object sender, EventArgs e)
175 {
176
177 }
178 }
179}
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.resx b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.resx
new file mode 100644
index 000000000..19dc0dd8b
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/DataLoggerSettings.resx
@@ -0,0 +1,120 @@
1<?xml version="1.0" encoding="utf-8"?>
2<root>
3 <!--
4 Microsoft ResX Schema
5
6 Version 2.0
7
8 The primary goals of this format is to allow a simple XML format
9 that is mostly human readable. The generation and parsing of the
10 various data types are done through the TypeConverter classes
11 associated with the data types.
12
13 Example:
14
15 ... ado.net/XML headers & schema ...
16 <resheader name="resmimetype">text/microsoft-resx</resheader>
17 <resheader name="version">2.0</resheader>
18 <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19 <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20 <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21 <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22 <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23 <value>[base64 mime encoded serialized .NET Framework object]</value>
24 </data>
25 <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26 <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27 <comment>This is a comment</comment>
28 </data>
29
30 There are any number of "resheader" rows that contain simple
31 name/value pairs.
32
33 Each data row contains a name, and value. The row also contains a
34 type or mimetype. Type corresponds to a .NET class that support
35 text/value conversion through the TypeConverter architecture.
36 Classes that don't support this are serialized and stored with the
37 mimetype set.
38
39 The mimetype is used for serialized objects, and tells the
40 ResXResourceReader how to depersist the object. This is currently not
41 extensible. For a given mimetype the value must be set accordingly:
42
43 Note - application/x-microsoft.net.object.binary.base64 is the format
44 that the ResXResourceWriter will generate, however the reader can
45 read any of the formats listed below.
46
47 mimetype: application/x-microsoft.net.object.binary.base64
48 value : The object must be serialized with
49 : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
50 : and then encoded with base64 encoding.
51
52 mimetype: application/x-microsoft.net.object.soap.base64
53 value : The object must be serialized with
54 : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55 : and then encoded with base64 encoding.
56
57 mimetype: application/x-microsoft.net.object.bytearray.base64
58 value : The object must be serialized into a byte array
59 : using a System.ComponentModel.TypeConverter
60 : and then encoded with base64 encoding.
61 -->
62 <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63 <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
64 <xsd:element name="root" msdata:IsDataSet="true">
65 <xsd:complexType>
66 <xsd:choice maxOccurs="unbounded">
67 <xsd:element name="metadata">
68 <xsd:complexType>
69 <xsd:sequence>
70 <xsd:element name="value" type="xsd:string" minOccurs="0" />
71 </xsd:sequence>
72 <xsd:attribute name="name" use="required" type="xsd:string" />
73 <xsd:attribute name="type" type="xsd:string" />
74 <xsd:attribute name="mimetype" type="xsd:string" />
75 <xsd:attribute ref="xml:space" />
76 </xsd:complexType>
77 </xsd:element>
78 <xsd:element name="assembly">
79 <xsd:complexType>
80 <xsd:attribute name="alias" type="xsd:string" />
81 <xsd:attribute name="name" type="xsd:string" />
82 </xsd:complexType>
83 </xsd:element>
84 <xsd:element name="data">
85 <xsd:complexType>
86 <xsd:sequence>
87 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
88 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
89 </xsd:sequence>
90 <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
91 <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
92 <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
93 <xsd:attribute ref="xml:space" />
94 </xsd:complexType>
95 </xsd:element>
96 <xsd:element name="resheader">
97 <xsd:complexType>
98 <xsd:sequence>
99 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
100 </xsd:sequence>
101 <xsd:attribute name="name" type="xsd:string" use="required" />
102 </xsd:complexType>
103 </xsd:element>
104 </xsd:choice>
105 </xsd:complexType>
106 </xsd:element>
107 </xsd:schema>
108 <resheader name="resmimetype">
109 <value>text/microsoft-resx</value>
110 </resheader>
111 <resheader name="version">
112 <value>2.0</value>
113 </resheader>
114 <resheader name="reader">
115 <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116 </resheader>
117 <resheader name="writer">
118 <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119 </resheader>
120</root> \ No newline at end of file
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Linux.dll b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Linux.dll
new file mode 100644
index 000000000..4c19edd21
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Linux.dll
Binary files differ
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Net.dll b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Net.dll
new file mode 100644
index 000000000..2a7112fc0
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Net.dll
Binary files differ
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Win32.dll b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Win32.dll
new file mode 100644
index 000000000..3693c6ca0
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Hid.Win32.dll
Binary files differ
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Program.cs b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Program.cs
new file mode 100644
index 000000000..2588e60c1
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Program.cs
@@ -0,0 +1,21 @@
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Windows.Forms;
5
6namespace Project1HostApp
7{
8 static class Program
9 {
10 /// <summary>
11 /// The main entry point for the application.
12 /// </summary>
13 [STAThread]
14 static void Main()
15 {
16 Application.EnableVisualStyles();
17 Application.SetCompatibleTextRenderingDefault(false);
18 Application.Run(new frmDataloggerSettings());
19 }
20 }
21}
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/AssemblyInfo.cs b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..a4d0ab1d5
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("TempDataLoggerHostApp")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("Dean Camera")]
12[assembly: AssemblyProduct("Temp Datalogger HostApp")]
13[assembly: AssemblyCopyright("Copyright © Dean Camera 2011")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("f41d67c7-13b2-4710-9e0f-f78e7f2bf2e9")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32// You can specify all the values or you can default the Build and Revision Numbers
33// by using the '*' as shown below:
34// [assembly: AssemblyVersion("1.0.*")]
35[assembly: AssemblyVersion("1.0.0.0")]
36[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.Designer.cs b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..63b1af40d
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
1//------------------------------------------------------------------------------
2// <auto-generated>
3// This code was generated by a tool.
4// Runtime Version:4.0.30319.239
5//
6// Changes to this file may cause incorrect behavior and will be lost if
7// the code is regenerated.
8// </auto-generated>
9//------------------------------------------------------------------------------
10
11namespace TemperatureLoggerHostApp.Properties {
12 using System;
13
14
15 /// <summary>
16 /// A strongly-typed resource class, for looking up localized strings, etc.
17 /// </summary>
18 // This class was auto-generated by the StronglyTypedResourceBuilder
19 // class via a tool like ResGen or Visual Studio.
20 // To add or remove a member, edit your .ResX file then rerun ResGen
21 // with the /str option, or rebuild your VS project.
22 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 internal class Resources {
26
27 private static global::System.Resources.ResourceManager resourceMan;
28
29 private static global::System.Globalization.CultureInfo resourceCulture;
30
31 [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 internal Resources() {
33 }
34
35 /// <summary>
36 /// Returns the cached ResourceManager instance used by this class.
37 /// </summary>
38 [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 internal static global::System.Resources.ResourceManager ResourceManager {
40 get {
41 if (object.ReferenceEquals(resourceMan, null)) {
42 global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TemperatureLoggerHostApp.Properties.Resources", typeof(Resources).Assembly);
43 resourceMan = temp;
44 }
45 return resourceMan;
46 }
47 }
48
49 /// <summary>
50 /// Overrides the current thread's CurrentUICulture property for all
51 /// resource lookups using this strongly typed resource class.
52 /// </summary>
53 [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 internal static global::System.Globalization.CultureInfo Culture {
55 get {
56 return resourceCulture;
57 }
58 set {
59 resourceCulture = value;
60 }
61 }
62 }
63}
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.resx b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Resources.resx
@@ -0,0 +1,117 @@
1<?xml version="1.0" encoding="utf-8"?>
2<root>
3 <!--
4 Microsoft ResX Schema
5
6 Version 2.0
7
8 The primary goals of this format is to allow a simple XML format
9 that is mostly human readable. The generation and parsing of the
10 various data types are done through the TypeConverter classes
11 associated with the data types.
12
13 Example:
14
15 ... ado.net/XML headers & schema ...
16 <resheader name="resmimetype">text/microsoft-resx</resheader>
17 <resheader name="version">2.0</resheader>
18 <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19 <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20 <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21 <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22 <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23 <value>[base64 mime encoded serialized .NET Framework object]</value>
24 </data>
25 <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26 <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27 <comment>This is a comment</comment>
28 </data>
29
30 There are any number of "resheader" rows that contain simple
31 name/value pairs.
32
33 Each data row contains a name, and value. The row also contains a
34 type or mimetype. Type corresponds to a .NET class that support
35 text/value conversion through the TypeConverter architecture.
36 Classes that don't support this are serialized and stored with the
37 mimetype set.
38
39 The mimetype is used for serialized objects, and tells the
40 ResXResourceReader how to depersist the object. This is currently not
41 extensible. For a given mimetype the value must be set accordingly:
42
43 Note - application/x-microsoft.net.object.binary.base64 is the format
44 that the ResXResourceWriter will generate, however the reader can
45 read any of the formats listed below.
46
47 mimetype: application/x-microsoft.net.object.binary.base64
48 value : The object must be serialized with
49 : System.Serialization.Formatters.Binary.BinaryFormatter
50 : and then encoded with base64 encoding.
51
52 mimetype: application/x-microsoft.net.object.soap.base64
53 value : The object must be serialized with
54 : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55 : and then encoded with base64 encoding.
56
57 mimetype: application/x-microsoft.net.object.bytearray.base64
58 value : The object must be serialized into a byte array
59 : using a System.ComponentModel.TypeConverter
60 : and then encoded with base64 encoding.
61 -->
62 <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63 <xsd:element name="root" msdata:IsDataSet="true">
64 <xsd:complexType>
65 <xsd:choice maxOccurs="unbounded">
66 <xsd:element name="metadata">
67 <xsd:complexType>
68 <xsd:sequence>
69 <xsd:element name="value" type="xsd:string" minOccurs="0" />
70 </xsd:sequence>
71 <xsd:attribute name="name" type="xsd:string" />
72 <xsd:attribute name="type" type="xsd:string" />
73 <xsd:attribute name="mimetype" type="xsd:string" />
74 </xsd:complexType>
75 </xsd:element>
76 <xsd:element name="assembly">
77 <xsd:complexType>
78 <xsd:attribute name="alias" type="xsd:string" />
79 <xsd:attribute name="name" type="xsd:string" />
80 </xsd:complexType>
81 </xsd:element>
82 <xsd:element name="data">
83 <xsd:complexType>
84 <xsd:sequence>
85 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
86 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
87 </xsd:sequence>
88 <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
89 <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
90 <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
91 </xsd:complexType>
92 </xsd:element>
93 <xsd:element name="resheader">
94 <xsd:complexType>
95 <xsd:sequence>
96 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
97 </xsd:sequence>
98 <xsd:attribute name="name" type="xsd:string" use="required" />
99 </xsd:complexType>
100 </xsd:element>
101 </xsd:choice>
102 </xsd:complexType>
103 </xsd:element>
104 </xsd:schema>
105 <resheader name="resmimetype">
106 <value>text/microsoft-resx</value>
107 </resheader>
108 <resheader name="version">
109 <value>2.0</value>
110 </resheader>
111 <resheader name="reader">
112 <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
113 </resheader>
114 <resheader name="writer">
115 <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116 </resheader>
117</root> \ No newline at end of file
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.Designer.cs b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..95fc3ad58
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
1//------------------------------------------------------------------------------
2// <auto-generated>
3// This code was generated by a tool.
4// Runtime Version:4.0.30319.239
5//
6// Changes to this file may cause incorrect behavior and will be lost if
7// the code is regenerated.
8// </auto-generated>
9//------------------------------------------------------------------------------
10
11namespace TemperatureLoggerHostApp.Properties {
12
13
14 [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
16 internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17
18 private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19
20 public static Settings Default {
21 get {
22 return defaultInstance;
23 }
24 }
25 }
26}
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.settings b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.settings
new file mode 100644
index 000000000..39645652a
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/Properties/Settings.settings
@@ -0,0 +1,7 @@
1<?xml version='1.0' encoding='utf-8'?>
2<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
3 <Profiles>
4 <Profile Name="(Default)" />
5 </Profiles>
6 <Settings />
7</SettingsFile>
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/README.txt b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/README.txt
new file mode 100644
index 000000000..ab6b9a83a
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/README.txt
@@ -0,0 +1,24 @@
1http://en.sourceforge.jp/projects/sfnet_libhidnet/
2
3This library has been tested on Windows Vista 32bit, Windows Vista 64bit,
4Windows XP 32bit and Debian (Lenny) AMD64 but should work on any version of
5Windows that can run the .NET framework 2.0 and any other operating system
6that has both hiddev and Mono.
7
8Any additions must be tested and work on Windows and Linux, on both 32 and
964 bit. Windows 64 bit testing is particularly important as it is often
10neglected.
11
12
13Hid.Linux.dll was compiled under Linux with Mono (mcs) and uses no generics.
14
15Hid.Win32.dll and Hid.Net.dll were compiled under Windows with the .NET
16Framework v2.0.50727 but are also tested to compile with Mono (gmcs).
17
18
19A good starting point when using this library is Hid.DeviceFactory's Enumerate
20methods.
21
22LogitechMX5000.cs is a simple example of how the library can be used. Other
23examples on common devices are welcomed.
24
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp/TempLoggerHostApp.csproj b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/TempLoggerHostApp.csproj
new file mode 100644
index 000000000..8517d6f42
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp/TempLoggerHostApp.csproj
@@ -0,0 +1,99 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>9.0.21022</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{A2D66069-8CF9-4104-828C-49A73D7DB5D1}</ProjectGuid>
9 <OutputType>WinExe</OutputType>
10 <AppDesignerFolder>Properties</AppDesignerFolder>
11 <RootNamespace>TemperatureLoggerHostApp</RootNamespace>
12 <AssemblyName>TemperatureLoggerHostApp</AssemblyName>
13 <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
14 <FileAlignment>512</FileAlignment>
15 <FileUpgradeFlags>
16 </FileUpgradeFlags>
17 <OldToolsVersion>3.5</OldToolsVersion>
18 <UpgradeBackupLocation />
19 </PropertyGroup>
20 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
21 <DebugSymbols>true</DebugSymbols>
22 <DebugType>full</DebugType>
23 <Optimize>false</Optimize>
24 <OutputPath>bin\Debug\</OutputPath>
25 <DefineConstants>DEBUG;TRACE</DefineConstants>
26 <ErrorReport>prompt</ErrorReport>
27 <WarningLevel>4</WarningLevel>
28 </PropertyGroup>
29 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
30 <DebugType>pdbonly</DebugType>
31 <Optimize>true</Optimize>
32 <OutputPath>bin\Release\</OutputPath>
33 <DefineConstants>TRACE</DefineConstants>
34 <ErrorReport>prompt</ErrorReport>
35 <WarningLevel>4</WarningLevel>
36 </PropertyGroup>
37 <ItemGroup>
38 <Reference Include="Hid.Net, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
39 <SpecificVersion>False</SpecificVersion>
40 <HintPath>.\Hid.Net.dll</HintPath>
41 </Reference>
42 <Reference Include="System" />
43 <Reference Include="System.Core">
44 <RequiredTargetFramework>3.5</RequiredTargetFramework>
45 </Reference>
46 <Reference Include="System.Xml.Linq">
47 <RequiredTargetFramework>3.5</RequiredTargetFramework>
48 </Reference>
49 <Reference Include="System.Data.DataSetExtensions">
50 <RequiredTargetFramework>3.5</RequiredTargetFramework>
51 </Reference>
52 <Reference Include="System.Data" />
53 <Reference Include="System.Deployment" />
54 <Reference Include="System.Drawing" />
55 <Reference Include="System.Windows.Forms" />
56 <Reference Include="System.Xml" />
57 </ItemGroup>
58 <ItemGroup>
59 <Compile Include="DataLoggerSettings.cs">
60 <SubType>Form</SubType>
61 </Compile>
62 <Compile Include="DataLoggerSettings.Designer.cs">
63 <DependentUpon>DataLoggerSettings.cs</DependentUpon>
64 </Compile>
65 <Compile Include="Program.cs" />
66 <Compile Include="Properties\AssemblyInfo.cs" />
67 <EmbeddedResource Include="DataLoggerSettings.resx">
68 <DependentUpon>DataLoggerSettings.cs</DependentUpon>
69 <SubType>Designer</SubType>
70 </EmbeddedResource>
71 <EmbeddedResource Include="Properties\Resources.resx">
72 <Generator>ResXFileCodeGenerator</Generator>
73 <LastGenOutput>Resources.Designer.cs</LastGenOutput>
74 <SubType>Designer</SubType>
75 </EmbeddedResource>
76 <Compile Include="Properties\Resources.Designer.cs">
77 <AutoGen>True</AutoGen>
78 <DependentUpon>Resources.resx</DependentUpon>
79 <DesignTime>True</DesignTime>
80 </Compile>
81 <None Include="Properties\Settings.settings">
82 <Generator>SettingsSingleFileGenerator</Generator>
83 <LastGenOutput>Settings.Designer.cs</LastGenOutput>
84 </None>
85 <Compile Include="Properties\Settings.Designer.cs">
86 <AutoGen>True</AutoGen>
87 <DependentUpon>Settings.settings</DependentUpon>
88 <DesignTimeSharedInput>True</DesignTimeSharedInput>
89 </Compile>
90 </ItemGroup>
91 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
92 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
93 Other similar extension points exist, see Microsoft.Common.targets.
94 <Target Name="BeforeBuild">
95 </Target>
96 <Target Name="AfterBuild">
97 </Target>
98 -->
99</Project> \ No newline at end of file
diff --git a/lib/lufa/Projects/TempDataLogger/TempLogHostApp_Python/temp_log_config.py b/lib/lufa/Projects/TempDataLogger/TempLogHostApp_Python/temp_log_config.py
new file mode 100644
index 000000000..fdb4ad9b6
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TempLogHostApp_Python/temp_log_config.py
@@ -0,0 +1,99 @@
1"""
2 LUFA Library
3 Copyright (C) Dean Camera, 2017.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7"""
8
9"""
10 Front-end configuration app for the TempDataLogger project. This script
11 configures the logger to the current system time and date, with a user
12 defined logging interval.
13
14 The logging interval should be specified in milliseconds and is rounded to
15 a multiple of 500ms.
16
17 Usage:
18 python temp_log_config.py <Log_Interval>
19
20 Example:
21 python temp_log_config.py 500
22
23 Requires the pywinusb library (https://pypi.python.org/pypi/pywinusb/).
24"""
25
26import sys
27from datetime import datetime
28import pywinusb.hid as hid
29
30# Generic HID device VID, PID and report payload length (length is increased
31# by one to account for the Report ID byte that must be pre-pended)
32device_vid = 0x03EB
33device_pid = 0x2063
34report_length = 1 + 7
35
36
37def get_hid_device_handle():
38 hid_device_filter = hid.HidDeviceFilter(vendor_id=device_vid,
39 product_id=device_pid)
40
41 valid_hid_devices = hid_device_filter.get_devices()
42
43 if len(valid_hid_devices) is 0:
44 return None
45 else:
46 return valid_hid_devices[0]
47
48
49def configure_temp_log_device(device, time_date, log_interval_500ms):
50 # Report data for the demo is the report ID (always zero)
51 report_data = [0]
52
53 # Followed by the time/date data
54 report_data.extend([time_date.hour, time_date.minute,
55 time_date.second, time_date.day,
56 time_date.month, time_date.year - 2000])
57
58 # Lastly the log interval in 500ms units of time
59 report_data.extend([log_interval_500ms])
60
61 # Zero-extend the array to the length the report should be
62 report_data.extend([0] * (report_length - len(report_data)))
63
64 # Send the generated report to the device
65 device.send_output_report(report_data)
66
67
68def main(time_date, log_interval_500ms):
69 hid_device = get_hid_device_handle()
70
71 if hid_device is None:
72 print("No valid HID device found.")
73 sys.exit(1)
74
75 try:
76 hid_device.open()
77
78 print("Connected to device 0x%04X/0x%04X - %s [%s]" %
79 (hid_device.vendor_id, hid_device.product_id,
80 hid_device.product_name, hid_device.vendor_name))
81
82 configure_temp_log_device(hid_device, time_date, log_interval_500ms)
83
84 print("Time/Date is now set to %s" % time_date)
85 print("Log interval is now set to every %0.1fs" % (log_interval_500ms * (500.0 / 1000.0)))
86
87 finally:
88 hid_device.close()
89
90
91if __name__ == '__main__':
92 time_date = datetime.now()
93 log_interval_500ms = (int(sys.argv[1]) / 500) if len(sys.argv) > 1 else 2
94
95 # Clamp the log interval to the allowable range
96 log_interval_500ms = max(log_interval_500ms, 0x01)
97 log_interval_500ms = min(log_interval_500ms, 0xFF)
98
99 main(time_date, log_interval_500ms)
diff --git a/lib/lufa/Projects/TempDataLogger/TemperatureDataLogger.txt b/lib/lufa/Projects/TempDataLogger/TemperatureDataLogger.txt
new file mode 100644
index 000000000..4d4e0b5e8
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/TemperatureDataLogger.txt
@@ -0,0 +1,86 @@
1/** \file
2 *
3 * This file contains special DoxyGen information for the generation of the main page and other special
4 * documentation pages. It is not a project source file.
5 */
6
7/** \mainpage Temperature Datalogger Project
8 *
9 * \section Sec_Compat Demo Compatibility:
10 *
11 * The following list indicates what microcontrollers are compatible with this demo.
12 *
13 * \li Series 7 USB AVRs (AT90USBxxx7)
14 * \li Series 6 USB AVRs (AT90USBxxx6)
15 * \li Series 4 USB AVRs (ATMEGAxxU4) - <i>those with >16KB of FLASH memory only</i>
16 *
17 * \section Sec_Info USB Information:
18 *
19 * The following table gives a rundown of the USB utilization of this demo.
20 *
21 * <table>
22 * <tr>
23 * <td><b>USB Mode:</b></td>
24 * <td>Device</td>
25 * </tr>
26 * <tr>
27 * <td><b>USB Classes:</b></td>
28 * <td>Mass Storage Device \n
29 * Human Interface Device</td>
30 * </tr>
31 * <tr>
32 * <td><b>USB Subclasses:</b></td>
33 * <td>Bulk-Only Transport \n
34 * Keyboard Subclass</td>
35 * </tr>
36 * <tr>
37 * <td><b>Relevant Standards:</b></td>
38 * <td>USBIF Mass Storage Standard \n
39 * USB Bulk-Only Transport Standard \n
40 * SCSI Primary Commands Specification \n
41 * SCSI Block Commands Specification \n
42 * USBIF HID Specification, USBIF HID Usage Tables</td>
43 * </tr>
44 * <tr>
45 * <td><b>Supported USB Speeds:</b></td>
46 * <td>Full Speed Mode</td>
47 * </tr>
48 * </table>
49 *
50 * \section Sec_Description Project Description:
51 *
52 * Temperature Data Logger project. This project is a very basic USB data logger for the current temperature as reported by
53 * the board's temperature sensor, writing the temperature to a file stored on the board's Dataflash in a FAT filesystem
54 * each time a specified interval elapses. When inserted into a PC, the datalogger will appear as a standard USB Mass Storage
55 * device with a single text file, which contains the logged data. Files are named according to the current date when the
56 * logging commences.
57 *
58 * A DS1307 or compatible RTC IC is designed to be attached to the AVR's TWI bus, for the management of timestamps on the
59 * sampled data. This project will not function correctly if the RTC chip is omitted unless the DUMMY_RTC compile time token
60 * is specified - see \ref Sec_Options.
61 *
62 * Due to the host's need for exclusive access to the file system, the device will not log samples while connected to a host.
63 * For the logger to store data, the Dataflash must first be formatted by the host so that it contains a valid FAT file system.
64 *
65 * This project uses the FatFS library from ELM Chan (http://elm-chan.org/fsw/ff/00index_e.html) and the .NET HID device library
66 * LibHIDNet (http://sourceforge.net/projects/libhidnet/).
67 *
68 * \section Sec_Options Project Options
69 *
70 * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
71 *
72 * <table>
73 * <tr>
74 * <th><b>Define Name:</b></th>
75 * <th><b>Location:</b></th>
76 * <th><b>Description:</b></th>
77 * </tr>
78 * <tr>
79 * <td>DUMMY_RTC</td>
80 * <td>AppConfig.h</td>
81 * <td>When a DS1307 RTC chip is not fitted, this token can be defined to make the demo use a dummy software RTC using the system
82 * clock. This is less accurate and does not store the set time and date into non-volatile memory.</td>
83 * </tr>
84 * </table>
85 */
86
diff --git a/lib/lufa/Projects/TempDataLogger/asf.xml b/lib/lufa/Projects/TempDataLogger/asf.xml
new file mode 100644
index 000000000..bf7ee2c3f
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/asf.xml
@@ -0,0 +1,72 @@
1<asf xmlversion="1.0">
2 <project caption="Temperature Datalogger" id="lufa.projects.temp_datalogger.avr8">
3 <require idref="lufa.projects.temp_datalogger"/>
4 <require idref="lufa.boards.dummy.avr8"/>
5 <generator value="as5_8"/>
6
7 <device-support value="at90usb1287"/>
8 <config name="lufa.drivers.board.name" value="usbkey"/>
9
10 <build type="define" name="F_CPU" value="8000000UL"/>
11 <build type="define" name="F_USB" value="8000000UL"/>
12 </project>
13
14 <module type="application" id="lufa.projects.temp_datalogger" caption="Temperature Datalogger">
15 <info type="description" value="summary">
16 Temperature Datalogger project.
17 </info>
18
19 <info type="gui-flag" value="move-to-root"/>
20
21 <info type="keyword" value="Technology">
22 <keyword value="Class Driver APIs"/>
23 <keyword value="USB Device"/>
24 <keyword value="HID Class"/>
25 <keyword value="Mass Storage Class"/>
26 </info>
27
28 <device-support-alias value="lufa_avr8"/>
29 <device-support-alias value="lufa_xmega"/>
30 <device-support-alias value="lufa_uc3"/>
31
32 <build type="distribute" subtype="user-file" value="doxyfile"/>
33 <build type="distribute" subtype="user-file" value="TemperatureDataLogger.txt"/>
34 <build type="distribute" subtype="directory" value="TempLogHostApp"/>
35 <build type="distribute" subtype="directory" value="TempLogHostApp_Python"/>
36
37 <build type="c-source" value="TempDataLogger.c"/>
38 <build type="c-source" value="Descriptors.c"/>
39 <build type="header-file" value="TempDataLogger.h"/>
40 <build type="header-file" value="Descriptors.h"/>
41
42 <build type="c-source" value="Lib/DataflashManager.c"/>
43 <build type="header-file" value="Lib/DataflashManager.h"/>
44 <build type="c-source" value="Lib/RTC.c"/>
45 <build type="header-file" value="Lib/RTC.h"/>
46 <build type="c-source" value="Lib/SCSI.c"/>
47 <build type="header-file" value="Lib/SCSI.h"/>
48
49 <build type="include-path" value="Lib/FATFs/"/>
50 <build type="c-source" value="Lib/FATFs/ff.c"/>
51 <build type="header-file" value="Lib/FATFs/ff.h"/>
52 <build type="c-source" value="Lib/FATFs/diskio.c"/>
53 <build type="header-file" value="Lib/FATFs/diskio.h"/>
54 <build type="header-file" value="Lib/FATFs/ffconf.h"/>
55 <build type="header-file" value="Lib/FATFs/integer.h"/>
56
57 <build type="module-config" subtype="path" value="Config"/>
58 <build type="module-config" subtype="required-header-file" value="AppConfig.h"/>
59 <build type="header-file" value="Config/AppConfig.h"/>
60 <build type="header-file" value="Config/LUFAConfig.h"/>
61
62 <require idref="lufa.common"/>
63 <require idref="lufa.platform"/>
64 <require idref="lufa.drivers.usb"/>
65 <require idref="lufa.drivers.board"/>
66 <require idref="lufa.drivers.board.leds"/>
67 <require idref="lufa.drivers.board.temperature"/>
68 <require idref="lufa.drivers.board.dataflash"/>
69 <require idref="lufa.drivers.peripheral.adc"/>
70 <require idref="lufa.drivers.peripheral.twi"/>
71 </module>
72</asf>
diff --git a/lib/lufa/Projects/TempDataLogger/doxyfile b/lib/lufa/Projects/TempDataLogger/doxyfile
new file mode 100644
index 000000000..395984174
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/doxyfile
@@ -0,0 +1,2397 @@
1# Doxyfile 1.8.9
2
3# This file describes the settings to be used by the documentation system
4# doxygen (www.doxygen.org) for a project.
5#
6# All text after a double hash (##) is considered a comment and is placed in
7# front of the TAG it is preceding.
8#
9# All text after a single hash (#) is considered a comment and will be ignored.
10# The format is:
11# TAG = value [value, ...]
12# For lists, items can also be appended using:
13# TAG += value [value, ...]
14# Values that contain spaces should be placed between quotes (\" \").
15
16#---------------------------------------------------------------------------
17# Project related configuration options
18#---------------------------------------------------------------------------
19
20# This tag specifies the encoding used for all characters in the config file
21# that follow. The default is UTF-8 which is also the encoding used for all text
22# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
23# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
24# for the list of possible encodings.
25# The default value is: UTF-8.
26
27DOXYFILE_ENCODING = UTF-8
28
29# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
30# double-quotes, unless you are using Doxywizard) that should identify the
31# project for which the documentation is generated. This name is used in the
32# title of most generated pages and in a few other places.
33# The default value is: My Project.
34
35PROJECT_NAME = "Temperature Datalogger Project"
36
37# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
38# could be handy for archiving the generated documentation or if some version
39# control system is used.
40
41PROJECT_NUMBER =
42
43# Using the PROJECT_BRIEF tag one can provide an optional one line description
44# for a project that appears at the top of each page and should give viewer a
45# quick idea about the purpose of the project. Keep the description short.
46
47PROJECT_BRIEF =
48
49# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
50# in the documentation. The maximum height of the logo should not exceed 55
51# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
52# the logo to the output directory.
53
54PROJECT_LOGO =
55
56# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
57# into which the generated documentation will be written. If a relative path is
58# entered, it will be relative to the location where doxygen was started. If
59# left blank the current directory will be used.
60
61OUTPUT_DIRECTORY = ./Documentation/
62
63# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
64# directories (in 2 levels) under the output directory of each output format and
65# will distribute the generated files over these directories. Enabling this
66# option can be useful when feeding doxygen a huge amount of source files, where
67# putting all generated files in the same directory would otherwise causes
68# performance problems for the file system.
69# The default value is: NO.
70
71CREATE_SUBDIRS = NO
72
73# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
74# characters to appear in the names of generated files. If set to NO, non-ASCII
75# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
76# U+3044.
77# The default value is: NO.
78
79ALLOW_UNICODE_NAMES = NO
80
81# The OUTPUT_LANGUAGE tag is used to specify the language in which all
82# documentation generated by doxygen is written. Doxygen will use this
83# information to generate all constant output in the proper language.
84# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
85# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
86# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
87# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
88# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
89# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
90# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
91# Ukrainian and Vietnamese.
92# The default value is: English.
93
94OUTPUT_LANGUAGE = English
95
96# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
97# descriptions after the members that are listed in the file and class
98# documentation (similar to Javadoc). Set to NO to disable this.
99# The default value is: YES.
100
101BRIEF_MEMBER_DESC = YES
102
103# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
104# description of a member or function before the detailed description
105#
106# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
107# brief descriptions will be completely suppressed.
108# The default value is: YES.
109
110REPEAT_BRIEF = YES
111
112# This tag implements a quasi-intelligent brief description abbreviator that is
113# used to form the text in various listings. Each string in this list, if found
114# as the leading text of the brief description, will be stripped from the text
115# and the result, after processing the whole list, is used as the annotated
116# text. Otherwise, the brief description is used as-is. If left blank, the
117# following values are used ($name is automatically replaced with the name of
118# the entity):The $name class, The $name widget, The $name file, is, provides,
119# specifies, contains, represents, a, an and the.
120
121ABBREVIATE_BRIEF = "The $name class" \
122 "The $name widget" \
123 "The $name file" \
124 is \
125 provides \
126 specifies \
127 contains \
128 represents \
129 a \
130 an \
131 the
132
133# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
134# doxygen will generate a detailed section even if there is only a brief
135# description.
136# The default value is: NO.
137
138ALWAYS_DETAILED_SEC = NO
139
140# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
141# inherited members of a class in the documentation of that class as if those
142# members were ordinary class members. Constructors, destructors and assignment
143# operators of the base classes will not be shown.
144# The default value is: NO.
145
146INLINE_INHERITED_MEMB = NO
147
148# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
149# before files name in the file list and in the header files. If set to NO the
150# shortest path that makes the file name unique will be used
151# The default value is: YES.
152
153FULL_PATH_NAMES = YES
154
155# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
156# Stripping is only done if one of the specified strings matches the left-hand
157# part of the path. The tag can be used to show relative paths in the file list.
158# If left blank the directory from which doxygen is run is used as the path to
159# strip.
160#
161# Note that you can specify absolute paths here, but also relative paths, which
162# will be relative from the directory where doxygen is started.
163# This tag requires that the tag FULL_PATH_NAMES is set to YES.
164
165STRIP_FROM_PATH =
166
167# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
168# path mentioned in the documentation of a class, which tells the reader which
169# header file to include in order to use a class. If left blank only the name of
170# the header file containing the class definition is used. Otherwise one should
171# specify the list of include paths that are normally passed to the compiler
172# using the -I flag.
173
174STRIP_FROM_INC_PATH =
175
176# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
177# less readable) file names. This can be useful is your file systems doesn't
178# support long names like on DOS, Mac, or CD-ROM.
179# The default value is: NO.
180
181SHORT_NAMES = YES
182
183# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
184# first line (until the first dot) of a Javadoc-style comment as the brief
185# description. If set to NO, the Javadoc-style will behave just like regular Qt-
186# style comments (thus requiring an explicit @brief command for a brief
187# description.)
188# The default value is: NO.
189
190JAVADOC_AUTOBRIEF = NO
191
192# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
193# line (until the first dot) of a Qt-style comment as the brief description. If
194# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
195# requiring an explicit \brief command for a brief description.)
196# The default value is: NO.
197
198QT_AUTOBRIEF = NO
199
200# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
201# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
202# a brief description. This used to be the default behavior. The new default is
203# to treat a multi-line C++ comment block as a detailed description. Set this
204# tag to YES if you prefer the old behavior instead.
205#
206# Note that setting this tag to YES also means that rational rose comments are
207# not recognized any more.
208# The default value is: NO.
209
210MULTILINE_CPP_IS_BRIEF = NO
211
212# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
213# documentation from any documented member that it re-implements.
214# The default value is: YES.
215
216INHERIT_DOCS = YES
217
218# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
219# page for each member. If set to NO, the documentation of a member will be part
220# of the file/class/namespace that contains it.
221# The default value is: NO.
222
223SEPARATE_MEMBER_PAGES = NO
224
225# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
226# uses this value to replace tabs by spaces in code fragments.
227# Minimum value: 1, maximum value: 16, default value: 4.
228
229TAB_SIZE = 4
230
231# This tag can be used to specify a number of aliases that act as commands in
232# the documentation. An alias has the form:
233# name=value
234# For example adding
235# "sideeffect=@par Side Effects:\n"
236# will allow you to put the command \sideeffect (or @sideeffect) in the
237# documentation, which will result in a user-defined paragraph with heading
238# "Side Effects:". You can put \n's in the value part of an alias to insert
239# newlines.
240
241ALIASES =
242
243# This tag can be used to specify a number of word-keyword mappings (TCL only).
244# A mapping has the form "name=value". For example adding "class=itcl::class"
245# will allow you to use the command class in the itcl::class meaning.
246
247TCL_SUBST =
248
249# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
250# only. Doxygen will then generate output that is more tailored for C. For
251# instance, some of the names that are used will be different. The list of all
252# members will be omitted, etc.
253# The default value is: NO.
254
255OPTIMIZE_OUTPUT_FOR_C = YES
256
257# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
258# Python sources only. Doxygen will then generate output that is more tailored
259# for that language. For instance, namespaces will be presented as packages,
260# qualified scopes will look different, etc.
261# The default value is: NO.
262
263OPTIMIZE_OUTPUT_JAVA = NO
264
265# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
266# sources. Doxygen will then generate output that is tailored for Fortran.
267# The default value is: NO.
268
269OPTIMIZE_FOR_FORTRAN = NO
270
271# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
272# sources. Doxygen will then generate output that is tailored for VHDL.
273# The default value is: NO.
274
275OPTIMIZE_OUTPUT_VHDL = NO
276
277# Doxygen selects the parser to use depending on the extension of the files it
278# parses. With this tag you can assign which parser to use for a given
279# extension. Doxygen has a built-in mapping, but you can override or extend it
280# using this tag. The format is ext=language, where ext is a file extension, and
281# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
282# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
283# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
284# Fortran. In the later case the parser tries to guess whether the code is fixed
285# or free formatted code, this is the default for Fortran type files), VHDL. For
286# instance to make doxygen treat .inc files as Fortran files (default is PHP),
287# and .f files as C (default is Fortran), use: inc=Fortran f=C.
288#
289# Note: For files without extension you can use no_extension as a placeholder.
290#
291# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
292# the files are not read by doxygen.
293
294EXTENSION_MAPPING =
295
296# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
297# according to the Markdown format, which allows for more readable
298# documentation. See http://daringfireball.net/projects/markdown/ for details.
299# The output of markdown processing is further processed by doxygen, so you can
300# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
301# case of backward compatibilities issues.
302# The default value is: YES.
303
304MARKDOWN_SUPPORT = NO
305
306# When enabled doxygen tries to link words that correspond to documented
307# classes, or namespaces to their corresponding documentation. Such a link can
308# be prevented in individual cases by putting a % sign in front of the word or
309# globally by setting AUTOLINK_SUPPORT to NO.
310# The default value is: YES.
311
312AUTOLINK_SUPPORT = YES
313
314# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
315# to include (a tag file for) the STL sources as input, then you should set this
316# tag to YES in order to let doxygen match functions declarations and
317# definitions whose arguments contain STL classes (e.g. func(std::string);
318# versus func(std::string) {}). This also make the inheritance and collaboration
319# diagrams that involve STL classes more complete and accurate.
320# The default value is: NO.
321
322BUILTIN_STL_SUPPORT = NO
323
324# If you use Microsoft's C++/CLI language, you should set this option to YES to
325# enable parsing support.
326# The default value is: NO.
327
328CPP_CLI_SUPPORT = NO
329
330# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
331# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
332# will parse them like normal C++ but will assume all classes use public instead
333# of private inheritance when no explicit protection keyword is present.
334# The default value is: NO.
335
336SIP_SUPPORT = NO
337
338# For Microsoft's IDL there are propget and propput attributes to indicate
339# getter and setter methods for a property. Setting this option to YES will make
340# doxygen to replace the get and set methods by a property in the documentation.
341# This will only work if the methods are indeed getting or setting a simple
342# type. If this is not the case, or you want to show the methods anyway, you
343# should set this option to NO.
344# The default value is: YES.
345
346IDL_PROPERTY_SUPPORT = YES
347
348# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
349# tag is set to YES then doxygen will reuse the documentation of the first
350# member in the group (if any) for the other members of the group. By default
351# all members of a group must be documented explicitly.
352# The default value is: NO.
353
354DISTRIBUTE_GROUP_DOC = NO
355
356# Set the SUBGROUPING tag to YES to allow class member groups of the same type
357# (for instance a group of public functions) to be put as a subgroup of that
358# type (e.g. under the Public Functions section). Set it to NO to prevent
359# subgrouping. Alternatively, this can be done per class using the
360# \nosubgrouping command.
361# The default value is: YES.
362
363SUBGROUPING = YES
364
365# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
366# are shown inside the group in which they are included (e.g. using \ingroup)
367# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
368# and RTF).
369#
370# Note that this feature does not work in combination with
371# SEPARATE_MEMBER_PAGES.
372# The default value is: NO.
373
374INLINE_GROUPED_CLASSES = NO
375
376# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
377# with only public data fields or simple typedef fields will be shown inline in
378# the documentation of the scope in which they are defined (i.e. file,
379# namespace, or group documentation), provided this scope is documented. If set
380# to NO, structs, classes, and unions are shown on a separate page (for HTML and
381# Man pages) or section (for LaTeX and RTF).
382# The default value is: NO.
383
384INLINE_SIMPLE_STRUCTS = NO
385
386# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
387# enum is documented as struct, union, or enum with the name of the typedef. So
388# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
389# with name TypeT. When disabled the typedef will appear as a member of a file,
390# namespace, or class. And the struct will be named TypeS. This can typically be
391# useful for C code in case the coding convention dictates that all compound
392# types are typedef'ed and only the typedef is referenced, never the tag name.
393# The default value is: NO.
394
395TYPEDEF_HIDES_STRUCT = NO
396
397# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
398# cache is used to resolve symbols given their name and scope. Since this can be
399# an expensive process and often the same symbol appears multiple times in the
400# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
401# doxygen will become slower. If the cache is too large, memory is wasted. The
402# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
403# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
404# symbols. At the end of a run doxygen will report the cache usage and suggest
405# the optimal cache size from a speed point of view.
406# Minimum value: 0, maximum value: 9, default value: 0.
407
408LOOKUP_CACHE_SIZE = 0
409
410#---------------------------------------------------------------------------
411# Build related configuration options
412#---------------------------------------------------------------------------
413
414# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
415# documentation are documented, even if no documentation was available. Private
416# class members and static file members will be hidden unless the
417# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
418# Note: This will also disable the warnings about undocumented members that are
419# normally produced when WARNINGS is set to YES.
420# The default value is: NO.
421
422EXTRACT_ALL = YES
423
424# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
425# be included in the documentation.
426# The default value is: NO.
427
428EXTRACT_PRIVATE = YES
429
430# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
431# scope will be included in the documentation.
432# The default value is: NO.
433
434EXTRACT_PACKAGE = NO
435
436# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
437# included in the documentation.
438# The default value is: NO.
439
440EXTRACT_STATIC = YES
441
442# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
443# locally in source files will be included in the documentation. If set to NO,
444# only classes defined in header files are included. Does not have any effect
445# for Java sources.
446# The default value is: YES.
447
448EXTRACT_LOCAL_CLASSES = YES
449
450# This flag is only useful for Objective-C code. If set to YES, local methods,
451# which are defined in the implementation section but not in the interface are
452# included in the documentation. If set to NO, only methods in the interface are
453# included.
454# The default value is: NO.
455
456EXTRACT_LOCAL_METHODS = NO
457
458# If this flag is set to YES, the members of anonymous namespaces will be
459# extracted and appear in the documentation as a namespace called
460# 'anonymous_namespace{file}', where file will be replaced with the base name of
461# the file that contains the anonymous namespace. By default anonymous namespace
462# are hidden.
463# The default value is: NO.
464
465EXTRACT_ANON_NSPACES = NO
466
467# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
468# undocumented members inside documented classes or files. If set to NO these
469# members will be included in the various overviews, but no documentation
470# section is generated. This option has no effect if EXTRACT_ALL is enabled.
471# The default value is: NO.
472
473HIDE_UNDOC_MEMBERS = NO
474
475# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
476# undocumented classes that are normally visible in the class hierarchy. If set
477# to NO, these classes will be included in the various overviews. This option
478# has no effect if EXTRACT_ALL is enabled.
479# The default value is: NO.
480
481HIDE_UNDOC_CLASSES = NO
482
483# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
484# (class|struct|union) declarations. If set to NO, these declarations will be
485# included in the documentation.
486# The default value is: NO.
487
488HIDE_FRIEND_COMPOUNDS = NO
489
490# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
491# documentation blocks found inside the body of a function. If set to NO, these
492# blocks will be appended to the function's detailed documentation block.
493# The default value is: NO.
494
495HIDE_IN_BODY_DOCS = NO
496
497# The INTERNAL_DOCS tag determines if documentation that is typed after a
498# \internal command is included. If the tag is set to NO then the documentation
499# will be excluded. Set it to YES to include the internal documentation.
500# The default value is: NO.
501
502INTERNAL_DOCS = NO
503
504# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
505# names in lower-case letters. If set to YES, upper-case letters are also
506# allowed. This is useful if you have classes or files whose names only differ
507# in case and if your file system supports case sensitive file names. Windows
508# and Mac users are advised to set this option to NO.
509# The default value is: system dependent.
510
511CASE_SENSE_NAMES = NO
512
513# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
514# their full class and namespace scopes in the documentation. If set to YES, the
515# scope will be hidden.
516# The default value is: NO.
517
518HIDE_SCOPE_NAMES = NO
519
520# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
521# append additional text to a page's title, such as Class Reference. If set to
522# YES the compound reference will be hidden.
523# The default value is: NO.
524
525HIDE_COMPOUND_REFERENCE= NO
526
527# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
528# the files that are included by a file in the documentation of that file.
529# The default value is: YES.
530
531SHOW_INCLUDE_FILES = YES
532
533# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
534# grouped member an include statement to the documentation, telling the reader
535# which file to include in order to use the member.
536# The default value is: NO.
537
538SHOW_GROUPED_MEMB_INC = NO
539
540# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
541# files with double quotes in the documentation rather than with sharp brackets.
542# The default value is: NO.
543
544FORCE_LOCAL_INCLUDES = NO
545
546# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
547# documentation for inline members.
548# The default value is: YES.
549
550INLINE_INFO = YES
551
552# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
553# (detailed) documentation of file and class members alphabetically by member
554# name. If set to NO, the members will appear in declaration order.
555# The default value is: YES.
556
557SORT_MEMBER_DOCS = YES
558
559# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
560# descriptions of file, namespace and class members alphabetically by member
561# name. If set to NO, the members will appear in declaration order. Note that
562# this will also influence the order of the classes in the class list.
563# The default value is: NO.
564
565SORT_BRIEF_DOCS = NO
566
567# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
568# (brief and detailed) documentation of class members so that constructors and
569# destructors are listed first. If set to NO the constructors will appear in the
570# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
571# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
572# member documentation.
573# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
574# detailed member documentation.
575# The default value is: NO.
576
577SORT_MEMBERS_CTORS_1ST = NO
578
579# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
580# of group names into alphabetical order. If set to NO the group names will
581# appear in their defined order.
582# The default value is: NO.
583
584SORT_GROUP_NAMES = NO
585
586# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
587# fully-qualified names, including namespaces. If set to NO, the class list will
588# be sorted only by class name, not including the namespace part.
589# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
590# Note: This option applies only to the class list, not to the alphabetical
591# list.
592# The default value is: NO.
593
594SORT_BY_SCOPE_NAME = NO
595
596# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
597# type resolution of all parameters of a function it will reject a match between
598# the prototype and the implementation of a member function even if there is
599# only one candidate or it is obvious which candidate to choose by doing a
600# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
601# accept a match between prototype and implementation in such cases.
602# The default value is: NO.
603
604STRICT_PROTO_MATCHING = NO
605
606# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
607# list. This list is created by putting \todo commands in the documentation.
608# The default value is: YES.
609
610GENERATE_TODOLIST = NO
611
612# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
613# list. This list is created by putting \test commands in the documentation.
614# The default value is: YES.
615
616GENERATE_TESTLIST = NO
617
618# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
619# list. This list is created by putting \bug commands in the documentation.
620# The default value is: YES.
621
622GENERATE_BUGLIST = NO
623
624# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
625# the deprecated list. This list is created by putting \deprecated commands in
626# the documentation.
627# The default value is: YES.
628
629GENERATE_DEPRECATEDLIST= YES
630
631# The ENABLED_SECTIONS tag can be used to enable conditional documentation
632# sections, marked by \if <section_label> ... \endif and \cond <section_label>
633# ... \endcond blocks.
634
635ENABLED_SECTIONS =
636
637# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
638# initial value of a variable or macro / define can have for it to appear in the
639# documentation. If the initializer consists of more lines than specified here
640# it will be hidden. Use a value of 0 to hide initializers completely. The
641# appearance of the value of individual variables and macros / defines can be
642# controlled using \showinitializer or \hideinitializer command in the
643# documentation regardless of this setting.
644# Minimum value: 0, maximum value: 10000, default value: 30.
645
646MAX_INITIALIZER_LINES = 30
647
648# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
649# the bottom of the documentation of classes and structs. If set to YES, the
650# list will mention the files that were used to generate the documentation.
651# The default value is: YES.
652
653SHOW_USED_FILES = YES
654
655# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
656# will remove the Files entry from the Quick Index and from the Folder Tree View
657# (if specified).
658# The default value is: YES.
659
660SHOW_FILES = YES
661
662# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
663# page. This will remove the Namespaces entry from the Quick Index and from the
664# Folder Tree View (if specified).
665# The default value is: YES.
666
667SHOW_NAMESPACES = YES
668
669# The FILE_VERSION_FILTER tag can be used to specify a program or script that
670# doxygen should invoke to get the current version for each file (typically from
671# the version control system). Doxygen will invoke the program by executing (via
672# popen()) the command command input-file, where command is the value of the
673# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
674# by doxygen. Whatever the program writes to standard output is used as the file
675# version. For an example see the documentation.
676
677FILE_VERSION_FILTER =
678
679# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
680# by doxygen. The layout file controls the global structure of the generated
681# output files in an output format independent way. To create the layout file
682# that represents doxygen's defaults, run doxygen with the -l option. You can
683# optionally specify a file name after the option, if omitted DoxygenLayout.xml
684# will be used as the name of the layout file.
685#
686# Note that if you run doxygen from a directory containing a file called
687# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
688# tag is left empty.
689
690LAYOUT_FILE =
691
692# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
693# the reference definitions. This must be a list of .bib files. The .bib
694# extension is automatically appended if omitted. This requires the bibtex tool
695# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
696# For LaTeX the style of the bibliography can be controlled using
697# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
698# search path. See also \cite for info how to create references.
699
700CITE_BIB_FILES =
701
702#---------------------------------------------------------------------------
703# Configuration options related to warning and progress messages
704#---------------------------------------------------------------------------
705
706# The QUIET tag can be used to turn on/off the messages that are generated to
707# standard output by doxygen. If QUIET is set to YES this implies that the
708# messages are off.
709# The default value is: NO.
710
711QUIET = YES
712
713# The WARNINGS tag can be used to turn on/off the warning messages that are
714# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
715# this implies that the warnings are on.
716#
717# Tip: Turn warnings on while writing the documentation.
718# The default value is: YES.
719
720WARNINGS = YES
721
722# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
723# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
724# will automatically be disabled.
725# The default value is: YES.
726
727WARN_IF_UNDOCUMENTED = YES
728
729# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
730# potential errors in the documentation, such as not documenting some parameters
731# in a documented function, or documenting parameters that don't exist or using
732# markup commands wrongly.
733# The default value is: YES.
734
735WARN_IF_DOC_ERROR = YES
736
737# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
738# are documented, but have no documentation for their parameters or return
739# value. If set to NO, doxygen will only warn about wrong or incomplete
740# parameter documentation, but not about the absence of documentation.
741# The default value is: NO.
742
743WARN_NO_PARAMDOC = YES
744
745# The WARN_FORMAT tag determines the format of the warning messages that doxygen
746# can produce. The string should contain the $file, $line, and $text tags, which
747# will be replaced by the file and line number from which the warning originated
748# and the warning text. Optionally the format may contain $version, which will
749# be replaced by the version of the file (if it could be obtained via
750# FILE_VERSION_FILTER)
751# The default value is: $file:$line: $text.
752
753WARN_FORMAT = "$file:$line: $text"
754
755# The WARN_LOGFILE tag can be used to specify a file to which warning and error
756# messages should be written. If left blank the output is written to standard
757# error (stderr).
758
759WARN_LOGFILE =
760
761#---------------------------------------------------------------------------
762# Configuration options related to the input files
763#---------------------------------------------------------------------------
764
765# The INPUT tag is used to specify the files and/or directories that contain
766# documented source files. You may enter file names like myfile.cpp or
767# directories like /usr/src/myproject. Separate the files or directories with
768# spaces.
769# Note: If this tag is empty the current directory is searched.
770
771INPUT = ./
772
773# This tag can be used to specify the character encoding of the source files
774# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
775# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
776# documentation (see: http://www.gnu.org/software/libiconv) for the list of
777# possible encodings.
778# The default value is: UTF-8.
779
780INPUT_ENCODING = UTF-8
781
782# If the value of the INPUT tag contains directories, you can use the
783# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
784# *.h) to filter out the source-files in the directories. If left blank the
785# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
786# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
787# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
788# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
789# *.qsf, *.as and *.js.
790
791FILE_PATTERNS = *.h \
792 *.c \
793 *.txt
794
795# The RECURSIVE tag can be used to specify whether or not subdirectories should
796# be searched for input files as well.
797# The default value is: NO.
798
799RECURSIVE = YES
800
801# The EXCLUDE tag can be used to specify files and/or directories that should be
802# excluded from the INPUT source files. This way you can easily exclude a
803# subdirectory from a directory tree whose root is specified with the INPUT tag.
804#
805# Note that relative paths are relative to the directory from which doxygen is
806# run.
807
808EXCLUDE = Documentation/ \
809 TempLogHostApp/ \
810 TempLogHostApp_Python/
811
812# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
813# directories that are symbolic links (a Unix file system feature) are excluded
814# from the input.
815# The default value is: NO.
816
817EXCLUDE_SYMLINKS = NO
818
819# If the value of the INPUT tag contains directories, you can use the
820# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
821# certain files from those directories.
822#
823# Note that the wildcards are matched against the file with absolute path, so to
824# exclude all test directories for example use the pattern */test/*
825
826EXCLUDE_PATTERNS =
827
828# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
829# (namespaces, classes, functions, etc.) that should be excluded from the
830# output. The symbol name can be a fully qualified name, a word, or if the
831# wildcard * is used, a substring. Examples: ANamespace, AClass,
832# AClass::ANamespace, ANamespace::*Test
833#
834# Note that the wildcards are matched against the file with absolute path, so to
835# exclude all test directories use the pattern */test/*
836
837EXCLUDE_SYMBOLS = __* \
838 INCLUDE_FROM_*
839
840# The EXAMPLE_PATH tag can be used to specify one or more files or directories
841# that contain example code fragments that are included (see the \include
842# command).
843
844EXAMPLE_PATH =
845
846# If the value of the EXAMPLE_PATH tag contains directories, you can use the
847# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
848# *.h) to filter out the source-files in the directories. If left blank all
849# files are included.
850
851EXAMPLE_PATTERNS = *
852
853# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
854# searched for input files to be used with the \include or \dontinclude commands
855# irrespective of the value of the RECURSIVE tag.
856# The default value is: NO.
857
858EXAMPLE_RECURSIVE = NO
859
860# The IMAGE_PATH tag can be used to specify one or more files or directories
861# that contain images that are to be included in the documentation (see the
862# \image command).
863
864IMAGE_PATH =
865
866# The INPUT_FILTER tag can be used to specify a program that doxygen should
867# invoke to filter for each input file. Doxygen will invoke the filter program
868# by executing (via popen()) the command:
869#
870# <filter> <input-file>
871#
872# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
873# name of an input file. Doxygen will then use the output that the filter
874# program writes to standard output. If FILTER_PATTERNS is specified, this tag
875# will be ignored.
876#
877# Note that the filter must not add or remove lines; it is applied before the
878# code is scanned, but not when the output code is generated. If lines are added
879# or removed, the anchors will not be placed correctly.
880
881INPUT_FILTER =
882
883# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
884# basis. Doxygen will compare the file name with each pattern and apply the
885# filter if there is a match. The filters are a list of the form: pattern=filter
886# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
887# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
888# patterns match the file name, INPUT_FILTER is applied.
889
890FILTER_PATTERNS =
891
892# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
893# INPUT_FILTER) will also be used to filter the input files that are used for
894# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
895# The default value is: NO.
896
897FILTER_SOURCE_FILES = NO
898
899# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
900# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
901# it is also possible to disable source filtering for a specific pattern using
902# *.ext= (so without naming a filter).
903# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
904
905FILTER_SOURCE_PATTERNS =
906
907# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
908# is part of the input, its contents will be placed on the main page
909# (index.html). This can be useful if you have a project on for instance GitHub
910# and want to reuse the introduction page also for the doxygen output.
911
912USE_MDFILE_AS_MAINPAGE =
913
914#---------------------------------------------------------------------------
915# Configuration options related to source browsing
916#---------------------------------------------------------------------------
917
918# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
919# generated. Documented entities will be cross-referenced with these sources.
920#
921# Note: To get rid of all source code in the generated output, make sure that
922# also VERBATIM_HEADERS is set to NO.
923# The default value is: NO.
924
925SOURCE_BROWSER = NO
926
927# Setting the INLINE_SOURCES tag to YES will include the body of functions,
928# classes and enums directly into the documentation.
929# The default value is: NO.
930
931INLINE_SOURCES = NO
932
933# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
934# special comment blocks from generated source code fragments. Normal C, C++ and
935# Fortran comments will always remain visible.
936# The default value is: YES.
937
938STRIP_CODE_COMMENTS = YES
939
940# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
941# function all documented functions referencing it will be listed.
942# The default value is: NO.
943
944REFERENCED_BY_RELATION = NO
945
946# If the REFERENCES_RELATION tag is set to YES then for each documented function
947# all documented entities called/used by that function will be listed.
948# The default value is: NO.
949
950REFERENCES_RELATION = NO
951
952# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
953# to YES then the hyperlinks from functions in REFERENCES_RELATION and
954# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
955# link to the documentation.
956# The default value is: YES.
957
958REFERENCES_LINK_SOURCE = NO
959
960# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
961# source code will show a tooltip with additional information such as prototype,
962# brief description and links to the definition and documentation. Since this
963# will make the HTML file larger and loading of large files a bit slower, you
964# can opt to disable this feature.
965# The default value is: YES.
966# This tag requires that the tag SOURCE_BROWSER is set to YES.
967
968SOURCE_TOOLTIPS = YES
969
970# If the USE_HTAGS tag is set to YES then the references to source code will
971# point to the HTML generated by the htags(1) tool instead of doxygen built-in
972# source browser. The htags tool is part of GNU's global source tagging system
973# (see http://www.gnu.org/software/global/global.html). You will need version
974# 4.8.6 or higher.
975#
976# To use it do the following:
977# - Install the latest version of global
978# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
979# - Make sure the INPUT points to the root of the source tree
980# - Run doxygen as normal
981#
982# Doxygen will invoke htags (and that will in turn invoke gtags), so these
983# tools must be available from the command line (i.e. in the search path).
984#
985# The result: instead of the source browser generated by doxygen, the links to
986# source code will now point to the output of htags.
987# The default value is: NO.
988# This tag requires that the tag SOURCE_BROWSER is set to YES.
989
990USE_HTAGS = NO
991
992# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
993# verbatim copy of the header file for each class for which an include is
994# specified. Set to NO to disable this.
995# See also: Section \class.
996# The default value is: YES.
997
998VERBATIM_HEADERS = NO
999
1000# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
1001# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
1002# cost of reduced performance. This can be particularly helpful with template
1003# rich C++ code for which doxygen's built-in parser lacks the necessary type
1004# information.
1005# Note: The availability of this option depends on whether or not doxygen was
1006# compiled with the --with-libclang option.
1007# The default value is: NO.
1008
1009CLANG_ASSISTED_PARSING = NO
1010
1011# If clang assisted parsing is enabled you can provide the compiler with command
1012# line options that you would normally use when invoking the compiler. Note that
1013# the include paths will already be set by doxygen for the files and directories
1014# specified with INPUT and INCLUDE_PATH.
1015# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
1016
1017CLANG_OPTIONS =
1018
1019#---------------------------------------------------------------------------
1020# Configuration options related to the alphabetical class index
1021#---------------------------------------------------------------------------
1022
1023# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
1024# compounds will be generated. Enable this if the project contains a lot of
1025# classes, structs, unions or interfaces.
1026# The default value is: YES.
1027
1028ALPHABETICAL_INDEX = YES
1029
1030# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
1031# which the alphabetical index list will be split.
1032# Minimum value: 1, maximum value: 20, default value: 5.
1033# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1034
1035COLS_IN_ALPHA_INDEX = 5
1036
1037# In case all classes in a project start with a common prefix, all classes will
1038# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
1039# can be used to specify a prefix (or a list of prefixes) that should be ignored
1040# while generating the index headers.
1041# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
1042
1043IGNORE_PREFIX =
1044
1045#---------------------------------------------------------------------------
1046# Configuration options related to the HTML output
1047#---------------------------------------------------------------------------
1048
1049# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
1050# The default value is: YES.
1051
1052GENERATE_HTML = YES
1053
1054# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
1055# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1056# it.
1057# The default directory is: html.
1058# This tag requires that the tag GENERATE_HTML is set to YES.
1059
1060HTML_OUTPUT = html
1061
1062# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
1063# generated HTML page (for example: .htm, .php, .asp).
1064# The default value is: .html.
1065# This tag requires that the tag GENERATE_HTML is set to YES.
1066
1067HTML_FILE_EXTENSION = .html
1068
1069# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
1070# each generated HTML page. If the tag is left blank doxygen will generate a
1071# standard header.
1072#
1073# To get valid HTML the header file that includes any scripts and style sheets
1074# that doxygen needs, which is dependent on the configuration options used (e.g.
1075# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
1076# default header using
1077# doxygen -w html new_header.html new_footer.html new_stylesheet.css
1078# YourConfigFile
1079# and then modify the file new_header.html. See also section "Doxygen usage"
1080# for information on how to generate the default header that doxygen normally
1081# uses.
1082# Note: The header is subject to change so you typically have to regenerate the
1083# default header when upgrading to a newer version of doxygen. For a description
1084# of the possible markers and block names see the documentation.
1085# This tag requires that the tag GENERATE_HTML is set to YES.
1086
1087HTML_HEADER =
1088
1089# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
1090# generated HTML page. If the tag is left blank doxygen will generate a standard
1091# footer. See HTML_HEADER for more information on how to generate a default
1092# footer and what special commands can be used inside the footer. See also
1093# section "Doxygen usage" for information on how to generate the default footer
1094# that doxygen normally uses.
1095# This tag requires that the tag GENERATE_HTML is set to YES.
1096
1097HTML_FOOTER =
1098
1099# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
1100# sheet that is used by each HTML page. It can be used to fine-tune the look of
1101# the HTML output. If left blank doxygen will generate a default style sheet.
1102# See also section "Doxygen usage" for information on how to generate the style
1103# sheet that doxygen normally uses.
1104# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
1105# it is more robust and this tag (HTML_STYLESHEET) will in the future become
1106# obsolete.
1107# This tag requires that the tag GENERATE_HTML is set to YES.
1108
1109HTML_STYLESHEET =
1110
1111# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1112# cascading style sheets that are included after the standard style sheets
1113# created by doxygen. Using this option one can overrule certain style aspects.
1114# This is preferred over using HTML_STYLESHEET since it does not replace the
1115# standard style sheet and is therefore more robust against future updates.
1116# Doxygen will copy the style sheet files to the output directory.
1117# Note: The order of the extra style sheet files is of importance (e.g. the last
1118# style sheet in the list overrules the setting of the previous ones in the
1119# list). For an example see the documentation.
1120# This tag requires that the tag GENERATE_HTML is set to YES.
1121
1122HTML_EXTRA_STYLESHEET =
1123
1124# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
1125# other source files which should be copied to the HTML output directory. Note
1126# that these files will be copied to the base HTML output directory. Use the
1127# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
1128# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
1129# files will be copied as-is; there are no commands or markers available.
1130# This tag requires that the tag GENERATE_HTML is set to YES.
1131
1132HTML_EXTRA_FILES =
1133
1134# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1135# will adjust the colors in the style sheet and background images according to
1136# this color. Hue is specified as an angle on a colorwheel, see
1137# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
1138# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
1139# purple, and 360 is red again.
1140# Minimum value: 0, maximum value: 359, default value: 220.
1141# This tag requires that the tag GENERATE_HTML is set to YES.
1142
1143HTML_COLORSTYLE_HUE = 220
1144
1145# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
1146# in the HTML output. For a value of 0 the output will use grayscales only. A
1147# value of 255 will produce the most vivid colors.
1148# Minimum value: 0, maximum value: 255, default value: 100.
1149# This tag requires that the tag GENERATE_HTML is set to YES.
1150
1151HTML_COLORSTYLE_SAT = 100
1152
1153# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
1154# luminance component of the colors in the HTML output. Values below 100
1155# gradually make the output lighter, whereas values above 100 make the output
1156# darker. The value divided by 100 is the actual gamma applied, so 80 represents
1157# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
1158# change the gamma.
1159# Minimum value: 40, maximum value: 240, default value: 80.
1160# This tag requires that the tag GENERATE_HTML is set to YES.
1161
1162HTML_COLORSTYLE_GAMMA = 80
1163
1164# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
1165# page will contain the date and time when the page was generated. Setting this
1166# to NO can help when comparing the output of multiple runs.
1167# The default value is: YES.
1168# This tag requires that the tag GENERATE_HTML is set to YES.
1169
1170HTML_TIMESTAMP = NO
1171
1172# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
1173# documentation will contain sections that can be hidden and shown after the
1174# page has loaded.
1175# The default value is: NO.
1176# This tag requires that the tag GENERATE_HTML is set to YES.
1177
1178HTML_DYNAMIC_SECTIONS = YES
1179
1180# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
1181# shown in the various tree structured indices initially; the user can expand
1182# and collapse entries dynamically later on. Doxygen will expand the tree to
1183# such a level that at most the specified number of entries are visible (unless
1184# a fully collapsed tree already exceeds this amount). So setting the number of
1185# entries 1 will produce a full collapsed tree by default. 0 is a special value
1186# representing an infinite number of entries and will result in a full expanded
1187# tree by default.
1188# Minimum value: 0, maximum value: 9999, default value: 100.
1189# This tag requires that the tag GENERATE_HTML is set to YES.
1190
1191HTML_INDEX_NUM_ENTRIES = 100
1192
1193# If the GENERATE_DOCSET tag is set to YES, additional index files will be
1194# generated that can be used as input for Apple's Xcode 3 integrated development
1195# environment (see: http://developer.apple.com/tools/xcode/), introduced with
1196# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
1197# Makefile in the HTML output directory. Running make will produce the docset in
1198# that directory and running make install will install the docset in
1199# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
1200# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
1201# for more information.
1202# The default value is: NO.
1203# This tag requires that the tag GENERATE_HTML is set to YES.
1204
1205GENERATE_DOCSET = NO
1206
1207# This tag determines the name of the docset feed. A documentation feed provides
1208# an umbrella under which multiple documentation sets from a single provider
1209# (such as a company or product suite) can be grouped.
1210# The default value is: Doxygen generated docs.
1211# This tag requires that the tag GENERATE_DOCSET is set to YES.
1212
1213DOCSET_FEEDNAME = "Doxygen generated docs"
1214
1215# This tag specifies a string that should uniquely identify the documentation
1216# set bundle. This should be a reverse domain-name style string, e.g.
1217# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
1218# The default value is: org.doxygen.Project.
1219# This tag requires that the tag GENERATE_DOCSET is set to YES.
1220
1221DOCSET_BUNDLE_ID = org.doxygen.Project
1222
1223# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
1224# the documentation publisher. This should be a reverse domain-name style
1225# string, e.g. com.mycompany.MyDocSet.documentation.
1226# The default value is: org.doxygen.Publisher.
1227# This tag requires that the tag GENERATE_DOCSET is set to YES.
1228
1229DOCSET_PUBLISHER_ID = org.doxygen.Publisher
1230
1231# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
1232# The default value is: Publisher.
1233# This tag requires that the tag GENERATE_DOCSET is set to YES.
1234
1235DOCSET_PUBLISHER_NAME = Publisher
1236
1237# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
1238# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
1239# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
1240# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
1241# Windows.
1242#
1243# The HTML Help Workshop contains a compiler that can convert all HTML output
1244# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
1245# files are now used as the Windows 98 help format, and will replace the old
1246# Windows help format (.hlp) on all Windows platforms in the future. Compressed
1247# HTML files also contain an index, a table of contents, and you can search for
1248# words in the documentation. The HTML workshop also contains a viewer for
1249# compressed HTML files.
1250# The default value is: NO.
1251# This tag requires that the tag GENERATE_HTML is set to YES.
1252
1253GENERATE_HTMLHELP = NO
1254
1255# The CHM_FILE tag can be used to specify the file name of the resulting .chm
1256# file. You can add a path in front of the file if the result should not be
1257# written to the html output directory.
1258# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1259
1260CHM_FILE =
1261
1262# The HHC_LOCATION tag can be used to specify the location (absolute path
1263# including file name) of the HTML help compiler (hhc.exe). If non-empty,
1264# doxygen will try to run the HTML help compiler on the generated index.hhp.
1265# The file has to be specified with full path.
1266# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1267
1268HHC_LOCATION =
1269
1270# The GENERATE_CHI flag controls if a separate .chi index file is generated
1271# (YES) or that it should be included in the master .chm file (NO).
1272# The default value is: NO.
1273# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1274
1275GENERATE_CHI = NO
1276
1277# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
1278# and project file content.
1279# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1280
1281CHM_INDEX_ENCODING =
1282
1283# The BINARY_TOC flag controls whether a binary table of contents is generated
1284# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
1285# enables the Previous and Next buttons.
1286# The default value is: NO.
1287# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1288
1289BINARY_TOC = NO
1290
1291# The TOC_EXPAND flag can be set to YES to add extra items for group members to
1292# the table of contents of the HTML help documentation and to the tree view.
1293# The default value is: NO.
1294# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
1295
1296TOC_EXPAND = YES
1297
1298# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
1299# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
1300# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
1301# (.qch) of the generated HTML documentation.
1302# The default value is: NO.
1303# This tag requires that the tag GENERATE_HTML is set to YES.
1304
1305GENERATE_QHP = NO
1306
1307# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
1308# the file name of the resulting .qch file. The path specified is relative to
1309# the HTML output folder.
1310# This tag requires that the tag GENERATE_QHP is set to YES.
1311
1312QCH_FILE =
1313
1314# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
1315# Project output. For more information please see Qt Help Project / Namespace
1316# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
1317# The default value is: org.doxygen.Project.
1318# This tag requires that the tag GENERATE_QHP is set to YES.
1319
1320QHP_NAMESPACE = org.doxygen.Project
1321
1322# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
1323# Help Project output. For more information please see Qt Help Project / Virtual
1324# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
1325# folders).
1326# The default value is: doc.
1327# This tag requires that the tag GENERATE_QHP is set to YES.
1328
1329QHP_VIRTUAL_FOLDER = doc
1330
1331# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
1332# filter to add. For more information please see Qt Help Project / Custom
1333# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1334# filters).
1335# This tag requires that the tag GENERATE_QHP is set to YES.
1336
1337QHP_CUST_FILTER_NAME =
1338
1339# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
1340# custom filter to add. For more information please see Qt Help Project / Custom
1341# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
1342# filters).
1343# This tag requires that the tag GENERATE_QHP is set to YES.
1344
1345QHP_CUST_FILTER_ATTRS =
1346
1347# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
1348# project's filter section matches. Qt Help Project / Filter Attributes (see:
1349# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
1350# This tag requires that the tag GENERATE_QHP is set to YES.
1351
1352QHP_SECT_FILTER_ATTRS =
1353
1354# The QHG_LOCATION tag can be used to specify the location of Qt's
1355# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
1356# generated .qhp file.
1357# This tag requires that the tag GENERATE_QHP is set to YES.
1358
1359QHG_LOCATION =
1360
1361# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
1362# generated, together with the HTML files, they form an Eclipse help plugin. To
1363# install this plugin and make it available under the help contents menu in
1364# Eclipse, the contents of the directory containing the HTML and XML files needs
1365# to be copied into the plugins directory of eclipse. The name of the directory
1366# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
1367# After copying Eclipse needs to be restarted before the help appears.
1368# The default value is: NO.
1369# This tag requires that the tag GENERATE_HTML is set to YES.
1370
1371GENERATE_ECLIPSEHELP = NO
1372
1373# A unique identifier for the Eclipse help plugin. When installing the plugin
1374# the directory name containing the HTML and XML files should also have this
1375# name. Each documentation set should have its own identifier.
1376# The default value is: org.doxygen.Project.
1377# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
1378
1379ECLIPSE_DOC_ID = org.doxygen.Project
1380
1381# If you want full control over the layout of the generated HTML pages it might
1382# be necessary to disable the index and replace it with your own. The
1383# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
1384# of each HTML page. A value of NO enables the index and the value YES disables
1385# it. Since the tabs in the index contain the same information as the navigation
1386# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
1387# The default value is: NO.
1388# This tag requires that the tag GENERATE_HTML is set to YES.
1389
1390DISABLE_INDEX = YES
1391
1392# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
1393# structure should be generated to display hierarchical information. If the tag
1394# value is set to YES, a side panel will be generated containing a tree-like
1395# index structure (just like the one that is generated for HTML Help). For this
1396# to work a browser that supports JavaScript, DHTML, CSS and frames is required
1397# (i.e. any modern browser). Windows users are probably better off using the
1398# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
1399# further fine-tune the look of the index. As an example, the default style
1400# sheet generated by doxygen has an example that shows how to put an image at
1401# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
1402# the same information as the tab index, you could consider setting
1403# DISABLE_INDEX to YES when enabling this option.
1404# The default value is: NO.
1405# This tag requires that the tag GENERATE_HTML is set to YES.
1406
1407GENERATE_TREEVIEW = YES
1408
1409# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
1410# doxygen will group on one line in the generated HTML documentation.
1411#
1412# Note that a value of 0 will completely suppress the enum values from appearing
1413# in the overview section.
1414# Minimum value: 0, maximum value: 20, default value: 4.
1415# This tag requires that the tag GENERATE_HTML is set to YES.
1416
1417ENUM_VALUES_PER_LINE = 1
1418
1419# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
1420# to set the initial width (in pixels) of the frame in which the tree is shown.
1421# Minimum value: 0, maximum value: 1500, default value: 250.
1422# This tag requires that the tag GENERATE_HTML is set to YES.
1423
1424TREEVIEW_WIDTH = 250
1425
1426# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
1427# external symbols imported via tag files in a separate window.
1428# The default value is: NO.
1429# This tag requires that the tag GENERATE_HTML is set to YES.
1430
1431EXT_LINKS_IN_WINDOW = NO
1432
1433# Use this tag to change the font size of LaTeX formulas included as images in
1434# the HTML documentation. When you change the font size after a successful
1435# doxygen run you need to manually remove any form_*.png images from the HTML
1436# output directory to force them to be regenerated.
1437# Minimum value: 8, maximum value: 50, default value: 10.
1438# This tag requires that the tag GENERATE_HTML is set to YES.
1439
1440FORMULA_FONTSIZE = 10
1441
1442# Use the FORMULA_TRANPARENT tag to determine whether or not the images
1443# generated for formulas are transparent PNGs. Transparent PNGs are not
1444# supported properly for IE 6.0, but are supported on all modern browsers.
1445#
1446# Note that when changing this option you need to delete any form_*.png files in
1447# the HTML output directory before the changes have effect.
1448# The default value is: YES.
1449# This tag requires that the tag GENERATE_HTML is set to YES.
1450
1451FORMULA_TRANSPARENT = YES
1452
1453# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
1454# http://www.mathjax.org) which uses client side Javascript for the rendering
1455# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
1456# installed or if you want to formulas look prettier in the HTML output. When
1457# enabled you may also need to install MathJax separately and configure the path
1458# to it using the MATHJAX_RELPATH option.
1459# The default value is: NO.
1460# This tag requires that the tag GENERATE_HTML is set to YES.
1461
1462USE_MATHJAX = NO
1463
1464# When MathJax is enabled you can set the default output format to be used for
1465# the MathJax output. See the MathJax site (see:
1466# http://docs.mathjax.org/en/latest/output.html) for more details.
1467# Possible values are: HTML-CSS (which is slower, but has the best
1468# compatibility), NativeMML (i.e. MathML) and SVG.
1469# The default value is: HTML-CSS.
1470# This tag requires that the tag USE_MATHJAX is set to YES.
1471
1472MATHJAX_FORMAT = HTML-CSS
1473
1474# When MathJax is enabled you need to specify the location relative to the HTML
1475# output directory using the MATHJAX_RELPATH option. The destination directory
1476# should contain the MathJax.js script. For instance, if the mathjax directory
1477# is located at the same level as the HTML output directory, then
1478# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
1479# Content Delivery Network so you can quickly see the result without installing
1480# MathJax. However, it is strongly recommended to install a local copy of
1481# MathJax from http://www.mathjax.org before deployment.
1482# The default value is: http://cdn.mathjax.org/mathjax/latest.
1483# This tag requires that the tag USE_MATHJAX is set to YES.
1484
1485MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
1486
1487# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
1488# extension names that should be enabled during MathJax rendering. For example
1489# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
1490# This tag requires that the tag USE_MATHJAX is set to YES.
1491
1492MATHJAX_EXTENSIONS =
1493
1494# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
1495# of code that will be used on startup of the MathJax code. See the MathJax site
1496# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
1497# example see the documentation.
1498# This tag requires that the tag USE_MATHJAX is set to YES.
1499
1500MATHJAX_CODEFILE =
1501
1502# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
1503# the HTML output. The underlying search engine uses javascript and DHTML and
1504# should work on any modern browser. Note that when using HTML help
1505# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
1506# there is already a search function so this one should typically be disabled.
1507# For large projects the javascript based search engine can be slow, then
1508# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
1509# search using the keyboard; to jump to the search box use <access key> + S
1510# (what the <access key> is depends on the OS and browser, but it is typically
1511# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
1512# key> to jump into the search results window, the results can be navigated
1513# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
1514# the search. The filter options can be selected when the cursor is inside the
1515# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
1516# to select a filter and <Enter> or <escape> to activate or cancel the filter
1517# option.
1518# The default value is: YES.
1519# This tag requires that the tag GENERATE_HTML is set to YES.
1520
1521SEARCHENGINE = NO
1522
1523# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
1524# implemented using a web server instead of a web client using Javascript. There
1525# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
1526# setting. When disabled, doxygen will generate a PHP script for searching and
1527# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
1528# and searching needs to be provided by external tools. See the section
1529# "External Indexing and Searching" for details.
1530# The default value is: NO.
1531# This tag requires that the tag SEARCHENGINE is set to YES.
1532
1533SERVER_BASED_SEARCH = NO
1534
1535# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
1536# script for searching. Instead the search results are written to an XML file
1537# which needs to be processed by an external indexer. Doxygen will invoke an
1538# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
1539# search results.
1540#
1541# Doxygen ships with an example indexer (doxyindexer) and search engine
1542# (doxysearch.cgi) which are based on the open source search engine library
1543# Xapian (see: http://xapian.org/).
1544#
1545# See the section "External Indexing and Searching" for details.
1546# The default value is: NO.
1547# This tag requires that the tag SEARCHENGINE is set to YES.
1548
1549EXTERNAL_SEARCH = NO
1550
1551# The SEARCHENGINE_URL should point to a search engine hosted by a web server
1552# which will return the search results when EXTERNAL_SEARCH is enabled.
1553#
1554# Doxygen ships with an example indexer (doxyindexer) and search engine
1555# (doxysearch.cgi) which are based on the open source search engine library
1556# Xapian (see: http://xapian.org/). See the section "External Indexing and
1557# Searching" for details.
1558# This tag requires that the tag SEARCHENGINE is set to YES.
1559
1560SEARCHENGINE_URL =
1561
1562# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
1563# search data is written to a file for indexing by an external tool. With the
1564# SEARCHDATA_FILE tag the name of this file can be specified.
1565# The default file is: searchdata.xml.
1566# This tag requires that the tag SEARCHENGINE is set to YES.
1567
1568SEARCHDATA_FILE = searchdata.xml
1569
1570# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
1571# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
1572# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
1573# projects and redirect the results back to the right project.
1574# This tag requires that the tag SEARCHENGINE is set to YES.
1575
1576EXTERNAL_SEARCH_ID =
1577
1578# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
1579# projects other than the one defined by this configuration file, but that are
1580# all added to the same external search index. Each project needs to have a
1581# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
1582# to a relative location where the documentation can be found. The format is:
1583# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
1584# This tag requires that the tag SEARCHENGINE is set to YES.
1585
1586EXTRA_SEARCH_MAPPINGS =
1587
1588#---------------------------------------------------------------------------
1589# Configuration options related to the LaTeX output
1590#---------------------------------------------------------------------------
1591
1592# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
1593# The default value is: YES.
1594
1595GENERATE_LATEX = NO
1596
1597# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
1598# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1599# it.
1600# The default directory is: latex.
1601# This tag requires that the tag GENERATE_LATEX is set to YES.
1602
1603LATEX_OUTPUT = latex
1604
1605# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
1606# invoked.
1607#
1608# Note that when enabling USE_PDFLATEX this option is only used for generating
1609# bitmaps for formulas in the HTML output, but not in the Makefile that is
1610# written to the output directory.
1611# The default file is: latex.
1612# This tag requires that the tag GENERATE_LATEX is set to YES.
1613
1614LATEX_CMD_NAME = latex
1615
1616# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
1617# index for LaTeX.
1618# The default file is: makeindex.
1619# This tag requires that the tag GENERATE_LATEX is set to YES.
1620
1621MAKEINDEX_CMD_NAME = makeindex
1622
1623# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
1624# documents. This may be useful for small projects and may help to save some
1625# trees in general.
1626# The default value is: NO.
1627# This tag requires that the tag GENERATE_LATEX is set to YES.
1628
1629COMPACT_LATEX = NO
1630
1631# The PAPER_TYPE tag can be used to set the paper type that is used by the
1632# printer.
1633# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
1634# 14 inches) and executive (7.25 x 10.5 inches).
1635# The default value is: a4.
1636# This tag requires that the tag GENERATE_LATEX is set to YES.
1637
1638PAPER_TYPE = a4wide
1639
1640# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
1641# that should be included in the LaTeX output. To get the times font for
1642# instance you can specify
1643# EXTRA_PACKAGES=times
1644# If left blank no extra packages will be included.
1645# This tag requires that the tag GENERATE_LATEX is set to YES.
1646
1647EXTRA_PACKAGES =
1648
1649# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
1650# generated LaTeX document. The header should contain everything until the first
1651# chapter. If it is left blank doxygen will generate a standard header. See
1652# section "Doxygen usage" for information on how to let doxygen write the
1653# default header to a separate file.
1654#
1655# Note: Only use a user-defined header if you know what you are doing! The
1656# following commands have a special meaning inside the header: $title,
1657# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
1658# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
1659# string, for the replacement values of the other commands the user is referred
1660# to HTML_HEADER.
1661# This tag requires that the tag GENERATE_LATEX is set to YES.
1662
1663LATEX_HEADER =
1664
1665# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
1666# generated LaTeX document. The footer should contain everything after the last
1667# chapter. If it is left blank doxygen will generate a standard footer. See
1668# LATEX_HEADER for more information on how to generate a default footer and what
1669# special commands can be used inside the footer.
1670#
1671# Note: Only use a user-defined footer if you know what you are doing!
1672# This tag requires that the tag GENERATE_LATEX is set to YES.
1673
1674LATEX_FOOTER =
1675
1676# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
1677# LaTeX style sheets that are included after the standard style sheets created
1678# by doxygen. Using this option one can overrule certain style aspects. Doxygen
1679# will copy the style sheet files to the output directory.
1680# Note: The order of the extra style sheet files is of importance (e.g. the last
1681# style sheet in the list overrules the setting of the previous ones in the
1682# list).
1683# This tag requires that the tag GENERATE_LATEX is set to YES.
1684
1685LATEX_EXTRA_STYLESHEET =
1686
1687# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
1688# other source files which should be copied to the LATEX_OUTPUT output
1689# directory. Note that the files will be copied as-is; there are no commands or
1690# markers available.
1691# This tag requires that the tag GENERATE_LATEX is set to YES.
1692
1693LATEX_EXTRA_FILES =
1694
1695# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
1696# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
1697# contain links (just like the HTML output) instead of page references. This
1698# makes the output suitable for online browsing using a PDF viewer.
1699# The default value is: YES.
1700# This tag requires that the tag GENERATE_LATEX is set to YES.
1701
1702PDF_HYPERLINKS = YES
1703
1704# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
1705# the PDF file directly from the LaTeX files. Set this option to YES, to get a
1706# higher quality PDF documentation.
1707# The default value is: YES.
1708# This tag requires that the tag GENERATE_LATEX is set to YES.
1709
1710USE_PDFLATEX = YES
1711
1712# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
1713# command to the generated LaTeX files. This will instruct LaTeX to keep running
1714# if errors occur, instead of asking the user for help. This option is also used
1715# when generating formulas in HTML.
1716# The default value is: NO.
1717# This tag requires that the tag GENERATE_LATEX is set to YES.
1718
1719LATEX_BATCHMODE = NO
1720
1721# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
1722# index chapters (such as File Index, Compound Index, etc.) in the output.
1723# The default value is: NO.
1724# This tag requires that the tag GENERATE_LATEX is set to YES.
1725
1726LATEX_HIDE_INDICES = NO
1727
1728# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
1729# code with syntax highlighting in the LaTeX output.
1730#
1731# Note that which sources are shown also depends on other settings such as
1732# SOURCE_BROWSER.
1733# The default value is: NO.
1734# This tag requires that the tag GENERATE_LATEX is set to YES.
1735
1736LATEX_SOURCE_CODE = NO
1737
1738# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
1739# bibliography, e.g. plainnat, or ieeetr. See
1740# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
1741# The default value is: plain.
1742# This tag requires that the tag GENERATE_LATEX is set to YES.
1743
1744LATEX_BIB_STYLE = plain
1745
1746#---------------------------------------------------------------------------
1747# Configuration options related to the RTF output
1748#---------------------------------------------------------------------------
1749
1750# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
1751# RTF output is optimized for Word 97 and may not look too pretty with other RTF
1752# readers/editors.
1753# The default value is: NO.
1754
1755GENERATE_RTF = NO
1756
1757# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
1758# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1759# it.
1760# The default directory is: rtf.
1761# This tag requires that the tag GENERATE_RTF is set to YES.
1762
1763RTF_OUTPUT = rtf
1764
1765# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
1766# documents. This may be useful for small projects and may help to save some
1767# trees in general.
1768# The default value is: NO.
1769# This tag requires that the tag GENERATE_RTF is set to YES.
1770
1771COMPACT_RTF = NO
1772
1773# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
1774# contain hyperlink fields. The RTF file will contain links (just like the HTML
1775# output) instead of page references. This makes the output suitable for online
1776# browsing using Word or some other Word compatible readers that support those
1777# fields.
1778#
1779# Note: WordPad (write) and others do not support links.
1780# The default value is: NO.
1781# This tag requires that the tag GENERATE_RTF is set to YES.
1782
1783RTF_HYPERLINKS = NO
1784
1785# Load stylesheet definitions from file. Syntax is similar to doxygen's config
1786# file, i.e. a series of assignments. You only have to provide replacements,
1787# missing definitions are set to their default value.
1788#
1789# See also section "Doxygen usage" for information on how to generate the
1790# default style sheet that doxygen normally uses.
1791# This tag requires that the tag GENERATE_RTF is set to YES.
1792
1793RTF_STYLESHEET_FILE =
1794
1795# Set optional variables used in the generation of an RTF document. Syntax is
1796# similar to doxygen's config file. A template extensions file can be generated
1797# using doxygen -e rtf extensionFile.
1798# This tag requires that the tag GENERATE_RTF is set to YES.
1799
1800RTF_EXTENSIONS_FILE =
1801
1802# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
1803# with syntax highlighting in the RTF output.
1804#
1805# Note that which sources are shown also depends on other settings such as
1806# SOURCE_BROWSER.
1807# The default value is: NO.
1808# This tag requires that the tag GENERATE_RTF is set to YES.
1809
1810RTF_SOURCE_CODE = NO
1811
1812#---------------------------------------------------------------------------
1813# Configuration options related to the man page output
1814#---------------------------------------------------------------------------
1815
1816# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
1817# classes and files.
1818# The default value is: NO.
1819
1820GENERATE_MAN = NO
1821
1822# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
1823# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1824# it. A directory man3 will be created inside the directory specified by
1825# MAN_OUTPUT.
1826# The default directory is: man.
1827# This tag requires that the tag GENERATE_MAN is set to YES.
1828
1829MAN_OUTPUT = man
1830
1831# The MAN_EXTENSION tag determines the extension that is added to the generated
1832# man pages. In case the manual section does not start with a number, the number
1833# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
1834# optional.
1835# The default value is: .3.
1836# This tag requires that the tag GENERATE_MAN is set to YES.
1837
1838MAN_EXTENSION = .3
1839
1840# The MAN_SUBDIR tag determines the name of the directory created within
1841# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
1842# MAN_EXTENSION with the initial . removed.
1843# This tag requires that the tag GENERATE_MAN is set to YES.
1844
1845MAN_SUBDIR =
1846
1847# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
1848# will generate one additional man file for each entity documented in the real
1849# man page(s). These additional files only source the real man page, but without
1850# them the man command would be unable to find the correct page.
1851# The default value is: NO.
1852# This tag requires that the tag GENERATE_MAN is set to YES.
1853
1854MAN_LINKS = NO
1855
1856#---------------------------------------------------------------------------
1857# Configuration options related to the XML output
1858#---------------------------------------------------------------------------
1859
1860# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
1861# captures the structure of the code including all documentation.
1862# The default value is: NO.
1863
1864GENERATE_XML = NO
1865
1866# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
1867# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
1868# it.
1869# The default directory is: xml.
1870# This tag requires that the tag GENERATE_XML is set to YES.
1871
1872XML_OUTPUT = xml
1873
1874# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
1875# listings (including syntax highlighting and cross-referencing information) to
1876# the XML output. Note that enabling this will significantly increase the size
1877# of the XML output.
1878# The default value is: YES.
1879# This tag requires that the tag GENERATE_XML is set to YES.
1880
1881XML_PROGRAMLISTING = YES
1882
1883#---------------------------------------------------------------------------
1884# Configuration options related to the DOCBOOK output
1885#---------------------------------------------------------------------------
1886
1887# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
1888# that can be used to generate PDF.
1889# The default value is: NO.
1890
1891GENERATE_DOCBOOK = NO
1892
1893# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
1894# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
1895# front of it.
1896# The default directory is: docbook.
1897# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1898
1899DOCBOOK_OUTPUT = docbook
1900
1901# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
1902# program listings (including syntax highlighting and cross-referencing
1903# information) to the DOCBOOK output. Note that enabling this will significantly
1904# increase the size of the DOCBOOK output.
1905# The default value is: NO.
1906# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
1907
1908DOCBOOK_PROGRAMLISTING = NO
1909
1910#---------------------------------------------------------------------------
1911# Configuration options for the AutoGen Definitions output
1912#---------------------------------------------------------------------------
1913
1914# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
1915# AutoGen Definitions (see http://autogen.sf.net) file that captures the
1916# structure of the code including all documentation. Note that this feature is
1917# still experimental and incomplete at the moment.
1918# The default value is: NO.
1919
1920GENERATE_AUTOGEN_DEF = NO
1921
1922#---------------------------------------------------------------------------
1923# Configuration options related to the Perl module output
1924#---------------------------------------------------------------------------
1925
1926# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
1927# file that captures the structure of the code including all documentation.
1928#
1929# Note that this feature is still experimental and incomplete at the moment.
1930# The default value is: NO.
1931
1932GENERATE_PERLMOD = NO
1933
1934# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
1935# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
1936# output from the Perl module output.
1937# The default value is: NO.
1938# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1939
1940PERLMOD_LATEX = NO
1941
1942# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
1943# formatted so it can be parsed by a human reader. This is useful if you want to
1944# understand what is going on. On the other hand, if this tag is set to NO, the
1945# size of the Perl module output will be much smaller and Perl will parse it
1946# just the same.
1947# The default value is: YES.
1948# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1949
1950PERLMOD_PRETTY = YES
1951
1952# The names of the make variables in the generated doxyrules.make file are
1953# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
1954# so different doxyrules.make files included by the same Makefile don't
1955# overwrite each other's variables.
1956# This tag requires that the tag GENERATE_PERLMOD is set to YES.
1957
1958PERLMOD_MAKEVAR_PREFIX =
1959
1960#---------------------------------------------------------------------------
1961# Configuration options related to the preprocessor
1962#---------------------------------------------------------------------------
1963
1964# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
1965# C-preprocessor directives found in the sources and include files.
1966# The default value is: YES.
1967
1968ENABLE_PREPROCESSING = YES
1969
1970# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
1971# in the source code. If set to NO, only conditional compilation will be
1972# performed. Macro expansion can be done in a controlled way by setting
1973# EXPAND_ONLY_PREDEF to YES.
1974# The default value is: NO.
1975# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1976
1977MACRO_EXPANSION = YES
1978
1979# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
1980# the macro expansion is limited to the macros specified with the PREDEFINED and
1981# EXPAND_AS_DEFINED tags.
1982# The default value is: NO.
1983# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1984
1985EXPAND_ONLY_PREDEF = YES
1986
1987# If the SEARCH_INCLUDES tag is set to YES, the include files in the
1988# INCLUDE_PATH will be searched if a #include is found.
1989# The default value is: YES.
1990# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
1991
1992SEARCH_INCLUDES = YES
1993
1994# The INCLUDE_PATH tag can be used to specify one or more directories that
1995# contain include files that are not input files but should be processed by the
1996# preprocessor.
1997# This tag requires that the tag SEARCH_INCLUDES is set to YES.
1998
1999INCLUDE_PATH =
2000
2001# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
2002# patterns (like *.h and *.hpp) to filter out the header-files in the
2003# directories. If left blank, the patterns specified with FILE_PATTERNS will be
2004# used.
2005# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2006
2007INCLUDE_FILE_PATTERNS =
2008
2009# The PREDEFINED tag can be used to specify one or more macro names that are
2010# defined before the preprocessor is started (similar to the -D option of e.g.
2011# gcc). The argument of the tag is a list of macros of the form: name or
2012# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
2013# is assumed. To prevent a macro definition from being undefined via #undef or
2014# recursively expanded use the := operator instead of the = operator.
2015# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2016
2017PREDEFINED = __DOXYGEN__ \
2018 PROGMEM
2019
2020# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
2021# tag can be used to specify a list of macro names that should be expanded. The
2022# macro definition that is found in the sources will be used. Use the PREDEFINED
2023# tag if you want to use a different macro definition that overrules the
2024# definition found in the source code.
2025# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2026
2027EXPAND_AS_DEFINED =
2028
2029# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
2030# remove all references to function-like macros that are alone on a line, have
2031# an all uppercase name, and do not end with a semicolon. Such function macros
2032# are typically used for boiler-plate code, and will confuse the parser if not
2033# removed.
2034# The default value is: YES.
2035# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
2036
2037SKIP_FUNCTION_MACROS = YES
2038
2039#---------------------------------------------------------------------------
2040# Configuration options related to external references
2041#---------------------------------------------------------------------------
2042
2043# The TAGFILES tag can be used to specify one or more tag files. For each tag
2044# file the location of the external documentation should be added. The format of
2045# a tag file without this location is as follows:
2046# TAGFILES = file1 file2 ...
2047# Adding location for the tag files is done as follows:
2048# TAGFILES = file1=loc1 "file2 = loc2" ...
2049# where loc1 and loc2 can be relative or absolute paths or URLs. See the
2050# section "Linking to external documentation" for more information about the use
2051# of tag files.
2052# Note: Each tag file must have a unique name (where the name does NOT include
2053# the path). If a tag file is not located in the directory in which doxygen is
2054# run, you must also specify the path to the tagfile here.
2055
2056TAGFILES =
2057
2058# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
2059# tag file that is based on the input files it reads. See section "Linking to
2060# external documentation" for more information about the usage of tag files.
2061
2062GENERATE_TAGFILE =
2063
2064# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
2065# the class index. If set to NO, only the inherited external classes will be
2066# listed.
2067# The default value is: NO.
2068
2069ALLEXTERNALS = NO
2070
2071# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
2072# in the modules index. If set to NO, only the current project's groups will be
2073# listed.
2074# The default value is: YES.
2075
2076EXTERNAL_GROUPS = YES
2077
2078# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
2079# the related pages index. If set to NO, only the current project's pages will
2080# be listed.
2081# The default value is: YES.
2082
2083EXTERNAL_PAGES = YES
2084
2085# The PERL_PATH should be the absolute path and name of the perl script
2086# interpreter (i.e. the result of 'which perl').
2087# The default file (with absolute path) is: /usr/bin/perl.
2088
2089PERL_PATH = /usr/bin/perl
2090
2091#---------------------------------------------------------------------------
2092# Configuration options related to the dot tool
2093#---------------------------------------------------------------------------
2094
2095# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
2096# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
2097# NO turns the diagrams off. Note that this option also works with HAVE_DOT
2098# disabled, but it is recommended to install and use dot, since it yields more
2099# powerful graphs.
2100# The default value is: YES.
2101
2102CLASS_DIAGRAMS = NO
2103
2104# You can define message sequence charts within doxygen comments using the \msc
2105# command. Doxygen will then run the mscgen tool (see:
2106# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
2107# documentation. The MSCGEN_PATH tag allows you to specify the directory where
2108# the mscgen tool resides. If left empty the tool is assumed to be found in the
2109# default search path.
2110
2111MSCGEN_PATH =
2112
2113# You can include diagrams made with dia in doxygen documentation. Doxygen will
2114# then run dia to produce the diagram and insert it in the documentation. The
2115# DIA_PATH tag allows you to specify the directory where the dia binary resides.
2116# If left empty dia is assumed to be found in the default search path.
2117
2118DIA_PATH =
2119
2120# If set to YES the inheritance and collaboration graphs will hide inheritance
2121# and usage relations if the target is undocumented or is not a class.
2122# The default value is: YES.
2123
2124HIDE_UNDOC_RELATIONS = YES
2125
2126# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
2127# available from the path. This tool is part of Graphviz (see:
2128# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
2129# Bell Labs. The other options in this section have no effect if this option is
2130# set to NO
2131# The default value is: NO.
2132
2133HAVE_DOT = NO
2134
2135# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
2136# to run in parallel. When set to 0 doxygen will base this on the number of
2137# processors available in the system. You can set it explicitly to a value
2138# larger than 0 to get control over the balance between CPU load and processing
2139# speed.
2140# Minimum value: 0, maximum value: 32, default value: 0.
2141# This tag requires that the tag HAVE_DOT is set to YES.
2142
2143DOT_NUM_THREADS = 0
2144
2145# When you want a differently looking font in the dot files that doxygen
2146# generates you can specify the font name using DOT_FONTNAME. You need to make
2147# sure dot is able to find the font, which can be done by putting it in a
2148# standard location or by setting the DOTFONTPATH environment variable or by
2149# setting DOT_FONTPATH to the directory containing the font.
2150# The default value is: Helvetica.
2151# This tag requires that the tag HAVE_DOT is set to YES.
2152
2153DOT_FONTNAME =
2154
2155# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
2156# dot graphs.
2157# Minimum value: 4, maximum value: 24, default value: 10.
2158# This tag requires that the tag HAVE_DOT is set to YES.
2159
2160DOT_FONTSIZE = 10
2161
2162# By default doxygen will tell dot to use the default font as specified with
2163# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
2164# the path where dot can find it using this tag.
2165# This tag requires that the tag HAVE_DOT is set to YES.
2166
2167DOT_FONTPATH =
2168
2169# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
2170# each documented class showing the direct and indirect inheritance relations.
2171# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
2172# The default value is: YES.
2173# This tag requires that the tag HAVE_DOT is set to YES.
2174
2175CLASS_GRAPH = NO
2176
2177# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
2178# graph for each documented class showing the direct and indirect implementation
2179# dependencies (inheritance, containment, and class references variables) of the
2180# class with other documented classes.
2181# The default value is: YES.
2182# This tag requires that the tag HAVE_DOT is set to YES.
2183
2184COLLABORATION_GRAPH = NO
2185
2186# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
2187# groups, showing the direct groups dependencies.
2188# The default value is: YES.
2189# This tag requires that the tag HAVE_DOT is set to YES.
2190
2191GROUP_GRAPHS = NO
2192
2193# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
2194# collaboration diagrams in a style similar to the OMG's Unified Modeling
2195# Language.
2196# The default value is: NO.
2197# This tag requires that the tag HAVE_DOT is set to YES.
2198
2199UML_LOOK = NO
2200
2201# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
2202# class node. If there are many fields or methods and many nodes the graph may
2203# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
2204# number of items for each type to make the size more manageable. Set this to 0
2205# for no limit. Note that the threshold may be exceeded by 50% before the limit
2206# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
2207# but if the number exceeds 15, the total amount of fields shown is limited to
2208# 10.
2209# Minimum value: 0, maximum value: 100, default value: 10.
2210# This tag requires that the tag HAVE_DOT is set to YES.
2211
2212UML_LIMIT_NUM_FIELDS = 10
2213
2214# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
2215# collaboration graphs will show the relations between templates and their
2216# instances.
2217# The default value is: NO.
2218# This tag requires that the tag HAVE_DOT is set to YES.
2219
2220TEMPLATE_RELATIONS = NO
2221
2222# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
2223# YES then doxygen will generate a graph for each documented file showing the
2224# direct and indirect include dependencies of the file with other documented
2225# files.
2226# The default value is: YES.
2227# This tag requires that the tag HAVE_DOT is set to YES.
2228
2229INCLUDE_GRAPH = NO
2230
2231# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
2232# set to YES then doxygen will generate a graph for each documented file showing
2233# the direct and indirect include dependencies of the file with other documented
2234# files.
2235# The default value is: YES.
2236# This tag requires that the tag HAVE_DOT is set to YES.
2237
2238INCLUDED_BY_GRAPH = NO
2239
2240# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
2241# dependency graph for every global function or class method.
2242#
2243# Note that enabling this option will significantly increase the time of a run.
2244# So in most cases it will be better to enable call graphs for selected
2245# functions only using the \callgraph command.
2246# The default value is: NO.
2247# This tag requires that the tag HAVE_DOT is set to YES.
2248
2249CALL_GRAPH = NO
2250
2251# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
2252# dependency graph for every global function or class method.
2253#
2254# Note that enabling this option will significantly increase the time of a run.
2255# So in most cases it will be better to enable caller graphs for selected
2256# functions only using the \callergraph command.
2257# The default value is: NO.
2258# This tag requires that the tag HAVE_DOT is set to YES.
2259
2260CALLER_GRAPH = NO
2261
2262# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
2263# hierarchy of all classes instead of a textual one.
2264# The default value is: YES.
2265# This tag requires that the tag HAVE_DOT is set to YES.
2266
2267GRAPHICAL_HIERARCHY = NO
2268
2269# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
2270# dependencies a directory has on other directories in a graphical way. The
2271# dependency relations are determined by the #include relations between the
2272# files in the directories.
2273# The default value is: YES.
2274# This tag requires that the tag HAVE_DOT is set to YES.
2275
2276DIRECTORY_GRAPH = NO
2277
2278# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
2279# generated by dot.
2280# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
2281# to make the SVG files visible in IE 9+ (other browsers do not have this
2282# requirement).
2283# Possible values are: png, jpg, gif and svg.
2284# The default value is: png.
2285# This tag requires that the tag HAVE_DOT is set to YES.
2286
2287DOT_IMAGE_FORMAT = png
2288
2289# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
2290# enable generation of interactive SVG images that allow zooming and panning.
2291#
2292# Note that this requires a modern browser other than Internet Explorer. Tested
2293# and working are Firefox, Chrome, Safari, and Opera.
2294# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
2295# the SVG files visible. Older versions of IE do not have SVG support.
2296# The default value is: NO.
2297# This tag requires that the tag HAVE_DOT is set to YES.
2298
2299INTERACTIVE_SVG = NO
2300
2301# The DOT_PATH tag can be used to specify the path where the dot tool can be
2302# found. If left blank, it is assumed the dot tool can be found in the path.
2303# This tag requires that the tag HAVE_DOT is set to YES.
2304
2305DOT_PATH =
2306
2307# The DOTFILE_DIRS tag can be used to specify one or more directories that
2308# contain dot files that are included in the documentation (see the \dotfile
2309# command).
2310# This tag requires that the tag HAVE_DOT is set to YES.
2311
2312DOTFILE_DIRS =
2313
2314# The MSCFILE_DIRS tag can be used to specify one or more directories that
2315# contain msc files that are included in the documentation (see the \mscfile
2316# command).
2317
2318MSCFILE_DIRS =
2319
2320# The DIAFILE_DIRS tag can be used to specify one or more directories that
2321# contain dia files that are included in the documentation (see the \diafile
2322# command).
2323
2324DIAFILE_DIRS =
2325
2326# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
2327# path where java can find the plantuml.jar file. If left blank, it is assumed
2328# PlantUML is not used or called during a preprocessing step. Doxygen will
2329# generate a warning when it encounters a \startuml command in this case and
2330# will not generate output for the diagram.
2331
2332PLANTUML_JAR_PATH =
2333
2334# When using plantuml, the specified paths are searched for files specified by
2335# the !include statement in a plantuml block.
2336
2337PLANTUML_INCLUDE_PATH =
2338
2339# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
2340# that will be shown in the graph. If the number of nodes in a graph becomes
2341# larger than this value, doxygen will truncate the graph, which is visualized
2342# by representing a node as a red box. Note that doxygen if the number of direct
2343# children of the root node in a graph is already larger than
2344# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
2345# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
2346# Minimum value: 0, maximum value: 10000, default value: 50.
2347# This tag requires that the tag HAVE_DOT is set to YES.
2348
2349DOT_GRAPH_MAX_NODES = 15
2350
2351# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
2352# generated by dot. A depth value of 3 means that only nodes reachable from the
2353# root by following a path via at most 3 edges will be shown. Nodes that lay
2354# further from the root node will be omitted. Note that setting this option to 1
2355# or 2 may greatly reduce the computation time needed for large code bases. Also
2356# note that the size of a graph can be further restricted by
2357# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
2358# Minimum value: 0, maximum value: 1000, default value: 0.
2359# This tag requires that the tag HAVE_DOT is set to YES.
2360
2361MAX_DOT_GRAPH_DEPTH = 2
2362
2363# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
2364# background. This is disabled by default, because dot on Windows does not seem
2365# to support this out of the box.
2366#
2367# Warning: Depending on the platform used, enabling this option may lead to
2368# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
2369# read).
2370# The default value is: NO.
2371# This tag requires that the tag HAVE_DOT is set to YES.
2372
2373DOT_TRANSPARENT = YES
2374
2375# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
2376# files in one run (i.e. multiple -o and -T options on the command line). This
2377# makes dot run faster, but since only newer versions of dot (>1.8.10) support
2378# this, this feature is disabled by default.
2379# The default value is: NO.
2380# This tag requires that the tag HAVE_DOT is set to YES.
2381
2382DOT_MULTI_TARGETS = NO
2383
2384# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
2385# explaining the meaning of the various boxes and arrows in the dot generated
2386# graphs.
2387# The default value is: YES.
2388# This tag requires that the tag HAVE_DOT is set to YES.
2389
2390GENERATE_LEGEND = YES
2391
2392# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
2393# files that are used to generate the various graphs.
2394# The default value is: YES.
2395# This tag requires that the tag HAVE_DOT is set to YES.
2396
2397DOT_CLEANUP = YES
diff --git a/lib/lufa/Projects/TempDataLogger/makefile b/lib/lufa/Projects/TempDataLogger/makefile
new file mode 100644
index 000000000..fea6fea91
--- /dev/null
+++ b/lib/lufa/Projects/TempDataLogger/makefile
@@ -0,0 +1,44 @@
1#
2# LUFA Library
3# Copyright (C) Dean Camera, 2017.
4#
5# dean [at] fourwalledcubicle [dot] com
6# www.lufa-lib.org
7#
8# --------------------------------------
9# LUFA Project Makefile.
10# --------------------------------------
11
12# Run "make help" for target help.
13
14MCU = at90usb1287
15ARCH = AVR8
16BOARD = USBKEY
17F_CPU = 8000000
18F_USB = $(F_CPU)
19OPTIMIZATION = s
20TARGET = TempDataLogger
21SRC = $(TARGET).c Descriptors.c Lib/DataflashManager.c Lib/RTC.c Lib/SCSI.c Lib/FATFs/diskio.c Lib/FATFs/ff.c \
22 $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) $(LUFA_SRC_SERIAL) $(LUFA_SRC_TWI) $(LUFA_SRC_TEMPERATURE)
23LUFA_PATH = ../../LUFA
24CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
25LD_FLAGS =
26
27# Default target
28all:
29
30# Include LUFA-specific DMBS extension modules
31DMBS_LUFA_PATH ?= $(LUFA_PATH)/Build/LUFA
32include $(DMBS_LUFA_PATH)/lufa-sources.mk
33include $(DMBS_LUFA_PATH)/lufa-gcc.mk
34
35# Include common DMBS build system modules
36DMBS_PATH ?= $(LUFA_PATH)/Build/DMBS/DMBS
37include $(DMBS_PATH)/core.mk
38include $(DMBS_PATH)/cppcheck.mk
39include $(DMBS_PATH)/doxygen.mk
40include $(DMBS_PATH)/dfu.mk
41include $(DMBS_PATH)/gcc.mk
42include $(DMBS_PATH)/hid.mk
43include $(DMBS_PATH)/avrdude.mk
44include $(DMBS_PATH)/atprogram.mk