Browse Source

trailing spaces cleanup (#2659)

sergio 5 years ago
parent
commit
d77666c0e8
100 changed files with 9217 additions and 24704 deletions
  1. 7 7
      .gdbinit
  2. 1 1
      .github/ISSUE_TEMPLATE.md
  3. 1 1
      CONTRIBUTING.md
  4. 1 1
      README.md
  5. 1 1
      app/coap/Makefile
  6. 8 8
      app/coap/coap.h
  7. 1 1
      app/coap/coap_io.c
  8. 1 1
      app/coap/coap_io.h
  9. 2 2
      app/coap/coap_timer.c
  10. 5 5
      app/coap/endpoints.c
  11. 3 3
      app/coap/hash.c
  12. 1 1
      app/coap/node.c
  13. 1 1
      app/coap/pdu.c
  14. 2 2
      app/coap/str.c
  15. 1 1
      app/coap/str.h
  16. 38 38
      app/coap/uri.c
  17. 28 28
      app/coap/uri.h
  18. 1 1
      app/crypto/digests.c
  19. 4 4
      app/crypto/sha2.c
  20. 1 1
      app/dht/Makefile
  21. 319 319
      app/dht/dht.c
  22. 69 69
      app/dht/dht.h
  23. 1 1
      app/driver/Makefile
  24. 3 3
      app/driver/pwm.c
  25. 2 2
      app/driver/readline.c
  26. 8 8
      app/driver/rotary.c
  27. 61 61
      app/driver/spi.c
  28. 13 13
      app/driver/switec.c
  29. 3 3
      app/driver/uart.c
  30. 1 1
      app/esp-gdbstub/Makefile
  31. 4 4
      app/esp-gdbstub/gdbstub-cfg.h
  32. 5 5
      app/esp-gdbstub/gdbstub-entry.S
  33. 10 10
      app/esp-gdbstub/gdbstub.c
  34. 52 52
      app/fatfs/Makefile
  35. 119 119
      app/fatfs/diskio.c
  36. 77 77
      app/fatfs/diskio.h
  37. 6554 6554
      app/fatfs/ff.c
  38. 405 405
      app/fatfs/ff.h
  39. 290 290
      app/fatfs/ffconf.h
  40. 170 170
      app/fatfs/ffsystem.c
  41. 0 15487
      app/fatfs/ffunicode.c
  42. 1 1
      app/http/Makefile
  43. 11 11
      app/http/httpclient.c
  44. 24 24
      app/include/arch/cc.h
  45. 24 24
      app/include/arch/perf.h
  46. 1 1
      app/include/driver/spi.h
  47. 1 1
      app/include/driver/uart.h
  48. 14 14
      app/include/lwip/api.h
  49. 14 14
      app/include/lwip/api_msg.h
  50. 117 117
      app/include/lwip/app/dhcpserver.h
  51. 12 12
      app/include/lwip/app/espconn.h
  52. 58 58
      app/include/lwip/app/espconn_tcp.h
  53. 64 64
      app/include/lwip/app/espconn_udp.h
  54. 15 15
      app/include/lwip/arch.h
  55. 1 1
      app/include/lwip/autoip.h
  56. 16 16
      app/include/lwip/debug.h
  57. 16 16
      app/include/lwip/def.h
  58. 9 9
      app/include/lwip/dhcp.h
  59. 1 1
      app/include/lwip/dns.h
  60. 14 14
      app/include/lwip/err.h
  61. 14 14
      app/include/lwip/icmp.h
  62. 23 23
      app/include/lwip/igmp.h
  63. 14 14
      app/include/lwip/inet.h
  64. 14 14
      app/include/lwip/inet_chksum.h
  65. 14 14
      app/include/lwip/init.h
  66. 15 15
      app/include/lwip/ip.h
  67. 14 14
      app/include/lwip/ip_frag.h
  68. 14 14
      app/include/lwip/mem.h
  69. 14 14
      app/include/lwip/memp.h
  70. 1 1
      app/include/lwip/memp_std.h
  71. 14 14
      app/include/lwip/netbuf.h
  72. 12 12
      app/include/lwip/netdb.h
  73. 15 15
      app/include/lwip/netif.h
  74. 13 13
      app/include/lwip/netifapi.h
  75. 30 30
      app/include/lwip/opt.h
  76. 17 17
      app/include/lwip/pbuf.h
  77. 44 44
      app/include/lwip/puck_def.h
  78. 24 24
      app/include/lwip/sio.h
  79. 27 27
      app/include/lwip/snmp.h
  80. 1 1
      app/include/lwip/snmp_asn1.h
  81. 4 4
      app/include/lwip/snmp_structs.h
  82. 15 15
      app/include/lwip/sockets.h
  83. 15 15
      app/include/lwip/stats.h
  84. 16 16
      app/include/lwip/sys.h
  85. 25 25
      app/include/lwip/tcp.h
  86. 17 17
      app/include/lwip/tcp_impl.h
  87. 14 14
      app/include/lwip/tcpip.h
  88. 14 14
      app/include/lwip/timers.h
  89. 15 15
      app/include/lwip/udp.h
  90. 31 31
      app/include/lwipopts.h
  91. 14 14
      app/include/netif/etharp.h
  92. 2 2
      app/include/netif/ppp_oe.h
  93. 2 2
      app/include/netif/wlan_lwip_if.h
  94. 3 3
      app/include/rtc/rtctime_internal.h
  95. 1 1
      app/include/sys/espconn_mbedtls.h
  96. 1 1
      app/include/sys/socket.h
  97. 2 2
      app/include/u8g2_displays.h
  98. 1 1
      app/include/u8g2_fonts.h
  99. 3 3
      app/include/user_config.h
  100. 1 1
      app/include/user_mbedtls.h

+ 7 - 7
.gdbinit

@@ -1,9 +1,9 @@
 #
-# This is very much a work in progress to show how we can use macros to make the 
-# GDB interface a lot more useable.  For example the next / step commands only 
-# work if the stepper doesn't leave the current scope.  Beyond that you have a 
-# single hardware breakpoint which can be used as an hb or a wa.  You have to 
-# remember to delete the previous one, so the br macro does this for you. 
+# This is very much a work in progress to show how we can use macros to make the
+# GDB interface a lot more useable.  For example the next / step commands only
+# work if the stepper doesn't leave the current scope.  Beyond that you have a
+# single hardware breakpoint which can be used as an hb or a wa.  You have to
+# remember to delete the previous one, so the br macro does this for you.
 #
 file app/.output/eagle/debug/image/eagle.app.v6.out
 #set remotedebug 1
@@ -16,12 +16,12 @@ target remote /dev/ttyUSB0
 
 set confirm off
 set print null-stop
-define br 
+define br
   d
   hb $arg0
 end
 
-define upto 
+define upto
   d
   hb $arg0
   c

+ 1 - 1
.github/ISSUE_TEMPLATE.md

@@ -15,7 +15,7 @@ Provide a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/h
 Which branch are you on? If you know the Git revision then add it here as well.
 
 ### Hardware
-Describe which ESP8266 device you use and document any special hardware setup 
+Describe which ESP8266 device you use and document any special hardware setup
 required to reproduce the problem.
 
 8<------------------------ END BUG REPORT -------------------------------------

+ 1 - 1
CONTRIBUTING.md

@@ -65,7 +65,7 @@ Avoid intermediate merge commits. [Rebase](https://www.atlassian.com/git/tutoria
 
 This is just one way of doing things. If you're proficient in Git matters you're free to choose your own. If you want to read more then the [GitHub chapter in the Git book](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project#The-GitHub-Flow) is a way to start. [GitHub's own documentation](https://help.github.com/categories/collaborating-with-issues-and-pull-requests/) contains a wealth of information as well.
 
-As a Windows or Mac user you could also resort to [GitHub Desktop](https://desktop.github.com/). It's a mature GUI application that supports most of the tasks outlined above. 
+As a Windows or Mac user you could also resort to [GitHub Desktop](https://desktop.github.com/). It's a mature GUI application that supports most of the tasks outlined above.
 
 ### Keeping your fork in sync
 You need to sync your fork with the NodeMCU upstream repository from time to time, latest before you rebase (see flow above).

+ 1 - 1
README.md

@@ -46,7 +46,7 @@ wifi.sta.config{ssid="SSID", pwd="password"}
 
 # Documentation
 
-The entire [NodeMCU documentation](https://nodemcu.readthedocs.io) is maintained right in this repository at [/docs](docs). The fact that the API documentation is maintained in the same repository as the code that *provides* the API ensures consistency between the two. With every commit the documentation is rebuilt by Read the Docs and thus transformed from terse Markdown into a nicely browsable HTML site at [https://nodemcu.readthedocs.io](https://nodemcu.readthedocs.io). 
+The entire [NodeMCU documentation](https://nodemcu.readthedocs.io) is maintained right in this repository at [/docs](docs). The fact that the API documentation is maintained in the same repository as the code that *provides* the API ensures consistency between the two. With every commit the documentation is rebuilt by Read the Docs and thus transformed from terse Markdown into a nicely browsable HTML site at [https://nodemcu.readthedocs.io](https://nodemcu.readthedocs.io).
 
 - How to [build the firmware](https://nodemcu.readthedocs.io/en/master/en/build/)
 - How to [flash the firmware](https://nodemcu.readthedocs.io/en/master/en/flash/)

+ 1 - 1
app/coap/Makefile

@@ -22,7 +22,7 @@ endif
 #   makefile at its root level - these are then overridden
 #   for a subtree within the makefile rooted therein
 #
-#DEFINES += 
+#DEFINES +=
 
 #############################################################
 # Recursion Magic - Don't touch this!!

+ 8 - 8
app/coap/coap.h

@@ -24,8 +24,8 @@ typedef struct
     uint8_t ver;                /* CoAP version number */
     uint8_t t;                  /* CoAP Message Type */
     uint8_t tkl;                /* Token length: indicates length of the Token field */
-    uint8_t code;               /* CoAP status code. Can be request (0.xx), success reponse (2.xx), 
-                                 * client error response (4.xx), or rever error response (5.xx) 
+    uint8_t code;               /* CoAP status code. Can be request (0.xx), success reponse (2.xx),
+                                 * client error response (4.xx), or rever error response (5.xx)
                                  * For possible values, see http://tools.ietf.org/html/rfc7252#section-12.1 */
     uint8_t id[2];
 } coap_header_t;
@@ -164,14 +164,14 @@ struct coap_luser_entry{
 
 struct coap_endpoint_t{
     coap_method_t method;               /* (i.e. POST, PUT or GET) */
-    coap_endpoint_func handler;         /* callback function which handles this 
-                                         * type of endpoint (and calls 
+    coap_endpoint_func handler;         /* callback function which handles this
+                                         * type of endpoint (and calls
                                          * coap_make_response() at some point) */
-    const coap_endpoint_path_t *path;   /* path towards a resource (i.e. foo/bar/) */ 
+    const coap_endpoint_path_t *path;   /* path towards a resource (i.e. foo/bar/) */
     const char *core_attr;              /* the 'ct' attribute, as defined in RFC7252, section 7.2.1.:
-                                         * "The Content-Format code "ct" attribute 
-                                         * provides a hint about the 
-                                         * Content-Formats this resource returns." 
+                                         * "The Content-Format code "ct" attribute
+                                         * provides a hint about the
+                                         * Content-Formats this resource returns."
                                          * (Section 12.3. lists possible ct values.) */
 	coap_luser_entry *user_entry;
 };

+ 1 - 1
app/coap/coap_io.c

@@ -64,7 +64,7 @@ coap_tid_t coap_send_confirmed(struct espconn *pesp_conn, coap_pdu_t *pdu) {
    */
   coap_timer_stop();
   coap_timer_update(&gQueue);
-  node->t = node->timeout;  
+  node->t = node->timeout;
   coap_insert_node(&gQueue, node);
   coap_timer_start(&gQueue);
   return node->id;

+ 1 - 1
app/coap/coap_io.h

@@ -10,7 +10,7 @@ extern "C" {
 #include "espconn.h"
 #include "pdu.h"
 #include "hash.h"
-	
+
 coap_tid_t coap_send(struct espconn *pesp_conn, coap_pdu_t *pdu);
 
 coap_tid_t coap_send_confirmed(struct espconn *pesp_conn, coap_pdu_t *pdu);

+ 2 - 2
app/coap/coap_timer.c

@@ -29,14 +29,14 @@ void coap_timer_tick(void *arg){
     node->retransmit_cnt++;
     node->t = node->timeout << node->retransmit_cnt;
 
-    NODE_DBG("** retransmission #%d of transaction %d\n", 
+    NODE_DBG("** retransmission #%d of transaction %d\n",
         node->retransmit_cnt, (((uint16_t)(node->pdu->pkt->hdr.id[0]))<<8)+node->pdu->pkt->hdr.id[1]);
     node->id = coap_send(node->pconn, node->pdu);
     if (COAP_INVALID_TID == node->id) {
       NODE_DBG("retransmission: error sending pdu\n");
       coap_delete_node(node);
     } else {
-      coap_insert_node(queue, node);    
+      coap_insert_node(queue, node);
     }
   } else {
     /* And finally delete the node */

+ 5 - 5
app/coap/endpoints.c

@@ -141,7 +141,7 @@ static int handle_post_function(const coap_endpoint_t *ep, coap_rw_buffer_t *scr
                                     NODE_DBG("\n");
                                     lua_settop(L, n);
                                     return coap_make_response(scratch, outpkt, ret, len, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
-                                } 
+                                }
                             } else {
                                 lua_settop(L, n);
                                 return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN);
@@ -157,7 +157,7 @@ static int handle_post_function(const coap_endpoint_t *ep, coap_rw_buffer_t *scr
             goto end;
         }
     }
-    NODE_DBG("none match.\n");    
+    NODE_DBG("none match.\n");
 end:
     return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE);
 }
@@ -226,7 +226,7 @@ void build_well_known_rsp(char *rsp, uint16_t rsplen)
                 c_strncat(rsp, ",", len);
                 len--;
             }
-        
+
             c_strncat(rsp, "<", len);
             len--;
 
@@ -250,7 +250,7 @@ void build_well_known_rsp(char *rsp, uint16_t rsplen)
                     c_strncat(rsp, ",", len);
                     len--;
                 }
-            
+
                 c_strncat(rsp, "<", len);
                 len--;
 
@@ -272,7 +272,7 @@ void build_well_known_rsp(char *rsp, uint16_t rsplen)
                 len -= 2;
 
                 c_strncat(rsp, ep->core_attr, len);
-                len -= c_strlen(ep->core_attr);  
+                len -= c_strlen(ep->core_attr);
 
                 h = h->next;
             }

+ 3 - 3
app/coap/hash.c

@@ -8,7 +8,7 @@ void coap_hash(const unsigned char *s, unsigned int len, coap_key_t h) {
 
   while (len--) {
     j = sizeof(coap_key_t)-1;
-  
+
     while (j) {
       h[j] = ((h[j] << 7) | (h[j-1] >> 1)) + h[j];
       --j;
@@ -23,8 +23,8 @@ void coap_transaction_id(const uint32_t ip, const uint32_t port, const coap_pack
   c_memset(h, 0, sizeof(coap_key_t));
 
   /* Compare the transport address. */
-  coap_hash((const unsigned char *)&(port), sizeof(port), h); 
-  coap_hash((const unsigned char *)&(ip), sizeof(ip), h); 
+  coap_hash((const unsigned char *)&(port), sizeof(port), h);
+  coap_hash((const unsigned char *)&(ip), sizeof(ip), h);
   coap_hash((const unsigned char *)(pkt->hdr.id), sizeof(pkt->hdr.id), h);
   *id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]);
 }

+ 1 - 1
app/coap/node.c

@@ -101,7 +101,7 @@ coap_queue_t * coap_pop_next( coap_queue_t **queue ) {		// this function is call
 
 int coap_remove_node( coap_queue_t **queue, const coap_tid_t id){
   coap_queue_t *p, *q, *node;
-  if ( !queue ) 
+  if ( !queue )
     return 0;
   if ( !*queue )  // if empty
     return 0;

+ 1 - 1
app/coap/pdu.c

@@ -16,7 +16,7 @@ coap_pdu_t * coap_new_pdu(void) {
     return NULL;
   }
   pdu->scratch.len = MAX_REQ_SCRATCH_SIZE;
-  
+
   pdu->pkt = (coap_packet_t *)c_zalloc(sizeof(coap_packet_t));
   if(!pdu->pkt){
     NODE_DBG("coap_new_pdu malloc error.\n");

+ 2 - 2
app/coap/str.c

@@ -3,12 +3,12 @@
  * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
  *
  * This file is part of the CoAP library libcoap. Please see
- * README for terms of use. 
+ * README for terms of use.
  */
 
 #include "c_stdlib.h"
 #include "c_types.h"
- 
+
 #include "str.h"
 
 str * coap_new_string(size_t size) {

+ 1 - 1
app/coap/str.h

@@ -3,7 +3,7 @@
  * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
  *
  * This file is part of the CoAP library libcoap. Please see
- * README for terms of use. 
+ * README for terms of use.
  */
 
 #ifndef _COAP_STR_H_

+ 38 - 38
app/coap/uri.c

@@ -17,22 +17,22 @@
 #endif
 
 
-/** 
+/**
  * A length-safe version of strchr(). This function returns a pointer
  * to the first occurrence of @p c  in @p s, or @c NULL if not found.
- * 
+ *
  * @param s   The string to search for @p c.
  * @param len The length of @p s.
  * @param c   The character to search.
- * 
- * @return A pointer to the first occurence of @p c, or @c NULL 
+ *
+ * @return A pointer to the first occurence of @p c, or @c NULL
  * if not found.
  */
 static inline unsigned char *
 strnchr(unsigned char *s, size_t len, unsigned char c) {
   while (len && *s++ != c)
     --len;
-  
+
   return len ? s : NULL;
 }
 
@@ -57,7 +57,7 @@ int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
   while (len && *q && tolower(*p) == *q) {
     ++p; ++q; --len;
   }
-  
+
   /* If q does not point to the string end marker '\0', the schema
    * identifier is wrong. */
   if (*q) {
@@ -84,7 +84,7 @@ int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
   q = p;
   if (len && *p == '[') {	/* IPv6 address reference */
     ++p;
-    
+
     while (len && *q != ']') {
       ++q; --len;
     }
@@ -92,7 +92,7 @@ int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
     if (!len || *q != ']' || p == q) {
       res = -3;
       goto error;
-    } 
+    }
 
     COAP_SET_STR(&uri->host, q - p, p);
     ++q; --len;
@@ -115,7 +115,7 @@ int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
   if (len && *q == ':') {
     p = ++q;
     --len;
-    
+
     while (len && isdigit(*q)) {
       ++q;
       --len;
@@ -123,19 +123,19 @@ int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
 
     if (p < q) {		/* explicit port number given */
       int uri_port = 0;
-    
+
       while (p < q)
 	     uri_port = uri_port * 10 + (*p++ - '0');
 
       uri->port = uri_port;
-    } 
+    }
   }
-  
+
  path:		 /* at this point, p must point to an absolute path */
 
   if (!len)
     goto end;
-  
+
   if (*q == '/') {
     p = ++q;
     --len;
@@ -144,7 +144,7 @@ int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
       ++q;
       --len;
     }
-  
+
     if (p < q) {
       COAP_SET_STR(&uri->path, q - p, p);
       p = q;
@@ -161,28 +161,28 @@ int coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
 
   end:
   return len ? -1 : 0;
-  
+
   error:
   return res;
 }
 
-/** 
+/**
  * Calculates decimal value from hexadecimal ASCII character given in
  * @p c. The caller must ensure that @p c actually represents a valid
- * heaxdecimal character, e.g. with isxdigit(3). 
+ * heaxdecimal character, e.g. with isxdigit(3).
  *
  * @hideinitializer
  */
 #define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F))
 
-/** 
+/**
  * Decodes percent-encoded characters while copying the string @p seg
  * of size @p length to @p buf. The caller of this function must
  * ensure that the percent-encodings are correct (i.e. the character
  * '%' is always followed by two hex digits. and that @p buf provides
  * sufficient space to hold the result. This function is supposed to
  * be called by make_decoded_option() only.
- * 
+ *
  * @param seg     The segment to decode and copy.
  * @param length  Length of @p seg.
  * @param buf     The result buffer.
@@ -193,12 +193,12 @@ void decode_segment(const unsigned char *seg, size_t length, unsigned char *buf)
 
     if (*seg == '%') {
       *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]);
-      
+
       seg += 2; length -= 2;
     } else {
       *buf = *seg;
     }
-    
+
     ++buf; ++seg;
   }
 }
@@ -216,18 +216,18 @@ int check_segment(const unsigned char *s, size_t length) {
     if (*s == '%') {
       if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2])))
         return -1;
-      
+
       s += 2;
       length -= 2;
     }
 
     ++s; ++n; --length;
   }
-  
+
   return n;
 }
-	 
-/** 
+
+/**
  * Writes a coap option from given string @p s to @p buf. @p s should
  * point to a (percent-encoded) path or query segment of a coap_uri_t
  * object.  The created option will have type @c 0, and the length
@@ -235,18 +235,18 @@ int check_segment(const unsigned char *s, size_t length) {
  * On success, this function returns the option's size, or a value
  * less than zero on error. This function must be called from
  * coap_split_path_impl() only.
- * 
+ *
  * @param s       The string to decode.
  * @param length  The size of the percent-encoded string @p s.
  * @param buf     The buffer to store the new coap option.
  * @param buflen  The maximum size of @p buf.
- * 
+ *
  * @return The option's size, or @c -1 on error.
  *
  * @bug This function does not split segments that are bigger than 270
  * bytes.
  */
-int make_decoded_option(const unsigned char *s, size_t length, 
+int make_decoded_option(const unsigned char *s, size_t length,
 		    unsigned char *buf, size_t buflen) {
   int res;
   size_t written;
@@ -289,32 +289,32 @@ int make_decoded_option(const unsigned char *s, size_t length,
 
 typedef void (*segment_handler_t)(unsigned char *, size_t, void *);
 
-/** 
+/**
  * Splits the given string into segments. You should call one of the
  * macros coap_split_path() or coap_split_query() instead.
- * 
+ *
  * @param parse_iter The iterator used for tokenizing.
  * @param h      A handler that is called with every token.
  * @param data   Opaque data that is passed to @p h when called.
- * 
+ *
  * @return The number of characters that have been parsed from @p s.
  */
 size_t coap_split_path_impl(coap_parse_iterator_t *parse_iter,
 		     segment_handler_t h, void *data) {
   unsigned char *seg;
   size_t length;
-  
+
   assert(parse_iter);
   assert(h);
 
   length = parse_iter->n;
-  
+
   while ( (seg = coap_parse_next(parse_iter)) ) {
 
     /* any valid path segment is handled here: */
     h(seg, parse_iter->segment_length, data);
   }
-  
+
   return length - (parse_iter->n - parse_iter->segment_length);
 }
 
@@ -332,7 +332,7 @@ void write_option(unsigned char *s, size_t len, void *data) {
   /* skip empty segments and those that consist of only one or two dots */
   if (memcmp(s, "..", min(len,2)) == 0)
     return;
-  
+
   res = check_segment(s, len);
   if (res < 0){
     NODE_DBG("not a valid segment\n");
@@ -360,7 +360,7 @@ int coap_split_path(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const unsigne
   struct pkt_scr tmp = { pkt, scratch, 0 };
   coap_parse_iterator_t pi;
 
-  coap_parse_iterator_init((unsigned char *)s, length, 
+  coap_parse_iterator_init((unsigned char *)s, length,
          '/', (unsigned char *)"?#", 2, &pi);
   coap_split_path_impl(&pi, write_option, &tmp);
 
@@ -376,7 +376,7 @@ int coap_split_query(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const unsign
   struct pkt_scr tmp = { pkt, scratch, 0 };
   coap_parse_iterator_t pi;
 
-  coap_parse_iterator_init((unsigned char *)s, length, 
+  coap_parse_iterator_init((unsigned char *)s, length,
          '&', (unsigned char *)"#", 1, &pi);
 
   coap_split_path_impl(&pi, write_option, &tmp);
@@ -411,7 +411,7 @@ coap_uri_t * coap_new_uri(const unsigned char *uri, unsigned int length) {
 
 /* iterator functions */
 
-coap_parse_iterator_t * coap_parse_iterator_init(unsigned char *s, size_t n, 
+coap_parse_iterator_t * coap_parse_iterator_init(unsigned char *s, size_t n,
 			 unsigned char separator,
 			 unsigned char *delim, size_t dlen,
 			 coap_parse_iterator_t *pi) {

+ 28 - 28
app/coap/uri.h

@@ -3,7 +3,7 @@
  * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
  *
  * This file is part of the CoAP library libcoap. Please see
- * README for terms of use. 
+ * README for terms of use.
  */
 
 #ifndef _COAP_URI_H_
@@ -20,7 +20,7 @@
 typedef struct {
   str host;			/**< host part of the URI */
   unsigned short port;		/**< The port in host byte order */
-  str path;			/**< Beginning of the first path segment. 
+  str path;			/**< Beginning of the first path segment.
 				   Use coap_split_path() to create Uri-Path options */
   str query;			/**<  The query part if present */
 } coap_uri_t;
@@ -44,7 +44,7 @@ coap_uri_t *coap_new_uri(const unsigned char *uri, unsigned int length);
  * @{
  */
 
-/** 
+/**
  * Iterator to for tokenizing a URI path or query. This structure must
  * be initialized with coap_parse_iterator_init(). Call
  * coap_parse_next() to walk through the tokens.
@@ -68,45 +68,45 @@ typedef struct {
   size_t segment_length;	/**< length of current segment */
 } coap_parse_iterator_t;
 
-/** 
- * Initializes the given iterator @p pi. 
- * 
+/**
+ * Initializes the given iterator @p pi.
+ *
  * @param s         The string to tokenize.
  * @param n         The length of @p s.
  * @param separator The separator character that delimits tokens.
  * @param delim     A set of characters that delimit @s.
  * @param dlen      The length of @p delim.
  * @param pi        The iterator object to initialize.
- * 
+ *
  * @return The initialized iterator object @p pi.
  */
 coap_parse_iterator_t *
-coap_parse_iterator_init(unsigned char *s, size_t n, 
+coap_parse_iterator_init(unsigned char *s, size_t n,
 			 unsigned char separator,
 			 unsigned char *delim, size_t dlen,
 			 coap_parse_iterator_t *pi);
 
-/** 
+/**
  * Updates the iterator @p pi to point to the next token. This
  * function returns a pointer to that token or @c NULL if no more
  * tokens exist. The contents of @p pi will be updated. In particular,
  * @c pi->segment_length specifies the length of the current token, @c
  * pi->pos points to its beginning.
- * 
+ *
  * @param pi The iterator to update.
- * 
+ *
  * @return The next token or @c NULL if no more tokens exist.
  */
 unsigned char *coap_parse_next(coap_parse_iterator_t *pi);
 
-/** 
+/**
  * Parses a given string into URI components. The identified syntactic
  * components are stored in the result parameter @p uri. Optional URI
  * components that are not specified will be set to { 0, 0 }, except
  * for the port which is set to @c COAP_DEFAULT_PORT. This function
  * returns @p 0 if parsing succeeded, a value less than zero
  * otherwise.
- * 
+ *
  * @param str_var The string to split up.
  * @param len     The actual length of @p str_var
  * @param uri     The coap_uri_t object to store the result.
@@ -118,47 +118,47 @@ unsigned char *coap_parse_next(coap_parse_iterator_t *pi);
 int
 coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri);
 
-/** 
+/**
  * Splits the given URI path into segments. Each segment is preceded
  * by an option pseudo-header with delta-value 0 and the actual length
  * of the respective segment after percent-decoding.
- * 
- * @param s      The path string to split. 
+ *
+ * @param s      The path string to split.
  * @param length The actual length of @p s.
- * @param buf    Result buffer for parsed segments. 
+ * @param buf    Result buffer for parsed segments.
  * @param buflen Maximum length of @p buf. Will be set to the actual number
  * of bytes written into buf on success.
- * 
+ *
  * @return The number of segments created or @c -1 on error.
  */
 #if 0
-int coap_split_path(const unsigned char *s, size_t length, 
+int coap_split_path(const unsigned char *s, size_t length,
 		    unsigned char *buf, size_t *buflen);
 #else
 int
-coap_split_path(coap_rw_buffer_t *scratch, coap_packet_t *pkt, 
+coap_split_path(coap_rw_buffer_t *scratch, coap_packet_t *pkt,
         const unsigned char *s, size_t length);
 #endif
-/** 
+/**
  * Splits the given URI query into segments. Each segment is preceded
  * by an option pseudo-header with delta-value 0 and the actual length
  * of the respective query term.
- * 
- * @param s      The query string to split. 
+ *
+ * @param s      The query string to split.
  * @param length The actual length of @p s.
- * @param buf    Result buffer for parsed segments. 
+ * @param buf    Result buffer for parsed segments.
  * @param buflen Maximum length of @p buf. Will be set to the actual number
  * of bytes written into buf on success.
- * 
+ *
  * @return The number of segments created or @c -1 on error.
  *
  * @bug This function does not reserve additional space for delta > 12.
  */
 #if 0
-int coap_split_query(const unsigned char *s, size_t length, 
+int coap_split_query(const unsigned char *s, size_t length,
 		     unsigned char *buf, size_t *buflen);
-#else 
-int coap_split_query(coap_rw_buffer_t *scratch, coap_packet_t *pkt, 
+#else
+int coap_split_query(coap_rw_buffer_t *scratch, coap_packet_t *pkt,
           const unsigned char *s, size_t length);
 #endif
 /** @} */

+ 1 - 1
app/crypto/digests.c

@@ -140,7 +140,7 @@ int ICACHE_FLASH_ATTR crypto_fhash (const digest_mech_info_t *mi,
   uint8_t* buffer = (uint8_t*)os_malloc (mi->block_size);
   if (!buffer)
     return ENOMEM;
-  
+
   int read_len = 0;
   do {
     read_len = read(readarg, buffer, mi->block_size);

+ 4 - 4
app/crypto/sha2.c

@@ -1,7 +1,7 @@
 /*
  * FILE:	sha2.c
  * AUTHOR:	Aaron D. Gifford - http://www.aarongifford.com/
- * 
+ *
  * Copyright (c) 2000-2001, Aaron D. Gifford
  * Copyright (c) 2015, DiUS Computing Pty Ltd (jmattsson@dius.com.au)
  * All rights reserved.
@@ -17,7 +17,7 @@
  * 3. Neither the name of the copyright holder nor the names of contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -424,11 +424,11 @@ void ICACHE_FLASH_ATTR SHA256_Transform(SHA256_CTX* context, const sha2_word32*
 		/* Part of the message block expansion: */
 		s0 = W256[(j+1)&0x0f];
 		s0 = sigma0_256(s0);
-		s1 = W256[(j+14)&0x0f];	
+		s1 = W256[(j+14)&0x0f];
 		s1 = sigma1_256(s1);
 
 		/* Apply the SHA-256 compression function to update a..h */
-		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + 
+		T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
 		     (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
 		T2 = Sigma0_256(a) + Maj(a, b, c);
 		h = g;

+ 1 - 1
app/dht/Makefile

@@ -23,7 +23,7 @@ endif
 #   makefile at its root level - these are then overridden
 #   for a subtree within the makefile rooted therein
 #
-#DEFINES += 
+#DEFINES +=
 
 #############################################################
 # Recursion Magic - Don't touch this!!

+ 319 - 319
app/dht/dht.c

@@ -1,319 +1,319 @@
-//
-//    FILE: dht.cpp
-//  AUTHOR: Rob Tillaart
-// VERSION: 0.1.14
-// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
-//     URL: http://arduino.cc/playground/Main/DHTLib
-//
-// HISTORY:
-// 0.1.14 replace digital read with faster (~3x) code => more robust low MHz machines.
-// 0.1.13 fix negative dht_temperature
-// 0.1.12 support DHT33 and DHT44 initial version
-// 0.1.11 renamed DHTLIB_TIMEOUT
-// 0.1.10 optimized faster WAKEUP + TIMEOUT
-// 0.1.09 optimize size: timeout check + use of mask
-// 0.1.08 added formula for timeout based upon clockspeed
-// 0.1.07 added support for DHT21
-// 0.1.06 minimize footprint (2012-12-27)
-// 0.1.05 fixed negative dht_temperature bug (thanks to Roseman)
-// 0.1.04 improved readability of code using DHTLIB_OK in code
-// 0.1.03 added error values for temp and dht_humidity when read failed
-// 0.1.02 added error codes
-// 0.1.01 added support for Arduino 1.0, fixed typos (31/12/2011)
-// 0.1.00 by Rob Tillaart (01/04/2011)
-//
-// inspired by DHT11 library
-//
-// Released to the public domain
-//
-
-#include "user_interface.h"
-#include "platform.h"
-#include "c_stdio.h"
-#include "dht.h"
-
-#ifndef LOW
-#define LOW     0
-#endif /* ifndef LOW */
-
-#ifndef HIGH
-#define HIGH    1
-#endif /* ifndef HIGH */
-
-#define COMBINE_HIGH_AND_LOW_BYTE(byte_high, byte_low)  (((byte_high) << 8) | (byte_low))
-
-static double dht_humidity;
-static double dht_temperature;
-
-static uint8_t dht_bytes[5];  // buffer to receive data
-static int dht_readSensor(uint8_t pin, uint8_t wakeupDelay);
-
-/////////////////////////////////////////////////////
-//
-// PUBLIC
-//
-
-// return values:
-// Humidity
-double dht_getHumidity(void)
-{
-    return dht_humidity;
-}
-
-// return values:
-// Temperature
-double dht_getTemperature(void)
-{
-    return dht_temperature;
-}
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read_universal(uint8_t pin)
-{
-    // READ VALUES
-    int rv = dht_readSensor(pin, DHTLIB_DHT_UNI_WAKEUP);
-    if (rv != DHTLIB_OK)
-    {
-        dht_humidity    = DHTLIB_INVALID_VALUE;  // invalid value, or is NaN prefered?
-        dht_temperature = DHTLIB_INVALID_VALUE;  // invalid value
-        return rv; // propagate error value
-    }
-
-#if defined(DHT_DEBUG_BYTES)
-    int i;
-    for (i = 0; i < 5; i++)
-    {
-        DHT_DEBUG("%02X\n", dht_bytes[i]);
-    }
-#endif // defined(DHT_DEBUG_BYTES)
-
-    // Assume it is DHT11
-    // If it is DHT11, both bit[1] and bit[3] is 0
-    if ((dht_bytes[1] == 0) && (dht_bytes[3] == 0))
-    {
-        // It may DHT11
-        // CONVERT AND STORE
-        DHT_DEBUG("DHT11 method\n");
-        dht_humidity    = dht_bytes[0];  // dht_bytes[1] == 0;
-        dht_temperature = dht_bytes[2];  // dht_bytes[3] == 0;
-
-        // TEST CHECKSUM
-        // dht_bytes[1] && dht_bytes[3] both 0
-        uint8_t sum = dht_bytes[0] + dht_bytes[2];
-        if (dht_bytes[4] != sum)
-        {
-            // It may not DHT11
-            dht_humidity    = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
-            dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
-            // Do nothing
-        }
-        else
-        {
-            return DHTLIB_OK;
-        }
-    }
-
-    // Assume it is not DHT11
-    // CONVERT AND STORE
-    DHT_DEBUG("DHTxx method\n");
-    dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
-    dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
-    if (dht_bytes[2] & 0x80)  // negative dht_temperature
-    {
-        dht_temperature = -dht_temperature;
-    }
-
-    // TEST CHECKSUM
-    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
-    if (dht_bytes[4] != sum)
-    {
-        return DHTLIB_ERROR_CHECKSUM;
-    }
-    return DHTLIB_OK;
-}
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read11(uint8_t pin)
-{
-    // READ VALUES
-    int rv = dht_readSensor(pin, DHTLIB_DHT11_WAKEUP);
-    if (rv != DHTLIB_OK)
-    {
-        dht_humidity    = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
-        dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
-        return rv;
-    }
-
-    // CONVERT AND STORE
-    dht_humidity    = dht_bytes[0];  // dht_bytes[1] == 0;
-    dht_temperature = dht_bytes[2];  // dht_bytes[3] == 0;
-
-    // TEST CHECKSUM
-    // dht_bytes[1] && dht_bytes[3] both 0
-    uint8_t sum = dht_bytes[0] + dht_bytes[2];
-    if (dht_bytes[4] != sum) return DHTLIB_ERROR_CHECKSUM;
-
-    return DHTLIB_OK;
-}
-
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read(uint8_t pin)
-{
-    // READ VALUES
-    int rv = dht_readSensor(pin, DHTLIB_DHT_WAKEUP);
-    if (rv != DHTLIB_OK)
-    {
-        dht_humidity    = DHTLIB_INVALID_VALUE;  // invalid value, or is NaN prefered?
-        dht_temperature = DHTLIB_INVALID_VALUE;  // invalid value
-        return rv; // propagate error value
-    }
-
-    // CONVERT AND STORE
-    dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
-    dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
-    if (dht_bytes[2] & 0x80)  // negative dht_temperature
-    {
-        dht_temperature = -dht_temperature;
-    }
-
-    // TEST CHECKSUM
-    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
-    if (dht_bytes[4] != sum)
-    {
-        return DHTLIB_ERROR_CHECKSUM;
-    }
-    return DHTLIB_OK;
-}
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read21(uint8_t pin)  __attribute__((alias("dht_read")));
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read22(uint8_t pin)  __attribute__((alias("dht_read")));
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read33(uint8_t pin)  __attribute__((alias("dht_read")));
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read44(uint8_t pin)  __attribute__((alias("dht_read")));
-
-/////////////////////////////////////////////////////
-//
-// PRIVATE
-//
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_TIMEOUT
-int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
-{
-    // INIT BUFFERVAR TO RECEIVE DATA
-    uint8_t mask = 128;
-    uint8_t idx = 0;
-    uint8_t i = 0;
-
-    // replace digitalRead() with Direct Port Reads.
-    // reduces footprint ~100 bytes => portability issue?
-    // direct port read is about 3x faster
-    // uint8_t bit = digitalPinToBitMask(pin);
-    // uint8_t port = digitalPinToPort(pin);
-    // volatile uint8_t *PIR = portInputRegister(port);
-
-    // EMPTY BUFFER
-    for (i = 0; i < 5; i++) dht_bytes[i] = 0;
-
-    // REQUEST SAMPLE
-    // pinMode(pin, OUTPUT);
-    platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP);
-    DIRECT_MODE_OUTPUT(pin);
-    // digitalWrite(pin, LOW); // T-be
-    DIRECT_WRITE_LOW(pin);
-    // delay(wakeupDelay);
-    for (i = 0; i < wakeupDelay; i++) os_delay_us(1000);
-    // Disable interrupts
-    ets_intr_lock();
-    // digitalWrite(pin, HIGH);   // T-go
-    DIRECT_WRITE_HIGH(pin);
-    os_delay_us(40);
-    // pinMode(pin, INPUT);
-    DIRECT_MODE_INPUT(pin);
-
-    // GET ACKNOWLEDGE or TIMEOUT
-    uint16_t loopCntLOW = DHTLIB_TIMEOUT;
-    while (DIRECT_READ(pin) == LOW )  // T-rel
-    {
-        os_delay_us(1);
-        if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
-    }
-
-    uint16_t loopCntHIGH = DHTLIB_TIMEOUT;
-    while (DIRECT_READ(pin) != LOW )  // T-reh
-    {
-        os_delay_us(1);
-        if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
-    }
-
-    // READ THE OUTPUT - 40 BITS => 5 BYTES
-    for (i = 40; i != 0; i--)
-    {
-        loopCntLOW = DHTLIB_TIMEOUT;
-        while (DIRECT_READ(pin) == LOW )
-        {
-            os_delay_us(1);
-            if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
-        }
-
-        uint32_t t = system_get_time();
-
-        loopCntHIGH = DHTLIB_TIMEOUT;
-        while (DIRECT_READ(pin) != LOW )
-        {
-            os_delay_us(1);
-            if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
-        }
-
-        if ((system_get_time() - t) > 40)
-        {
-            dht_bytes[idx] |= mask;
-        }
-        mask >>= 1;
-        if (mask == 0)   // next byte?
-        {
-            mask = 128;
-            idx++;
-        }
-    }
-    // Enable interrupts
-    ets_intr_unlock();
-    // pinMode(pin, OUTPUT);
-    DIRECT_MODE_OUTPUT(pin);
-    // digitalWrite(pin, HIGH);
-    DIRECT_WRITE_HIGH(pin);
-
-    return DHTLIB_OK;
-}
-//
-// END OF FILE
-//
+//
+//    FILE: dht.cpp
+//  AUTHOR: Rob Tillaart
+// VERSION: 0.1.14
+// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
+//     URL: http://arduino.cc/playground/Main/DHTLib
+//
+// HISTORY:
+// 0.1.14 replace digital read with faster (~3x) code => more robust low MHz machines.
+// 0.1.13 fix negative dht_temperature
+// 0.1.12 support DHT33 and DHT44 initial version
+// 0.1.11 renamed DHTLIB_TIMEOUT
+// 0.1.10 optimized faster WAKEUP + TIMEOUT
+// 0.1.09 optimize size: timeout check + use of mask
+// 0.1.08 added formula for timeout based upon clockspeed
+// 0.1.07 added support for DHT21
+// 0.1.06 minimize footprint (2012-12-27)
+// 0.1.05 fixed negative dht_temperature bug (thanks to Roseman)
+// 0.1.04 improved readability of code using DHTLIB_OK in code
+// 0.1.03 added error values for temp and dht_humidity when read failed
+// 0.1.02 added error codes
+// 0.1.01 added support for Arduino 1.0, fixed typos (31/12/2011)
+// 0.1.00 by Rob Tillaart (01/04/2011)
+//
+// inspired by DHT11 library
+//
+// Released to the public domain
+//
+
+#include "user_interface.h"
+#include "platform.h"
+#include "c_stdio.h"
+#include "dht.h"
+
+#ifndef LOW
+#define LOW     0
+#endif /* ifndef LOW */
+
+#ifndef HIGH
+#define HIGH    1
+#endif /* ifndef HIGH */
+
+#define COMBINE_HIGH_AND_LOW_BYTE(byte_high, byte_low)  (((byte_high) << 8) | (byte_low))
+
+static double dht_humidity;
+static double dht_temperature;
+
+static uint8_t dht_bytes[5];  // buffer to receive data
+static int dht_readSensor(uint8_t pin, uint8_t wakeupDelay);
+
+/////////////////////////////////////////////////////
+//
+// PUBLIC
+//
+
+// return values:
+// Humidity
+double dht_getHumidity(void)
+{
+    return dht_humidity;
+}
+
+// return values:
+// Temperature
+double dht_getTemperature(void)
+{
+    return dht_temperature;
+}
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read_universal(uint8_t pin)
+{
+    // READ VALUES
+    int rv = dht_readSensor(pin, DHTLIB_DHT_UNI_WAKEUP);
+    if (rv != DHTLIB_OK)
+    {
+        dht_humidity    = DHTLIB_INVALID_VALUE;  // invalid value, or is NaN prefered?
+        dht_temperature = DHTLIB_INVALID_VALUE;  // invalid value
+        return rv; // propagate error value
+    }
+
+#if defined(DHT_DEBUG_BYTES)
+    int i;
+    for (i = 0; i < 5; i++)
+    {
+        DHT_DEBUG("%02X\n", dht_bytes[i]);
+    }
+#endif // defined(DHT_DEBUG_BYTES)
+
+    // Assume it is DHT11
+    // If it is DHT11, both bit[1] and bit[3] is 0
+    if ((dht_bytes[1] == 0) && (dht_bytes[3] == 0))
+    {
+        // It may DHT11
+        // CONVERT AND STORE
+        DHT_DEBUG("DHT11 method\n");
+        dht_humidity    = dht_bytes[0];  // dht_bytes[1] == 0;
+        dht_temperature = dht_bytes[2];  // dht_bytes[3] == 0;
+
+        // TEST CHECKSUM
+        // dht_bytes[1] && dht_bytes[3] both 0
+        uint8_t sum = dht_bytes[0] + dht_bytes[2];
+        if (dht_bytes[4] != sum)
+        {
+            // It may not DHT11
+            dht_humidity    = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
+            dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
+            // Do nothing
+        }
+        else
+        {
+            return DHTLIB_OK;
+        }
+    }
+
+    // Assume it is not DHT11
+    // CONVERT AND STORE
+    DHT_DEBUG("DHTxx method\n");
+    dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
+    dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
+    if (dht_bytes[2] & 0x80)  // negative dht_temperature
+    {
+        dht_temperature = -dht_temperature;
+    }
+
+    // TEST CHECKSUM
+    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
+    if (dht_bytes[4] != sum)
+    {
+        return DHTLIB_ERROR_CHECKSUM;
+    }
+    return DHTLIB_OK;
+}
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read11(uint8_t pin)
+{
+    // READ VALUES
+    int rv = dht_readSensor(pin, DHTLIB_DHT11_WAKEUP);
+    if (rv != DHTLIB_OK)
+    {
+        dht_humidity    = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered?
+        dht_temperature = DHTLIB_INVALID_VALUE; // invalid value
+        return rv;
+    }
+
+    // CONVERT AND STORE
+    dht_humidity    = dht_bytes[0];  // dht_bytes[1] == 0;
+    dht_temperature = dht_bytes[2];  // dht_bytes[3] == 0;
+
+    // TEST CHECKSUM
+    // dht_bytes[1] && dht_bytes[3] both 0
+    uint8_t sum = dht_bytes[0] + dht_bytes[2];
+    if (dht_bytes[4] != sum) return DHTLIB_ERROR_CHECKSUM;
+
+    return DHTLIB_OK;
+}
+
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read(uint8_t pin)
+{
+    // READ VALUES
+    int rv = dht_readSensor(pin, DHTLIB_DHT_WAKEUP);
+    if (rv != DHTLIB_OK)
+    {
+        dht_humidity    = DHTLIB_INVALID_VALUE;  // invalid value, or is NaN prefered?
+        dht_temperature = DHTLIB_INVALID_VALUE;  // invalid value
+        return rv; // propagate error value
+    }
+
+    // CONVERT AND STORE
+    dht_humidity = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[0], dht_bytes[1]) * 0.1;
+    dht_temperature = (double)COMBINE_HIGH_AND_LOW_BYTE(dht_bytes[2] & 0x7F, dht_bytes[3]) * 0.1;
+    if (dht_bytes[2] & 0x80)  // negative dht_temperature
+    {
+        dht_temperature = -dht_temperature;
+    }
+
+    // TEST CHECKSUM
+    uint8_t sum = dht_bytes[0] + dht_bytes[1] + dht_bytes[2] + dht_bytes[3];
+    if (dht_bytes[4] != sum)
+    {
+        return DHTLIB_ERROR_CHECKSUM;
+    }
+    return DHTLIB_OK;
+}
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read21(uint8_t pin)  __attribute__((alias("dht_read")));
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read22(uint8_t pin)  __attribute__((alias("dht_read")));
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read33(uint8_t pin)  __attribute__((alias("dht_read")));
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read44(uint8_t pin)  __attribute__((alias("dht_read")));
+
+/////////////////////////////////////////////////////
+//
+// PRIVATE
+//
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_TIMEOUT
+int dht_readSensor(uint8_t pin, uint8_t wakeupDelay)
+{
+    // INIT BUFFERVAR TO RECEIVE DATA
+    uint8_t mask = 128;
+    uint8_t idx = 0;
+    uint8_t i = 0;
+
+    // replace digitalRead() with Direct Port Reads.
+    // reduces footprint ~100 bytes => portability issue?
+    // direct port read is about 3x faster
+    // uint8_t bit = digitalPinToBitMask(pin);
+    // uint8_t port = digitalPinToPort(pin);
+    // volatile uint8_t *PIR = portInputRegister(port);
+
+    // EMPTY BUFFER
+    for (i = 0; i < 5; i++) dht_bytes[i] = 0;
+
+    // REQUEST SAMPLE
+    // pinMode(pin, OUTPUT);
+    platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP);
+    DIRECT_MODE_OUTPUT(pin);
+    // digitalWrite(pin, LOW); // T-be
+    DIRECT_WRITE_LOW(pin);
+    // delay(wakeupDelay);
+    for (i = 0; i < wakeupDelay; i++) os_delay_us(1000);
+    // Disable interrupts
+    ets_intr_lock();
+    // digitalWrite(pin, HIGH);   // T-go
+    DIRECT_WRITE_HIGH(pin);
+    os_delay_us(40);
+    // pinMode(pin, INPUT);
+    DIRECT_MODE_INPUT(pin);
+
+    // GET ACKNOWLEDGE or TIMEOUT
+    uint16_t loopCntLOW = DHTLIB_TIMEOUT;
+    while (DIRECT_READ(pin) == LOW )  // T-rel
+    {
+        os_delay_us(1);
+        if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
+    }
+
+    uint16_t loopCntHIGH = DHTLIB_TIMEOUT;
+    while (DIRECT_READ(pin) != LOW )  // T-reh
+    {
+        os_delay_us(1);
+        if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
+    }
+
+    // READ THE OUTPUT - 40 BITS => 5 BYTES
+    for (i = 40; i != 0; i--)
+    {
+        loopCntLOW = DHTLIB_TIMEOUT;
+        while (DIRECT_READ(pin) == LOW )
+        {
+            os_delay_us(1);
+            if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT;
+        }
+
+        uint32_t t = system_get_time();
+
+        loopCntHIGH = DHTLIB_TIMEOUT;
+        while (DIRECT_READ(pin) != LOW )
+        {
+            os_delay_us(1);
+            if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT;
+        }
+
+        if ((system_get_time() - t) > 40)
+        {
+            dht_bytes[idx] |= mask;
+        }
+        mask >>= 1;
+        if (mask == 0)   // next byte?
+        {
+            mask = 128;
+            idx++;
+        }
+    }
+    // Enable interrupts
+    ets_intr_unlock();
+    // pinMode(pin, OUTPUT);
+    DIRECT_MODE_OUTPUT(pin);
+    // digitalWrite(pin, HIGH);
+    DIRECT_WRITE_HIGH(pin);
+
+    return DHTLIB_OK;
+}
+//
+// END OF FILE
+//

+ 69 - 69
app/dht/dht.h

@@ -1,70 +1,70 @@
-//
-//    FILE: dht.h
-//  AUTHOR: Rob Tillaart
-// VERSION: 0.1.14
-// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
-//     URL: http://arduino.cc/playground/Main/DHTLib
-//
-// HISTORY:
-// see dht.cpp file
-//
-
-#ifndef dht_h
-#define dht_h
-
-// #if ARDUINO < 100
-// #include <WProgram.h>
-// #else
-// #include <Arduino.h>
-// #endif
-#include "c_types.h"
-
-#define DHT_LIB_VERSION "0.1.14"
-
-#define DHTLIB_OK                0
-#define DHTLIB_ERROR_CHECKSUM   -1
-#define DHTLIB_ERROR_TIMEOUT    -2
-#define DHTLIB_INVALID_VALUE    -999
-
-#define DHTLIB_DHT11_WAKEUP     18
-#define DHTLIB_DHT_WAKEUP       1
-#define DHTLIB_DHT_UNI_WAKEUP   18
-
-#define DHT_DEBUG
-
-// max timeout is 100 usec.
-// For a 16 Mhz proc 100 usec is 1600 clock cycles
-// loops using DHTLIB_TIMEOUT use at least 4 clock cycli
-// so 100 us takes max 400 loops
-// so by dividing F_CPU by 40000 we "fail" as fast as possible
-// ESP8266 uses delay_us get 1us time
-#define DHTLIB_TIMEOUT (100)
-
-// Platform specific I/O definitions
-
-#define DIRECT_READ(pin)         (0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(pin_num[pin])))
-#define DIRECT_MODE_INPUT(pin)   GPIO_DIS_OUTPUT(pin_num[pin])
-#define DIRECT_MODE_OUTPUT(pin)
-#define DIRECT_WRITE_LOW(pin)    (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 0))
-#define DIRECT_WRITE_HIGH(pin)   (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 1))
-
-// return values:
-// DHTLIB_OK
-// DHTLIB_ERROR_CHECKSUM
-// DHTLIB_ERROR_TIMEOUT
-int dht_read_universal(uint8_t pin);
-int dht_read11(uint8_t pin);
-int dht_read(uint8_t pin);
-
-int dht_read21(uint8_t pin);
-int dht_read22(uint8_t pin);
-int dht_read33(uint8_t pin);
-int dht_read44(uint8_t pin);
-
-double dht_getHumidity(void);
-double dht_getTemperature(void);
-
-#endif
-//
-// END OF FILE
+//
+//    FILE: dht.h
+//  AUTHOR: Rob Tillaart
+// VERSION: 0.1.14
+// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino
+//     URL: http://arduino.cc/playground/Main/DHTLib
+//
+// HISTORY:
+// see dht.cpp file
+//
+
+#ifndef dht_h
+#define dht_h
+
+// #if ARDUINO < 100
+// #include <WProgram.h>
+// #else
+// #include <Arduino.h>
+// #endif
+#include "c_types.h"
+
+#define DHT_LIB_VERSION "0.1.14"
+
+#define DHTLIB_OK                0
+#define DHTLIB_ERROR_CHECKSUM   -1
+#define DHTLIB_ERROR_TIMEOUT    -2
+#define DHTLIB_INVALID_VALUE    -999
+
+#define DHTLIB_DHT11_WAKEUP     18
+#define DHTLIB_DHT_WAKEUP       1
+#define DHTLIB_DHT_UNI_WAKEUP   18
+
+#define DHT_DEBUG
+
+// max timeout is 100 usec.
+// For a 16 Mhz proc 100 usec is 1600 clock cycles
+// loops using DHTLIB_TIMEOUT use at least 4 clock cycli
+// so 100 us takes max 400 loops
+// so by dividing F_CPU by 40000 we "fail" as fast as possible
+// ESP8266 uses delay_us get 1us time
+#define DHTLIB_TIMEOUT (100)
+
+// Platform specific I/O definitions
+
+#define DIRECT_READ(pin)         (0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(pin_num[pin])))
+#define DIRECT_MODE_INPUT(pin)   GPIO_DIS_OUTPUT(pin_num[pin])
+#define DIRECT_MODE_OUTPUT(pin)
+#define DIRECT_WRITE_LOW(pin)    (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 0))
+#define DIRECT_WRITE_HIGH(pin)   (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 1))
+
+// return values:
+// DHTLIB_OK
+// DHTLIB_ERROR_CHECKSUM
+// DHTLIB_ERROR_TIMEOUT
+int dht_read_universal(uint8_t pin);
+int dht_read11(uint8_t pin);
+int dht_read(uint8_t pin);
+
+int dht_read21(uint8_t pin);
+int dht_read22(uint8_t pin);
+int dht_read33(uint8_t pin);
+int dht_read44(uint8_t pin);
+
+double dht_getHumidity(void);
+double dht_getTemperature(void);
+
+#endif
+//
+// END OF FILE
 //

+ 1 - 1
app/driver/Makefile

@@ -24,7 +24,7 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
 #   makefile at its root level - these are then overridden
 #   for a subtree within the makefile rooted therein
 #
-#DEFINES += 
+#DEFINES +=
 
 #############################################################
 # Recursion Magic - Don't touch this!!

+ 3 - 3
app/driver/pwm.c

@@ -49,7 +49,7 @@ LOCAL uint8 *pwm_channel;
 // Toggle flips between 1 and 0 when we make updates so that the interrupt code
 // cn switch cleanly between the two states. The cinterrupt handler uses either
 // the pwm_single_toggle[0] or pwm_single_toggle[1]
-// pwm_toggle indicates which state should be used on the *next* timer interrupt 
+// pwm_toggle indicates which state should be used on the *next* timer interrupt
 // freq boundary.
 LOCAL uint8 pwm_toggle = 1;
 LOCAL volatile uint8 pwm_current_toggle = 1;
@@ -326,7 +326,7 @@ pwm_tim1_intr_handler(os_param_t p)
   int offset = 0;
 
   while (1) {
-    if (pwm_current_channel >= (*pwm_channel - 1)) {      
+    if (pwm_current_channel >= (*pwm_channel - 1)) {
       pwm_single = pwm_single_toggle[pwm_toggle];
       pwm_channel = &pwm_channel_toggle[pwm_toggle];
       pwm_current_toggle = pwm_toggle;
@@ -388,7 +388,7 @@ pwm_init(uint16 freq, uint16 *duty)
     // GPIO_OUTPUT_SET(GPIO_ID_PIN(PWM_0_OUT_IO_NUM), 0);
     // GPIO_OUTPUT_SET(GPIO_ID_PIN(PWM_1_OUT_IO_NUM), 0);
     // GPIO_OUTPUT_SET(GPIO_ID_PIN(PWM_2_OUT_IO_NUM), 0);
-    
+
     for (i = 0; i < PWM_CHANNEL; i++) {
         // pwm_gpio |= (1 << pwm_out_io_num[i]);
         pwm_gpio = 0;

+ 2 - 2
app/driver/readline.c

@@ -20,7 +20,7 @@ bool uart_getc(char *c){
     ETS_INTR_LOCK();
     *c = (char)*(pRxBuff->pReadPos);
     if (pRxBuff->pReadPos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) {
-        pRxBuff->pReadPos = pRxBuff->pRcvMsgBuff ; 
+        pRxBuff->pReadPos = pRxBuff->pRcvMsgBuff ;
     } else {
         pRxBuff->pReadPos++;
     }
@@ -73,7 +73,7 @@ start:
                 else
                     continue;
             }
-            
+
             /* end of line */
             if (ch == '\r' || ch == '\n')
             {

+ 8 - 8
app/driver/rotary.c

@@ -20,7 +20,7 @@
 #include "ets_sys.h"
 
 //
-//  Queue is empty if read == write. 
+//  Queue is empty if read == write.
 //  However, we always want to keep the previous value
 //  so writing is only allowed if write - read < QUEUE_SIZE - 1
 
@@ -60,7 +60,7 @@ static uint8_t task_queued;
 
 static void set_gpio_bits(void);
 
-static void rotary_clear_pin(int pin) 
+static void rotary_clear_pin(int pin)
 {
   if (pin >= 0) {
     gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[pin]), GPIO_PIN_INTR_DISABLE);
@@ -69,7 +69,7 @@ static void rotary_clear_pin(int pin)
 }
 
 // Just takes the channel number. Cleans up the resources used.
-int rotary_close(uint32_t channel) 
+int rotary_close(uint32_t channel)
 {
   if (channel >= sizeof(data) / sizeof(data[0])) {
     return -1;
@@ -94,7 +94,7 @@ int rotary_close(uint32_t channel)
   return 0;
 }
 
-static uint32_t  ICACHE_RAM_ATTR rotary_interrupt(uint32_t ret_gpio_status) 
+static uint32_t  ICACHE_RAM_ATTR rotary_interrupt(uint32_t ret_gpio_status)
 {
   // This function really is running at interrupt level with everything
   // else masked off. It should take as little time as necessary.
@@ -168,10 +168,10 @@ static uint32_t  ICACHE_RAM_ATTR rotary_interrupt(uint32_t ret_gpio_status)
     }
 
     new_status |= rotary_pos & 0x7fffffff;
-    
+
     if (last_status != new_status) {
       // Either we overwrite the status or we add a new one
-      if (!HAS_QUEUED_DATA(d) 
+      if (!HAS_QUEUED_DATA(d)
 	  || STATUS_IS_PRESSED(last_status ^ new_status)
 	  || STATUS_IS_PRESSED(last_status ^ GET_PREV_STATUS(d).pos)) {
 	if (HAS_QUEUE_SPACE(d)) {
@@ -271,10 +271,10 @@ bool rotary_has_queued_event(uint32_t channel)
 }
 
 // Get the oldest event in the queue and remove it (if possible)
-bool rotary_getevent(uint32_t channel, rotary_event_t *resultp) 
+bool rotary_getevent(uint32_t channel, rotary_event_t *resultp)
 {
   rotary_event_t result = { 0 };
-  
+
   if (channel >= sizeof(data) / sizeof(data[0])) {
     return FALSE;
   }

+ 61 - 61
app/driver/spi.c

@@ -15,33 +15,33 @@ static uint32_t spi_clkdiv[2];
 *******************************************************************************/
 void spi_lcd_mode_init(uint8 spi_no)
 {
-	uint32 regvalue; 
+	uint32 regvalue;
 	if(spi_no>1) 		return; //handle invalid input number
 	//bit9 of PERIPHS_IO_MUX should be cleared when HSPI clock doesn't equal CPU clock
 	//bit8 of PERIPHS_IO_MUX should be cleared when SPI clock doesn't equal CPU clock
 	if(spi_no==SPI_SPI){
 		WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005); //clear bit9,and bit8
 		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode	
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode
 	}else if(spi_no==SPI_HSPI){
 		WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9
 		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode	
-	}			
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
+	}
 
 	SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND);
 	CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
 	// SPI clock=CPU clock/8
-	WRITE_PERI_REG(SPI_CLOCK(spi_no), 
+	WRITE_PERI_REG(SPI_CLOCK(spi_no),
 					((1&SPI_CLKDIV_PRE)<<SPI_CLKDIV_PRE_S)|
 					((3&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
 					((1&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
 					((3&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
-	
+
 }
 /******************************************************************************
  * FunctionName : spi_lcd_9bit_write
@@ -55,11 +55,11 @@ void spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit)
 	uint32 regvalue;
 	uint8 bytetemp;
 	if(spi_no>1) 		return; //handle invalid input number
-	
+
 	if(high_bit)		bytetemp=(low_8bit>>1)|0x80;
 	else				bytetemp=(low_8bit>>1)&0x7f;
-	
-	regvalue= ((8&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)bytetemp);		//configure transmission variable,9bit transmission length and first 8 command bit 
+
+	regvalue= ((8&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)bytetemp);		//configure transmission variable,9bit transmission length and first 8 command bit
 	if(low_8bit&0x01) 	regvalue|=BIT15;        //write the 9th bit
 	while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);		//waiting for spi module available
 	WRITE_PERI_REG(SPI_USER2(spi_no), regvalue);				//write  command and command length into spi reg
@@ -97,7 +97,7 @@ uint32_t spi_set_clkdiv(uint8 spi_no, uint32_t clock_div)
 		WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div <= 1 ? 0x100 : 0));
 	}
 	else if(spi_no==SPI_HSPI){
-		WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div <= 1 ? 0x200 : 0)); 
+		WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div <= 1 ? 0x200 : 0));
 	}
 
 	spi_clkdiv[spi_no] = clock_div;
@@ -112,7 +112,7 @@ uint32_t spi_set_clkdiv(uint8 spi_no, uint32_t clock_div)
 *******************************************************************************/
 void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_div)
 {
-	uint32 regvalue; 
+	uint32 regvalue;
 
 	if(spi_no>1) 		return; //handle invalid input number
 
@@ -125,7 +125,7 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_
 	} else {
 		CLEAR_PERI_REG_MASK(SPI_PIN(spi_no), SPI_IDLE_EDGE);
 	}
-	
+
 	//set clock phase
 	if (cpha == cpol) {
 		// Mode 3: MOSI is set on falling edge of clock
@@ -133,8 +133,8 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_
 		CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE);
 	} else {
 		// Mode 2: MOSI is set on rising edge of clock
-		// Mode 1: MOSI is set on rising edge of clock	
-		SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE);		
+		// Mode 1: MOSI is set on rising edge of clock
+		SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE);
 	}
 
 	CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE|SPI_USR_MISO|SPI_USR_ADDR|SPI_USR_COMMAND|SPI_USR_DUMMY);
@@ -146,15 +146,15 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_
 
 	if(spi_no==SPI_SPI){
 		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode	
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode
 	}
 	else if(spi_no==SPI_HSPI){
 		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode	
-		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode	
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
+		PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
 	}
 }
 
@@ -398,7 +398,7 @@ void spi_byte_write_espslave(uint8 spi_no,uint8 data)
 	//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
 	// bit15-0 is cmd value.
 	//0x70000000 is for 8bits cmd, 0x04 is eps8266 slave write cmd value
-	WRITE_PERI_REG(SPI_USER2(spi_no), 
+	WRITE_PERI_REG(SPI_USER2(spi_no),
 					((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|4);
 	WRITE_PERI_REG(SPI_W0(spi_no), (uint32)(data));
 	SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
@@ -424,10 +424,10 @@ void spi_byte_write_espslave(uint8 spi_no,uint8 data)
 		//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
 	// bit15-0 is cmd value.
 	//0x70000000 is for 8bits cmd, 0x06 is eps8266 slave read cmd value
-	WRITE_PERI_REG(SPI_USER2(spi_no), 
+	WRITE_PERI_REG(SPI_USER2(spi_no),
 					((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|6);
 	SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
-	
+
 	while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
 	*data=(uint8)(READ_PERI_REG(SPI_W0(spi_no))&0xff);
  }
@@ -440,7 +440,7 @@ void spi_byte_write_espslave(uint8 spi_no,uint8 data)
 *******************************************************************************/
 void spi_slave_init(uint8 spi_no)
 {
-    uint32 regvalue; 
+    uint32 regvalue;
     if(spi_no>1)
         return; //handle invalid input number
 
@@ -450,29 +450,29 @@ void spi_slave_init(uint8 spi_no)
     ////WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9//TEST
     if(spi_no==SPI_SPI){
         PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode
-        PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode	
-        PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode	
-        PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode	
+        PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode
+        PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode
+        PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode
     }else if(spi_no==SPI_HSPI){
         PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
-        PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode	
-        PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode	
-        PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode	
+        PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
+        PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
+        PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
     }
 
     //regvalue=READ_PERI_REG(SPI_FLASH_SLAVE(spi_no));
     //slave mode,slave use buffers which are register "SPI_FLASH_C0~C15", enable trans done isr
     //set bit 30 bit 29 bit9,bit9 is trans done isr mask
-    SET_PERI_REG_MASK(	SPI_SLAVE(spi_no), 
+    SET_PERI_REG_MASK(	SPI_SLAVE(spi_no),
     						SPI_SLAVE_MODE|SPI_SLV_WR_RD_BUF_EN|
                                          	SPI_SLV_WR_BUF_DONE_EN|SPI_SLV_RD_BUF_DONE_EN|
                                          	SPI_SLV_WR_STA_DONE_EN|SPI_SLV_RD_STA_DONE_EN|
                                          	SPI_TRANS_DONE_EN);
-    //disable general trans intr 
+    //disable general trans intr
     //CLEAR_PERI_REG_MASK(SPI_SLAVE(spi_no),SPI_TRANS_DONE_EN);
 
     CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);//disable flash operation mode
-    SET_PERI_REG_MASK(SPI_USER(spi_no),SPI_USR_MISO_HIGHPART);//SLAVE SEND DATA BUFFER IN C8-C15 
+    SET_PERI_REG_MASK(SPI_USER(spi_no),SPI_USR_MISO_HIGHPART);//SLAVE SEND DATA BUFFER IN C8-C15
 
 
 //////**************RUN WHEN SLAVE RECIEVE*******************///////
@@ -482,12 +482,12 @@ void spi_slave_init(uint8 spi_no)
     WRITE_PERI_REG(SPI_CLOCK(spi_no), 0);
 
 
-    
-/////***************************************************//////	
 
-    //set 8 bit slave command length, because slave must have at least one bit addr, 
-    //8 bit slave+8bit addr, so master device first 2 bytes can be regarded as a command 
-    //and the  following bytes are datas, 
+/////***************************************************//////
+
+    //set 8 bit slave command length, because slave must have at least one bit addr,
+    //8 bit slave+8bit addr, so master device first 2 bytes can be regarded as a command
+    //and the  following bytes are datas,
     //32 bytes input wil be stored in SPI_FLASH_C0-C7
     //32 bytes output data should be set to SPI_FLASH_C8-C15
     WRITE_PERI_REG(SPI_USER2(spi_no), (0x7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S); //0x70000000
@@ -498,15 +498,15 @@ void spi_slave_init(uint8 spi_no)
                                                                                         ((0x7&SPI_SLV_STATUS_BITLEN)<<SPI_SLV_STATUS_BITLEN_S)|
                                                                                        ((0x7&SPI_SLV_WR_ADDR_BITLEN)<<SPI_SLV_WR_ADDR_BITLEN_S)|
                                                                                        ((0x7&SPI_SLV_RD_ADDR_BITLEN)<<SPI_SLV_RD_ADDR_BITLEN_S));
-    
-    SET_PERI_REG_MASK(SPI_PIN(spi_no),BIT19);//BIT19   
 
-    //maybe enable slave transmission liston 
+    SET_PERI_REG_MASK(SPI_PIN(spi_no),BIT19);//BIT19
+
+    //maybe enable slave transmission liston
     SET_PERI_REG_MASK(SPI_CMD(spi_no),SPI_USR);
     //register level2 isr function, which contains spi, hspi and i2s events
     ETS_SPI_INTR_ATTACH(spi_slave_isr_handler,NULL);
     //enable level2 isr, which contains spi, hspi and i2s events
-    ETS_SPI_INTR_ENABLE(); 
+    ETS_SPI_INTR_ENABLE();
 }
 
 
@@ -531,7 +531,7 @@ void spi_slave_init(uint8 spi_no)
  /******************************************************************************
  * FunctionName : hspi_master_readwrite_repeat
  * Description  : SPI master test  function for reading and writing esp8266 slave buffer,
- 			the function uses HSPI module 
+ 			the function uses HSPI module
 *******************************************************************************/
 os_timer_t timer2;
 
@@ -556,7 +556,7 @@ void hspi_master_readwrite_repeat(void)
 /******************************************************************************
  * FunctionName : spi_slave_isr_handler
  * Description  : SPI interrupt function, SPI HSPI and I2S interrupt can trig this function
- 			   some basic operation like clear isr flag has been done, 
+ 			   some basic operation like clear isr flag has been done,
  			   and it is availible	for adding user coder in the funtion
  * Parameters  : void *para- function parameter address, which has been registered in function spi_slave_init
 *******************************************************************************/
@@ -578,7 +578,7 @@ os_event_t * spiQueue;
 #define DATA_ERROR 6
 #define STATUS_R_IN_RD 7
 //init the two intr line of slave
-//gpio0: wr_ready ,and  
+//gpio0: wr_ready ,and
 //gpio2: rd_ready , controlled by slave
 void ICACHE_FLASH_ATTR
     gpio_init()
@@ -600,32 +600,32 @@ void spi_slave_isr_handler(void *para)
     	static uint8 state =0;
 	uint32 recv_data,send_data;
 
-	if(READ_PERI_REG(0x3ff00020)&BIT4){		
+	if(READ_PERI_REG(0x3ff00020)&BIT4){
         //following 3 lines is to clear isr signal
         	CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI_SPI), 0x3ff);
     	}else if(READ_PERI_REG(0x3ff00020)&BIT7){ //bit7 is for hspi isr,
         	regvalue=READ_PERI_REG(SPI_SLAVE(SPI_HSPI));
-         	CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI_HSPI),  
+         	CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI_HSPI),
 								SPI_TRANS_DONE_EN|
 								SPI_SLV_WR_STA_DONE_EN|
 								SPI_SLV_RD_STA_DONE_EN|
 								SPI_SLV_WR_BUF_DONE_EN|
 								SPI_SLV_RD_BUF_DONE_EN);
         	SET_PERI_REG_MASK(SPI_SLAVE(SPI_HSPI), SPI_SYNC_RESET);
-        	CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI_HSPI),  
+        	CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI_HSPI),
 								SPI_TRANS_DONE|
 								SPI_SLV_WR_STA_DONE|
 								SPI_SLV_RD_STA_DONE|
 								SPI_SLV_WR_BUF_DONE|
-								SPI_SLV_RD_BUF_DONE); 
-		SET_PERI_REG_MASK(SPI_SLAVE(SPI_HSPI),  
+								SPI_SLV_RD_BUF_DONE);
+		SET_PERI_REG_MASK(SPI_SLAVE(SPI_HSPI),
 								SPI_TRANS_DONE_EN|
 								SPI_SLV_WR_STA_DONE_EN|
 								SPI_SLV_RD_STA_DONE_EN|
 								SPI_SLV_WR_BUF_DONE_EN|
 								SPI_SLV_RD_BUF_DONE_EN);
 
-		if(regvalue&SPI_SLV_WR_BUF_DONE){ 
+		if(regvalue&SPI_SLV_WR_BUF_DONE){
             		GPIO_OUTPUT_SET(0, 0);
             		idx=0;
             		while(idx<8){
@@ -646,7 +646,7 @@ void spi_slave_isr_handler(void *para)
 			//system_os_post(USER_TASK_PRIO_1,WR_RD,regvalue);
 
         	}
-    
+
     }else if(READ_PERI_REG(0x3ff00020)&BIT9){ //bit7 is for i2s isr,
 
     }
@@ -698,19 +698,19 @@ void ICACHE_FLASH_ATTR
 		break;
 	case STATUS_W:
 		os_printf("SW ERR,Reg:%08x\n",e->par);
-		break;	
+		break;
 	case TR_DONE_ALONE:
 		os_printf("TD ALO ERR,Reg:%08x\n",e->par);
-		break;	
+		break;
 	case WR_RD:
 		os_printf("WR&RD ERR,Reg:%08x\n",e->par);
-		break;	
+		break;
 	case DATA_ERROR:
 		os_printf("Data ERR,Reg:%08x\n",e->par);
 		break;
 	case STATUS_R_IN_RD :
 		os_printf("SR ERR in RDPR,Reg:%08x\n",e->par);
-		break;	
+		break;
         default:
             break;
     }
@@ -738,7 +738,7 @@ void ICACHE_FLASH_ATTR
     os_printf("spi miso init\n\r");
     set_miso_data();
 #endif
-    
+
     //os_timer_disarm(&spi_timer_test);
     //os_timer_setfn(&spi_timer_test, (os_timer_func_t *)set_miso_data, NULL);//wjl
     //os_timer_arm(&spi_timer_test,50,1);

+ 13 - 13
app/driver/switec.c

@@ -1,6 +1,6 @@
 /*
  * Module for interfacing with Switec instrument steppers (and
- * similar devices). These are the steppers that are used in automotive 
+ * similar devices). These are the steppers that are used in automotive
  * instrument panels and the like. Run off 5 volts at low current.
  *
  * Code inspired by:
@@ -81,7 +81,7 @@ static void ICACHE_RAM_ATTR timer_interrupt(os_param_t);
 
 
 // Just takes the channel number
-int switec_close(uint32_t channel) 
+int switec_close(uint32_t channel)
 {
   if (channel >= sizeof(data) / sizeof(data[0])) {
     return -1;
@@ -118,28 +118,28 @@ int switec_close(uint32_t channel)
   return 0;
 }
 
-static __attribute__((always_inline)) inline void write_io(DATA *d) 
+static __attribute__((always_inline)) inline void write_io(DATA *d)
 {
   uint32_t pin_state = d->pinstate[d->current_state];
 
   gpio_output_set(pin_state, d->mask & ~pin_state, 0, 0);
 }
 
-static __attribute__((always_inline)) inline  void step_up(DATA *d) 
+static __attribute__((always_inline)) inline  void step_up(DATA *d)
 {
   d->current_step++;
   d->current_state = (d->current_state + 1) % N_STATES;
   write_io(d);
 }
 
-static __attribute__((always_inline)) inline  void step_down(DATA *d) 
+static __attribute__((always_inline)) inline  void step_down(DATA *d)
 {
   d->current_step--;
   d->current_state = (d->current_state + N_STATES - 1) % N_STATES;
   write_io(d);
 }
 
-static void ICACHE_RAM_ATTR timer_interrupt(os_param_t p) 
+static void ICACHE_RAM_ATTR timer_interrupt(os_param_t p)
 {
   // This function really is running at interrupt level with everything
   // else masked off. It should take as little time as necessary.
@@ -179,9 +179,9 @@ static void ICACHE_RAM_ATTR timer_interrupt(os_param_t p)
     if (d->vel == 0) {
       d->dir = d->current_step < d->target_step ? 1 : -1;
       // do not set to 0 or it could go negative in case 2 below
-      d->vel = 1; 
+      d->vel = 1;
     }
-    
+
     // Move the pointer by one step in the correct direction
     if (d->dir > 0) {
       step_up(d);
@@ -192,7 +192,7 @@ static void ICACHE_RAM_ATTR timer_interrupt(os_param_t p)
     // determine delta, number of steps in current direction to target.
     // may be negative if we are headed away from target
     int delta = d->dir > 0 ? d->target_step - d->current_step : d->current_step - d->target_step;
-    
+
     if (delta > 0) {
       // case 1 : moving towards target (maybe under accel or decel)
       if (delta <= d->vel) {
@@ -208,7 +208,7 @@ static void ICACHE_RAM_ATTR timer_interrupt(os_param_t p)
       // case 2 : at or moving away from target (slow down!)
       d->vel--;
     }
-    
+
     // vel now defines delay
     uint8_t row = 0;
     // this is why vel must not be greater than the last vel in the table.
@@ -232,7 +232,7 @@ static void ICACHE_RAM_ATTR timer_interrupt(os_param_t p)
     if (need_to_wait < delay) {
       delay = need_to_wait;
     }
-  } 
+  }
 
   if (delay < 1000000) {
     if (delay < 50) {
@@ -367,11 +367,11 @@ int switec_moveto(uint32_t channel, int pos)
     }
   }
 
-  return 0;  
+  return 0;
 }
 
 // Get the current position, direction and target position
-int switec_getpos(uint32_t channel, int32_t *pos, int32_t *dir, int32_t *target) 
+int switec_getpos(uint32_t channel, int32_t *pos, int32_t *dir, int32_t *target)
 {
   if (channel >= sizeof(data) / sizeof(data[0])) {
     return -1;

+ 3 - 3
app/driver/uart.c

@@ -307,7 +307,7 @@ uart0_rx_intr_handler(void *para)
     }
 }
 
-static void 
+static void
 uart_autobaud_timeout(void *timer_arg)
 {
   uint32_t uart_no = (uint32_t) timer_arg;
@@ -325,7 +325,7 @@ uart_autobaud_timeout(void *timer_arg)
 }
 #include "pm/swtimer.h"
 
-static void 
+static void
 uart_init_autobaud(uint32_t uart_no)
 {
   os_timer_setfn(&autobaud_timer, uart_autobaud_timeout, (void *) uart_no);
@@ -334,7 +334,7 @@ uart_init_autobaud(uint32_t uart_no)
   os_timer_arm(&autobaud_timer, 100, TRUE);
 }
 
-static void 
+static void
 uart_stop_autobaud()
 {
   os_timer_disarm(&autobaud_timer);

+ 1 - 1
app/esp-gdbstub/Makefile

@@ -23,7 +23,7 @@ endif
 #   makefile at its root level - these are then overridden
 #   for a subtree within the makefile rooted therein
 #
-#DEFINES += -DGDBSTUB_REDIRECT_CONSOLE_OUTPUT 
+#DEFINES += -DGDBSTUB_REDIRECT_CONSOLE_OUTPUT
 
 #############################################################
 # Recursion Magic - Don't touch this!!

+ 4 - 4
app/esp-gdbstub/gdbstub-cfg.h

@@ -10,9 +10,9 @@ and do some other magic to make everything work and compile under FreeRTOS.
 #endif
 
 /*
-Enable this to make the exception and debugging handlers switch to a private stack. This will use 
+Enable this to make the exception and debugging handlers switch to a private stack. This will use
 up 1K of RAM, but may be useful if you're debugging stack or stack pointer corruption problems. It's
-normally disabled because not many situations need it. If for some reason the GDB communication 
+normally disabled because not many situations need it. If for some reason the GDB communication
 stops when you run into an error in your code, try enabling this.
 */
 #ifndef GDBSTUB_USE_OWN_STACK
@@ -30,7 +30,7 @@ the gdbstub_init call.
 #endif
 
 /*
-Enabling this will redirect console output to GDB. This basically means that printf/os_printf output 
+Enabling this will redirect console output to GDB. This basically means that printf/os_printf output
 will show up in your gdb session, which is useful if you use gdb to do stuff. It also means that if
 you use a normal terminal, you can't read the printfs anymore.
 */
@@ -52,7 +52,7 @@ Gdbstub functions are placed in flash or IRAM using attributes, as defined here.
 (and related) can always be in flash, because it's called in the normal code flow. The rest of the
 gdbstub functions can be in flash too, but only if there's no chance of them being called when the
 flash somehow is disabled (eg during SPI operations or flash write/erase operations). If the routines
-are called when the flash is disabled (eg due to a Ctrl-C at the wrong time), the ESP8266 will most 
+are called when the flash is disabled (eg due to a Ctrl-C at the wrong time), the ESP8266 will most
 likely crash.
 */
 #define ATTR_GDBINIT	ICACHE_FLASH_ATTR

+ 5 - 5
app/esp-gdbstub/gdbstub-entry.S

@@ -46,9 +46,9 @@ The savedRegs struct:
 */
 
 /*
-This is the debugging exception routine; it's called by the debugging vector 
+This is the debugging exception routine; it's called by the debugging vector
 
-We arrive here with all regs intact except for a2. The old contents of A2 are saved 
+We arrive here with all regs intact except for a2. The old contents of A2 are saved
 into the DEBUG_EXCSAVE special function register. EPC is the original PC.
 */
 gdbstub_debug_exception_entry:
@@ -170,7 +170,7 @@ DebugExceptionExit:
 FreeRTOS exception handling code. For some reason or another, we can't just hook the main exception vector: it
 seems FreeRTOS uses that for something else too (interrupts). FreeRTOS has its own fatal exception handler, and we
 hook that. Unfortunately, that one is called from a few different places (eg directly in the DoubleExceptionVector)
-so the precise location of the original register values are somewhat of a mystery when we arrive here... 
+so the precise location of the original register values are somewhat of a mystery when we arrive here...
 
 As a 'solution', we'll just decode the most common case of the user_fatal_exception_handler being called from
 the user exception handler vector:
@@ -350,14 +350,14 @@ gdbstub_set_hw_watchpoint:
 	bany	a6, a5, return_w_error
 	//Set watchpoint
 	wsr		a2, DBREAKA
-	
+
 	//Combine type and mask
 	movi	a6, 0x3F
 	and		a3, a3, a6
 	slli	a4, a4, 30
 	or		a3, a3, a4
 	wsr		a3, DBREAKC
-	
+
 //	movi	a2, 1
 	mov		a2, a3
 	isync

+ 10 - 10
app/esp-gdbstub/gdbstub.c

@@ -1,7 +1,7 @@
 /******************************************************************************
  * Copyright 2015 Espressif Systems
  *
- * Description: A stub to make the ESP8266 debuggable by GDB over the serial 
+ * Description: A stub to make the ESP8266 debuggable by GDB over the serial
  * port.
  *
  * License: ESPRESSIF MIT License
@@ -267,7 +267,7 @@ static int ATTR_GDBFN validWrAddr(int p) {
 	return 0;
 }
 
-/* 
+/*
 Register file in the format lx106 gdb port expects it.
 Inspired by gdb/regformats/reg-xtensa.dat from
 https://github.com/jcmvbkbc/crosstool-NG/blob/lx106-g%2B%2B/overlays/xtensa_lx106.tar
@@ -470,7 +470,7 @@ static int ATTR_GDBFN gdbHandleCommand(unsigned char *cmd, int len) {
 
 //Lower layer: grab a command packet and check the checksum
 //Calls gdbHandleCommand on the packet if the checksum is OK
-//Returns ST_OK on success, ST_ERR when checksum fails, a 
+//Returns ST_OK on success, ST_ERR when checksum fails, a
 //character if it is received instead of the GDB packet
 //start char.
 static int ATTR_GDBFN gdbReadCommand() {
@@ -580,7 +580,7 @@ void ATTR_GDBFN gdbstub_handle_debug_exception() {
 	while(gdbReadCommand()!=ST_CONT);
 	if ((gdbstub_savedRegs.reason&0x84)==0x4) {
 		//We stopped due to a watchpoint. We can't re-execute the current instruction
-		//because it will happily re-trigger the same watchpoint, so we emulate it 
+		//because it will happily re-trigger the same watchpoint, so we emulate it
 		//while we're still in debugger space.
 		emulLdSt();
 	} else if ((gdbstub_savedRegs.reason&0x88)==0x8) {
@@ -659,12 +659,12 @@ static void ATTR_GDBFN gdb_semihost_putchar1(char c) {
 }
 
 #if !GDBSTUB_FREERTOS
-//The OS-less SDK uses the Xtensa HAL to handle exceptions. We can use those functions to catch any 
+//The OS-less SDK uses the Xtensa HAL to handle exceptions. We can use those functions to catch any
 //fatal exceptions and invoke the debugger when this happens.
 static void ATTR_GDBINIT install_exceptions() {
 	int i;
 	int exno[]={EXCCAUSE_ILLEGAL, EXCCAUSE_SYSCALL, EXCCAUSE_INSTR_ERROR, EXCCAUSE_LOAD_STORE_ERROR,
-			EXCCAUSE_DIVIDE_BY_ZERO, EXCCAUSE_UNALIGNED, EXCCAUSE_INSTR_DATA_ERROR, EXCCAUSE_LOAD_STORE_DATA_ERROR, 
+			EXCCAUSE_DIVIDE_BY_ZERO, EXCCAUSE_UNALIGNED, EXCCAUSE_INSTR_DATA_ERROR, EXCCAUSE_LOAD_STORE_DATA_ERROR,
 			EXCCAUSE_INSTR_ADDR_ERROR, EXCCAUSE_LOAD_STORE_ADDR_ERROR, EXCCAUSE_INSTR_PROHIBITED,
 			EXCCAUSE_LOAD_PROHIBITED, EXCCAUSE_STORE_PROHIBITED};
 	for (i=0; i<(sizeof(exno)/sizeof(exno[0])); i++) {
@@ -708,9 +708,9 @@ static void ATTR_GDBFN uart_hdlr(void *arg, void *frame) {
 		//Copy registers the Xtensa HAL did save to gdbstub_savedRegs
 		os_memcpy(&gdbstub_savedRegs, frame, 19*4);
 		gdbstub_savedRegs.a1=(uint32_t)frame+EXCEPTION_GDB_SP_OFFSET;
-	
+
 		gdbstub_savedRegs.reason=0xff; //mark as user break reason
-	
+
 		ets_wdt_disable();
 		sendReason();
 		xthal_set_intenable(0);
@@ -749,9 +749,9 @@ void ATTR_GDBFN gdbstub_handle_uart_int(struct XTensa_rtos_int_frame_s *frame) {
 		for (x=2; x<16; x++) gdbstub_savedRegs.a[x-2]=frame->a[x];
 
 //		gdbstub_savedRegs.a1=(uint32_t)frame+EXCEPTION_GDB_SP_OFFSET;
-	
+
 		gdbstub_savedRegs.reason=0xff; //mark as user break reason
-	
+
 //		ets_wdt_disable();
 		sendReason();
 		while(gdbReadCommand()!=ST_CONT);

+ 52 - 52
app/fatfs/Makefile

@@ -1,52 +1,52 @@
-
-#############################################################
-# Required variables for each makefile
-# Discard this section from all parent makefiles
-# Expected variables (with automatic defaults):
-#   CSRCS (all "C" files in the dir)
-#   SUBDIRS (all subdirs with a Makefile)
-#   GEN_LIBS - list of libs to be generated ()
-#   GEN_IMAGES - list of images to be generated ()
-#   COMPONENTS_xxx - a list of libs/objs in the form
-#     subdir/lib to be extracted and rolled up into
-#     a generated lib/image xxx.a ()
-#
-ifndef PDIR
-GEN_LIBS = libfatfs.a
-endif
-
-ifndef FATFS_INC_DIR
-FATFS_INC_DIR = ./
-endif
-
-STD_CFLAGS=-std=gnu11 -Wimplicit -imacros $(FATFS_INC_DIR)fatfs_prefix_lib.h
-
-#############################################################
-# Configuration i.e. compile options etc.
-# Target specific stuff (defines etc.) goes in here!
-# Generally values applying to a tree are captured in the
-#   makefile at its root level - these are then overridden
-#   for a subtree within the makefile rooted therein
-#
-#DEFINES += 
-
-#############################################################
-# Recursion Magic - Don't touch this!!
-#
-# Each subtree potentially has an include directory
-#   corresponding to the common APIs applicable to modules
-#   rooted at that subtree. Accordingly, the INCLUDE PATH
-#   of a module can only contain the include directories up
-#   its parent path, and not its siblings
-#
-# Required for each makefile to inherit from the parent
-#
-
-INCLUDES := $(INCLUDES) -I $(PDIR)include
-INCLUDES += -I ./
-INCLUDES += -I ../platform
-INCLUDES += -I ../libc
-INCLUDES += -I ../lua
-PDIR := ../$(PDIR)
-sinclude $(PDIR)Makefile
-
+
+#############################################################
+# Required variables for each makefile
+# Discard this section from all parent makefiles
+# Expected variables (with automatic defaults):
+#   CSRCS (all "C" files in the dir)
+#   SUBDIRS (all subdirs with a Makefile)
+#   GEN_LIBS - list of libs to be generated ()
+#   GEN_IMAGES - list of images to be generated ()
+#   COMPONENTS_xxx - a list of libs/objs in the form
+#     subdir/lib to be extracted and rolled up into
+#     a generated lib/image xxx.a ()
+#
+ifndef PDIR
+GEN_LIBS = libfatfs.a
+endif
+
+ifndef FATFS_INC_DIR
+FATFS_INC_DIR = ./
+endif
+
+STD_CFLAGS=-std=gnu11 -Wimplicit -imacros $(FATFS_INC_DIR)fatfs_prefix_lib.h
+
+#############################################################
+# Configuration i.e. compile options etc.
+# Target specific stuff (defines etc.) goes in here!
+# Generally values applying to a tree are captured in the
+#   makefile at its root level - these are then overridden
+#   for a subtree within the makefile rooted therein
+#
+#DEFINES +=
+
+#############################################################
+# Recursion Magic - Don't touch this!!
+#
+# Each subtree potentially has an include directory
+#   corresponding to the common APIs applicable to modules
+#   rooted at that subtree. Accordingly, the INCLUDE PATH
+#   of a module can only contain the include directories up
+#   its parent path, and not its siblings
+#
+# Required for each makefile to inherit from the parent
+#
+
+INCLUDES := $(INCLUDES) -I $(PDIR)include
+INCLUDES += -I ./
+INCLUDES += -I ../platform
+INCLUDES += -I ../libc
+INCLUDES += -I ../lua
+PDIR := ../$(PDIR)
+sinclude $(PDIR)Makefile
+

+ 119 - 119
app/fatfs/diskio.c

@@ -1,119 +1,119 @@
-/*-----------------------------------------------------------------------*/
-/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2016        */
-/*-----------------------------------------------------------------------*/
-/* If a working storage control module is available, it should be        */
-/* attached to the FatFs via a glue function rather than modifying it.   */
-/* This is an example of glue functions to attach various exsisting      */
-/* storage control modules to the FatFs module with a defined API.       */
-/*-----------------------------------------------------------------------*/
-
-#include "ff.h"			/* Obtains integer types */
-#include "diskio.h"		/* FatFs lower layer API */
-#include "sdcard.h"
-
-static DSTATUS m_status = STA_NOINIT;
-
-/*-----------------------------------------------------------------------*/
-/* Get Drive Status                                                      */
-/*-----------------------------------------------------------------------*/
-
-DSTATUS disk_status (
-	BYTE pdrv		/* Physical drive nmuber to identify the drive */
-)
-{
-  return m_status;
-}
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Inidialize a Drive                                                    */
-/*-----------------------------------------------------------------------*/
-
-DSTATUS disk_initialize (
-	BYTE pdrv				/* Physical drive nmuber to identify the drive */
-)
-{
-  int result;
-
-  if (platform_sdcard_init( 1, pdrv )) {
-    m_status &= ~STA_NOINIT;
-  }
-
-  return m_status;
-}
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Read Sector(s)                                                        */
-/*-----------------------------------------------------------------------*/
-
-DRESULT disk_read (
-	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
-	BYTE *buff,		/* Data buffer to store read data */
-	DWORD sector,	/* Sector address in LBA */
-	UINT count		/* Number of sectors to read */
-)
-{
-  if (count == 1) {
-    if (! platform_sdcard_read_block( pdrv, sector, buff )) {
-      return RES_ERROR;
-    }
-  } else {
-    if (! platform_sdcard_read_blocks( pdrv, sector, count, buff )) {
-      return RES_ERROR;
-    }
-  }
-
-  return RES_OK;
-}
-
-
-/*-----------------------------------------------------------------------*/
-/* Write Sector(s)                                                       */
-/*-----------------------------------------------------------------------*/
-
-#if FF_FS_READONLY == 0
-
-DRESULT disk_write (
-	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
-	const BYTE *buff,	/* Data to be written */
-	DWORD sector,		/* Sector address in LBA */
-	UINT count			/* Number of sectors to write */
-)
-{
-  if (count == 1) {
-    if (! platform_sdcard_write_block( pdrv, sector, buff )) {
-      return RES_ERROR;
-    }
-  } else {
-    if (! platform_sdcard_write_blocks( pdrv, sector, count, buff )) {
-      return RES_ERROR;
-    }
-  }
-
-  return RES_OK;
-}
-
-#endif
-
-/*-----------------------------------------------------------------------*/
-/* Miscellaneous Functions                                               */
-/*-----------------------------------------------------------------------*/
-
-DRESULT disk_ioctl (
-	BYTE pdrv,		/* Physical drive nmuber (0..) */
-	BYTE cmd,		/* Control code */
-	void *buff		/* Buffer to send/receive control data */
-)
-{
-  switch (cmd) {
-  case CTRL_TRIM:    /* no-op */
-  case CTRL_SYNC:    /* no-op */
-    return RES_OK;
-
-  default:           /* anything else throws parameter error */
-    return RES_PARERR;
-  }
-}
+/*-----------------------------------------------------------------------*/
+/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2016        */
+/*-----------------------------------------------------------------------*/
+/* If a working storage control module is available, it should be        */
+/* attached to the FatFs via a glue function rather than modifying it.   */
+/* This is an example of glue functions to attach various exsisting      */
+/* storage control modules to the FatFs module with a defined API.       */
+/*-----------------------------------------------------------------------*/
+
+#include "ff.h"			/* Obtains integer types */
+#include "diskio.h"		/* FatFs lower layer API */
+#include "sdcard.h"
+
+static DSTATUS m_status = STA_NOINIT;
+
+/*-----------------------------------------------------------------------*/
+/* Get Drive Status                                                      */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_status (
+	BYTE pdrv		/* Physical drive nmuber to identify the drive */
+)
+{
+  return m_status;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Inidialize a Drive                                                    */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_initialize (
+	BYTE pdrv				/* Physical drive nmuber to identify the drive */
+)
+{
+  int result;
+
+  if (platform_sdcard_init( 1, pdrv )) {
+    m_status &= ~STA_NOINIT;
+  }
+
+  return m_status;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Sector(s)                                                        */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_read (
+	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
+	BYTE *buff,		/* Data buffer to store read data */
+	DWORD sector,	/* Sector address in LBA */
+	UINT count		/* Number of sectors to read */
+)
+{
+  if (count == 1) {
+    if (! platform_sdcard_read_block( pdrv, sector, buff )) {
+      return RES_ERROR;
+    }
+  } else {
+    if (! platform_sdcard_read_blocks( pdrv, sector, count, buff )) {
+      return RES_ERROR;
+    }
+  }
+
+  return RES_OK;
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* Write Sector(s)                                                       */
+/*-----------------------------------------------------------------------*/
+
+#if FF_FS_READONLY == 0
+
+DRESULT disk_write (
+	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
+	const BYTE *buff,	/* Data to be written */
+	DWORD sector,		/* Sector address in LBA */
+	UINT count			/* Number of sectors to write */
+)
+{
+  if (count == 1) {
+    if (! platform_sdcard_write_block( pdrv, sector, buff )) {
+      return RES_ERROR;
+    }
+  } else {
+    if (! platform_sdcard_write_blocks( pdrv, sector, count, buff )) {
+      return RES_ERROR;
+    }
+  }
+
+  return RES_OK;
+}
+
+#endif
+
+/*-----------------------------------------------------------------------*/
+/* Miscellaneous Functions                                               */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_ioctl (
+	BYTE pdrv,		/* Physical drive nmuber (0..) */
+	BYTE cmd,		/* Control code */
+	void *buff		/* Buffer to send/receive control data */
+)
+{
+  switch (cmd) {
+  case CTRL_TRIM:    /* no-op */
+  case CTRL_SYNC:    /* no-op */
+    return RES_OK;
+
+  default:           /* anything else throws parameter error */
+    return RES_PARERR;
+  }
+}

+ 77 - 77
app/fatfs/diskio.h

@@ -1,77 +1,77 @@
-/*-----------------------------------------------------------------------/
-/  Low level disk interface modlue include file   (C)ChaN, 2014          /
-/-----------------------------------------------------------------------*/
-
-#ifndef _DISKIO_DEFINED
-#define _DISKIO_DEFINED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Status of Disk Functions */
-typedef BYTE	DSTATUS;
-
-/* Results of Disk Functions */
-typedef enum {
-	RES_OK = 0,		/* 0: Successful */
-	RES_ERROR,		/* 1: R/W Error */
-	RES_WRPRT,		/* 2: Write Protected */
-	RES_NOTRDY,		/* 3: Not Ready */
-	RES_PARERR		/* 4: Invalid Parameter */
-} DRESULT;
-
-
-/*---------------------------------------*/
-/* Prototypes for disk control functions */
-
-
-DSTATUS disk_initialize (BYTE pdrv);
-DSTATUS disk_status (BYTE pdrv);
-DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
-DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
-DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
-
-
-/* Disk Status Bits (DSTATUS) */
-
-#define STA_NOINIT		0x01	/* Drive not initialized */
-#define STA_NODISK		0x02	/* No medium in the drive */
-#define STA_PROTECT		0x04	/* Write protected */
-
-
-/* Command code for disk_ioctrl fucntion */
-
-/* Generic command (Used by FatFs) */
-#define CTRL_SYNC			0	/* Complete pending write process (needed at FF_FS_READONLY == 0) */
-#define GET_SECTOR_COUNT	1	/* Get media size (needed at FF_USE_MKFS == 1) */
-#define GET_SECTOR_SIZE		2	/* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
-#define GET_BLOCK_SIZE		3	/* Get erase block size (needed at FF_USE_MKFS == 1) */
-#define CTRL_TRIM			4	/* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
-
-/* Generic command (Not used by FatFs) */
-#define CTRL_POWER			5	/* Get/Set power status */
-#define CTRL_LOCK			6	/* Lock/Unlock media removal */
-#define CTRL_EJECT			7	/* Eject media */
-#define CTRL_FORMAT			8	/* Create physical format on the media */
-
-/* MMC/SDC specific ioctl command */
-#define MMC_GET_TYPE		10	/* Get card type */
-#define MMC_GET_CSD			11	/* Get CSD */
-#define MMC_GET_CID			12	/* Get CID */
-#define MMC_GET_OCR			13	/* Get OCR */
-#define MMC_GET_SDSTAT		14	/* Get SD status */
-#define ISDIO_READ			55	/* Read data form SD iSDIO register */
-#define ISDIO_WRITE			56	/* Write data to SD iSDIO register */
-#define ISDIO_MRITE			57	/* Masked write data to SD iSDIO register */
-
-/* ATA/CF specific ioctl command */
-#define ATA_GET_REV			20	/* Get F/W revision */
-#define ATA_GET_MODEL		21	/* Get model name */
-#define ATA_GET_SN			22	/* Get serial number */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*-----------------------------------------------------------------------/
+/  Low level disk interface modlue include file   (C)ChaN, 2014          /
+/-----------------------------------------------------------------------*/
+
+#ifndef _DISKIO_DEFINED
+#define _DISKIO_DEFINED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Status of Disk Functions */
+typedef BYTE	DSTATUS;
+
+/* Results of Disk Functions */
+typedef enum {
+	RES_OK = 0,		/* 0: Successful */
+	RES_ERROR,		/* 1: R/W Error */
+	RES_WRPRT,		/* 2: Write Protected */
+	RES_NOTRDY,		/* 3: Not Ready */
+	RES_PARERR		/* 4: Invalid Parameter */
+} DRESULT;
+
+
+/*---------------------------------------*/
+/* Prototypes for disk control functions */
+
+
+DSTATUS disk_initialize (BYTE pdrv);
+DSTATUS disk_status (BYTE pdrv);
+DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
+DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
+DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
+
+
+/* Disk Status Bits (DSTATUS) */
+
+#define STA_NOINIT		0x01	/* Drive not initialized */
+#define STA_NODISK		0x02	/* No medium in the drive */
+#define STA_PROTECT		0x04	/* Write protected */
+
+
+/* Command code for disk_ioctrl fucntion */
+
+/* Generic command (Used by FatFs) */
+#define CTRL_SYNC			0	/* Complete pending write process (needed at FF_FS_READONLY == 0) */
+#define GET_SECTOR_COUNT	1	/* Get media size (needed at FF_USE_MKFS == 1) */
+#define GET_SECTOR_SIZE		2	/* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
+#define GET_BLOCK_SIZE		3	/* Get erase block size (needed at FF_USE_MKFS == 1) */
+#define CTRL_TRIM			4	/* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
+
+/* Generic command (Not used by FatFs) */
+#define CTRL_POWER			5	/* Get/Set power status */
+#define CTRL_LOCK			6	/* Lock/Unlock media removal */
+#define CTRL_EJECT			7	/* Eject media */
+#define CTRL_FORMAT			8	/* Create physical format on the media */
+
+/* MMC/SDC specific ioctl command */
+#define MMC_GET_TYPE		10	/* Get card type */
+#define MMC_GET_CSD			11	/* Get CSD */
+#define MMC_GET_CID			12	/* Get CID */
+#define MMC_GET_OCR			13	/* Get OCR */
+#define MMC_GET_SDSTAT		14	/* Get SD status */
+#define ISDIO_READ			55	/* Read data form SD iSDIO register */
+#define ISDIO_WRITE			56	/* Write data to SD iSDIO register */
+#define ISDIO_MRITE			57	/* Masked write data to SD iSDIO register */
+
+/* ATA/CF specific ioctl command */
+#define ATA_GET_REV			20	/* Get F/W revision */
+#define ATA_GET_MODEL		21	/* Get model name */
+#define ATA_GET_SN			22	/* Get serial number */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 6554 - 6554
app/fatfs/ff.c

@@ -1,6554 +1,6554 @@
-/*----------------------------------------------------------------------------/
-/  FatFs - Generic FAT Filesystem Module  R0.13c                              /
-/-----------------------------------------------------------------------------/
-/
-/ Copyright (C) 2018, ChaN, all right reserved.
-/
-/ FatFs module is an open source software. Redistribution and use of FatFs in
-/ source and binary forms, with or without modification, are permitted provided
-/ that the following condition is met:
-/
-/ 1. Redistributions of source code must retain the above copyright notice,
-/    this condition and the following disclaimer.
-/
-/ This software is provided by the copyright holder and contributors "AS IS"
-/ and any warranties related to this software are DISCLAIMED.
-/ The copyright owner or contributors be NOT LIABLE for any damages caused
-/ by use of this software.
-/
-/----------------------------------------------------------------------------*/
-
-
-#include "ff.h"			/* Declarations of FatFs API */
-#include "diskio.h"		/* Declarations of device I/O functions */
-
-
-/*--------------------------------------------------------------------------
-
-   Module Private Definitions
-
----------------------------------------------------------------------------*/
-
-#if FF_DEFINED != 86604	/* Revision ID */
-#error Wrong include file (ff.h).
-#endif
-
-
-/* Limits and boundaries */
-#define MAX_DIR		0x200000		/* Max size of FAT directory */
-#define MAX_DIR_EX	0x10000000		/* Max size of exFAT directory */
-#define MAX_FAT12	0xFF5			/* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
-#define MAX_FAT16	0xFFF5			/* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
-#define MAX_FAT32	0x0FFFFFF5		/* Max FAT32 clusters (not specified, practical limit) */
-#define MAX_EXFAT	0x7FFFFFFD		/* Max exFAT clusters (differs from specs, implementation limit) */
-
-
-/* Character code support macros */
-#define IsUpper(c)		((c) >= 'A' && (c) <= 'Z')
-#define IsLower(c)		((c) >= 'a' && (c) <= 'z')
-#define IsDigit(c)		((c) >= '0' && (c) <= '9')
-#define IsSurrogate(c)	((c) >= 0xD800 && (c) <= 0xDFFF)
-#define IsSurrogateH(c)	((c) >= 0xD800 && (c) <= 0xDBFF)
-#define IsSurrogateL(c)	((c) >= 0xDC00 && (c) <= 0xDFFF)
-
-
-/* Additional file access control and file status flags for internal use */
-#define FA_SEEKEND	0x20	/* Seek to end of the file on file open */
-#define FA_MODIFIED	0x40	/* File has been modified */
-#define FA_DIRTY	0x80	/* FIL.buf[] needs to be written-back */
-
-
-/* Additional file attribute bits for internal use */
-#define AM_VOL		0x08	/* Volume label */
-#define AM_LFN		0x0F	/* LFN entry */
-#define AM_MASK		0x3F	/* Mask of defined bits */
-
-
-/* Name status flags in fn[11] */
-#define NSFLAG		11		/* Index of the name status byte */
-#define NS_LOSS		0x01	/* Out of 8.3 format */
-#define NS_LFN		0x02	/* Force to create LFN entry */
-#define NS_LAST		0x04	/* Last segment */
-#define NS_BODY		0x08	/* Lower case flag (body) */
-#define NS_EXT		0x10	/* Lower case flag (ext) */
-#define NS_DOT		0x20	/* Dot entry */
-#define NS_NOLFN	0x40	/* Do not find LFN */
-#define NS_NONAME	0x80	/* Not followed */
-
-
-/* exFAT directory entry types */
-#define	ET_BITMAP	0x81	/* Allocation bitmap */
-#define	ET_UPCASE	0x82	/* Up-case table */
-#define	ET_VLABEL	0x83	/* Volume label */
-#define	ET_FILEDIR	0x85	/* File and directory */
-#define	ET_STREAM	0xC0	/* Stream extension */
-#define	ET_FILENAME	0xC1	/* Name extension */
-
-
-/* FatFs refers the FAT structure as simple byte array instead of structure member
-/ because the C structure is not binary compatible between different platforms */
-
-#define BS_JmpBoot			0		/* x86 jump instruction (3-byte) */
-#define BS_OEMName			3		/* OEM name (8-byte) */
-#define BPB_BytsPerSec		11		/* Sector size [byte] (WORD) */
-#define BPB_SecPerClus		13		/* Cluster size [sector] (BYTE) */
-#define BPB_RsvdSecCnt		14		/* Size of reserved area [sector] (WORD) */
-#define BPB_NumFATs			16		/* Number of FATs (BYTE) */
-#define BPB_RootEntCnt		17		/* Size of root directory area for FAT [entry] (WORD) */
-#define BPB_TotSec16		19		/* Volume size (16-bit) [sector] (WORD) */
-#define BPB_Media			21		/* Media descriptor byte (BYTE) */
-#define BPB_FATSz16			22		/* FAT size (16-bit) [sector] (WORD) */
-#define BPB_SecPerTrk		24		/* Number of sectors per track for int13h [sector] (WORD) */
-#define BPB_NumHeads		26		/* Number of heads for int13h (WORD) */
-#define BPB_HiddSec			28		/* Volume offset from top of the drive (DWORD) */
-#define BPB_TotSec32		32		/* Volume size (32-bit) [sector] (DWORD) */
-#define BS_DrvNum			36		/* Physical drive number for int13h (BYTE) */
-#define BS_NTres			37		/* WindowsNT error flag (BYTE) */
-#define BS_BootSig			38		/* Extended boot signature (BYTE) */
-#define BS_VolID			39		/* Volume serial number (DWORD) */
-#define BS_VolLab			43		/* Volume label string (8-byte) */
-#define BS_FilSysType		54		/* Filesystem type string (8-byte) */
-#define BS_BootCode			62		/* Boot code (448-byte) */
-#define BS_55AA				510		/* Signature word (WORD) */
-
-#define BPB_FATSz32			36		/* FAT32: FAT size [sector] (DWORD) */
-#define BPB_ExtFlags32		40		/* FAT32: Extended flags (WORD) */
-#define BPB_FSVer32			42		/* FAT32: Filesystem version (WORD) */
-#define BPB_RootClus32		44		/* FAT32: Root directory cluster (DWORD) */
-#define BPB_FSInfo32		48		/* FAT32: Offset of FSINFO sector (WORD) */
-#define BPB_BkBootSec32		50		/* FAT32: Offset of backup boot sector (WORD) */
-#define BS_DrvNum32			64		/* FAT32: Physical drive number for int13h (BYTE) */
-#define BS_NTres32			65		/* FAT32: Error flag (BYTE) */
-#define BS_BootSig32		66		/* FAT32: Extended boot signature (BYTE) */
-#define BS_VolID32			67		/* FAT32: Volume serial number (DWORD) */
-#define BS_VolLab32			71		/* FAT32: Volume label string (8-byte) */
-#define BS_FilSysType32		82		/* FAT32: Filesystem type string (8-byte) */
-#define BS_BootCode32		90		/* FAT32: Boot code (420-byte) */
-
-#define BPB_ZeroedEx		11		/* exFAT: MBZ field (53-byte) */
-#define BPB_VolOfsEx		64		/* exFAT: Volume offset from top of the drive [sector] (QWORD) */
-#define BPB_TotSecEx		72		/* exFAT: Volume size [sector] (QWORD) */
-#define BPB_FatOfsEx		80		/* exFAT: FAT offset from top of the volume [sector] (DWORD) */
-#define BPB_FatSzEx			84		/* exFAT: FAT size [sector] (DWORD) */
-#define BPB_DataOfsEx		88		/* exFAT: Data offset from top of the volume [sector] (DWORD) */
-#define BPB_NumClusEx		92		/* exFAT: Number of clusters (DWORD) */
-#define BPB_RootClusEx		96		/* exFAT: Root directory start cluster (DWORD) */
-#define BPB_VolIDEx			100		/* exFAT: Volume serial number (DWORD) */
-#define BPB_FSVerEx			104		/* exFAT: Filesystem version (WORD) */
-#define BPB_VolFlagEx		106		/* exFAT: Volume flags (WORD) */
-#define BPB_BytsPerSecEx	108		/* exFAT: Log2 of sector size in unit of byte (BYTE) */
-#define BPB_SecPerClusEx	109		/* exFAT: Log2 of cluster size in unit of sector (BYTE) */
-#define BPB_NumFATsEx		110		/* exFAT: Number of FATs (BYTE) */
-#define BPB_DrvNumEx		111		/* exFAT: Physical drive number for int13h (BYTE) */
-#define BPB_PercInUseEx		112		/* exFAT: Percent in use (BYTE) */
-#define BPB_RsvdEx			113		/* exFAT: Reserved (7-byte) */
-#define BS_BootCodeEx		120		/* exFAT: Boot code (390-byte) */
-
-#define DIR_Name			0		/* Short file name (11-byte) */
-#define DIR_Attr			11		/* Attribute (BYTE) */
-#define DIR_NTres			12		/* Lower case flag (BYTE) */
-#define DIR_CrtTime10		13		/* Created time sub-second (BYTE) */
-#define DIR_CrtTime			14		/* Created time (DWORD) */
-#define DIR_LstAccDate		18		/* Last accessed date (WORD) */
-#define DIR_FstClusHI		20		/* Higher 16-bit of first cluster (WORD) */
-#define DIR_ModTime			22		/* Modified time (DWORD) */
-#define DIR_FstClusLO		26		/* Lower 16-bit of first cluster (WORD) */
-#define DIR_FileSize		28		/* File size (DWORD) */
-#define LDIR_Ord			0		/* LFN: LFN order and LLE flag (BYTE) */
-#define LDIR_Attr			11		/* LFN: LFN attribute (BYTE) */
-#define LDIR_Type			12		/* LFN: Entry type (BYTE) */
-#define LDIR_Chksum			13		/* LFN: Checksum of the SFN (BYTE) */
-#define LDIR_FstClusLO		26		/* LFN: MBZ field (WORD) */
-#define XDIR_Type			0		/* exFAT: Type of exFAT directory entry (BYTE) */
-#define XDIR_NumLabel		1		/* exFAT: Number of volume label characters (BYTE) */
-#define XDIR_Label			2		/* exFAT: Volume label (11-WORD) */
-#define XDIR_CaseSum		4		/* exFAT: Sum of case conversion table (DWORD) */
-#define XDIR_NumSec			1		/* exFAT: Number of secondary entries (BYTE) */
-#define XDIR_SetSum			2		/* exFAT: Sum of the set of directory entries (WORD) */
-#define XDIR_Attr			4		/* exFAT: File attribute (WORD) */
-#define XDIR_CrtTime		8		/* exFAT: Created time (DWORD) */
-#define XDIR_ModTime		12		/* exFAT: Modified time (DWORD) */
-#define XDIR_AccTime		16		/* exFAT: Last accessed time (DWORD) */
-#define XDIR_CrtTime10		20		/* exFAT: Created time subsecond (BYTE) */
-#define XDIR_ModTime10		21		/* exFAT: Modified time subsecond (BYTE) */
-#define XDIR_CrtTZ			22		/* exFAT: Created timezone (BYTE) */
-#define XDIR_ModTZ			23		/* exFAT: Modified timezone (BYTE) */
-#define XDIR_AccTZ			24		/* exFAT: Last accessed timezone (BYTE) */
-#define XDIR_GenFlags		33		/* exFAT: General secondary flags (BYTE) */
-#define XDIR_NumName		35		/* exFAT: Number of file name characters (BYTE) */
-#define XDIR_NameHash		36		/* exFAT: Hash of file name (WORD) */
-#define XDIR_ValidFileSize	40		/* exFAT: Valid file size (QWORD) */
-#define XDIR_FstClus		52		/* exFAT: First cluster of the file data (DWORD) */
-#define XDIR_FileSize		56		/* exFAT: File/Directory size (QWORD) */
-
-#define SZDIRE				32		/* Size of a directory entry */
-#define DDEM				0xE5	/* Deleted directory entry mark set to DIR_Name[0] */
-#define RDDEM				0x05	/* Replacement of the character collides with DDEM */
-#define LLEF				0x40	/* Last long entry flag in LDIR_Ord */
-
-#define FSI_LeadSig			0		/* FAT32 FSI: Leading signature (DWORD) */
-#define FSI_StrucSig		484		/* FAT32 FSI: Structure signature (DWORD) */
-#define FSI_Free_Count		488		/* FAT32 FSI: Number of free clusters (DWORD) */
-#define FSI_Nxt_Free		492		/* FAT32 FSI: Last allocated cluster (DWORD) */
-
-#define MBR_Table			446		/* MBR: Offset of partition table in the MBR */
-#define SZ_PTE				16		/* MBR: Size of a partition table entry */
-#define PTE_Boot			0		/* MBR PTE: Boot indicator */
-#define PTE_StHead			1		/* MBR PTE: Start head */
-#define PTE_StSec			2		/* MBR PTE: Start sector */
-#define PTE_StCyl			3		/* MBR PTE: Start cylinder */
-#define PTE_System			4		/* MBR PTE: System ID */
-#define PTE_EdHead			5		/* MBR PTE: End head */
-#define PTE_EdSec			6		/* MBR PTE: End sector */
-#define PTE_EdCyl			7		/* MBR PTE: End cylinder */
-#define PTE_StLba			8		/* MBR PTE: Start in LBA */
-#define PTE_SizLba			12		/* MBR PTE: Size in LBA */
-
-
-/* Post process on fatal error in the file operations */
-#define ABORT(fs, res)		{ fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
-
-
-/* Re-entrancy related */
-#if FF_FS_REENTRANT
-#if FF_USE_LFN == 1
-#error Static LFN work area cannot be used at thread-safe configuration
-#endif
-#define LEAVE_FF(fs, res)	{ unlock_fs(fs, res); return res; }
-#else
-#define LEAVE_FF(fs, res)	return res
-#endif
-
-
-/* Definitions of volume - physical location conversion */
-#if FF_MULTI_PARTITION
-#define LD2PD(vol) VolToPart[vol].pd	/* Get physical drive number */
-#define LD2PT(vol) VolToPart[vol].pt	/* Get partition index */
-#else
-#define LD2PD(vol) (BYTE)(vol)	/* Each logical drive is bound to the same physical drive number */
-#define LD2PT(vol) 0			/* Find first valid partition or in SFD */
-#endif
-
-
-/* Definitions of sector size */
-#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096)
-#error Wrong sector size configuration
-#endif
-#if FF_MAX_SS == FF_MIN_SS
-#define SS(fs)	((UINT)FF_MAX_SS)	/* Fixed sector size */
-#else
-#define SS(fs)	((fs)->ssize)	/* Variable sector size */
-#endif
-
-
-/* Timestamp */
-#if FF_FS_NORTC == 1
-#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31
-#error Invalid FF_FS_NORTC settings
-#endif
-#define GET_FATTIME()	((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16)
-#else
-#define GET_FATTIME()	get_fattime()
-#endif
-
-
-/* File lock controls */
-#if FF_FS_LOCK != 0
-#if FF_FS_READONLY
-#error FF_FS_LOCK must be 0 at read-only configuration
-#endif
-typedef struct {
-	FATFS *fs;		/* Object ID 1, volume (NULL:blank entry) */
-	DWORD clu;		/* Object ID 2, containing directory (0:root) */
-	DWORD ofs;		/* Object ID 3, offset in the directory */
-	WORD ctr;		/* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */
-} FILESEM;
-#endif
-
-
-/* SBCS up-case tables (\x80-\xFF) */
-#define TBL_CT437  {0x80,0x9A,0x45,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, \
-					0x41,0x49,0x4F,0x55,0xA5,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, \
-					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, \
-					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}
-#define TBL_CT720  {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, \
-					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, \
-					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, \
-					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}
-#define TBL_CT737  {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, \
-					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, \
-					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, \
-					0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
-					0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-#define TBL_CT771  {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, \
-					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, \
-					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,0xDC,0xDE,0xDE, \
-					0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
-					0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF}
-#define TBL_CT775  {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, \
-					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, \
-					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, \
-					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}
-#define TBL_CT850  {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \
-					0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \
-					0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
-					0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
-					0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
-					0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \
-					0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \
-					0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-#define TBL_CT852  {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,0xAC, \
-					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, \
-					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, \
-					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}
-#define TBL_CT855  {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, \
-					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, \
-					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, \
-					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}
-#define TBL_CT857  {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \
-					0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
-					0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
-					0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
-					0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
-					0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
-					0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \
-					0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
-#define TBL_CT860  {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \
-					0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
-					0x86,0x8B,0x9F,0x96,0xA5,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, \
-					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, \
-					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}
-#define TBL_CT861  {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \
-					0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
-					0xA4,0xA5,0xA6,0xA7,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, \
-					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, \
-					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}
-#define TBL_CT862  {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, \
-					0x41,0x49,0x4F,0x55,0xA5,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, \
-					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, \
-					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}
-#define TBL_CT863  {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \
-					0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \
-					0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
-					0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
-					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, \
-					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}
-#define TBL_CT864  {0x80,0x9A,0x45,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, \
-					0x41,0x49,0x4F,0x55,0xA5,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, \
-					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, \
-					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}
-#define TBL_CT865  {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, \
-					0x41,0x49,0x4F,0x55,0xA5,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, \
-					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, \
-					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}
-#define TBL_CT866  {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, \
-					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, \
-					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, \
-					0x90,0x91,0x92,0x93,0x94,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}
-#define TBL_CT869  {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,0x86,0x9C,0x8D,0x8F,0x90, \
-					0x91,0x90,0x92,0x95,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, \
-					0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
-					0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \
-					0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \
-					0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF}
-
-
-/* DBCS code range |----- 1st byte -----|  |----------- 2nd byte -----------| */
-#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00}
-#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00}
-#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE}
-#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00}
-
-
-/* Macros for table definitions */
-#define MERGE_2STR(a, b) a ## b
-#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp)
-
-
-
-
-/*--------------------------------------------------------------------------
-
-   Module Private Work Area
-
----------------------------------------------------------------------------*/
-/* Remark: Variables defined here without initial value shall be guaranteed
-/  zero/null at start-up. If not, the linker option or start-up routine is
-/  not compliance with C standard. */
-
-/*--------------------------------*/
-/* File/Volume controls           */
-/*--------------------------------*/
-
-#if FF_VOLUMES < 1 || FF_VOLUMES > 10
-#error Wrong FF_VOLUMES setting
-#endif
-static FATFS* FatFs[FF_VOLUMES];	/* Pointer to the filesystem objects (logical drives) */
-static WORD Fsid;					/* Filesystem mount ID */
-
-#if FF_FS_RPATH != 0
-static BYTE CurrVol;				/* Current drive */
-#endif
-
-#if FF_FS_LOCK != 0
-static FILESEM Files[FF_FS_LOCK];	/* Open object lock semaphores */
-#endif
-
-#if FF_STR_VOLUME_ID
-#ifdef FF_VOLUME_STRS
-static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS};	/* Pre-defined volume ID */
-#endif
-#endif
-
-
-/*--------------------------------*/
-/* LFN/Directory working buffer   */
-/*--------------------------------*/
-
-#if FF_USE_LFN == 0		/* Non-LFN configuration */
-#if FF_FS_EXFAT
-#error LFN must be enabled when enable exFAT
-#endif
-#define DEF_NAMBUF
-#define INIT_NAMBUF(fs)
-#define FREE_NAMBUF()
-#define LEAVE_MKFS(res)	return res
-
-#else					/* LFN configurations */
-#if FF_MAX_LFN < 12 || FF_MAX_LFN > 255
-#error Wrong setting of FF_MAX_LFN
-#endif
-#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12
-#error Wrong setting of FF_LFN_BUF or FF_SFN_BUF
-#endif
-#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3
-#error Wrong setting of FF_LFN_UNICODE
-#endif
-static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30};	/* FAT: Offset of LFN characters in the directory entry */
-#define MAXDIRB(nc)	((nc + 44U) / 15 * SZDIRE)	/* exFAT: Size of directory entry block scratchpad buffer needed for the name length */
-
-#if FF_USE_LFN == 1		/* LFN enabled with static working buffer */
-#if FF_FS_EXFAT
-static BYTE	DirBuf[MAXDIRB(FF_MAX_LFN)];	/* Directory entry block scratchpad buffer */
-#endif
-static WCHAR LfnBuf[FF_MAX_LFN + 1];		/* LFN working buffer */
-#define DEF_NAMBUF
-#define INIT_NAMBUF(fs)
-#define FREE_NAMBUF()
-#define LEAVE_MKFS(res)	return res
-
-#elif FF_USE_LFN == 2 	/* LFN enabled with dynamic working buffer on the stack */
-#if FF_FS_EXFAT
-#define DEF_NAMBUF		WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)];	/* LFN working buffer and directory entry block scratchpad buffer */
-#define INIT_NAMBUF(fs)	{ (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; }
-#define FREE_NAMBUF()
-#else
-#define DEF_NAMBUF		WCHAR lbuf[FF_MAX_LFN+1];	/* LFN working buffer */
-#define INIT_NAMBUF(fs)	{ (fs)->lfnbuf = lbuf; }
-#define FREE_NAMBUF()
-#endif
-#define LEAVE_MKFS(res)	return res
-
-#elif FF_USE_LFN == 3 	/* LFN enabled with dynamic working buffer on the heap */
-#if FF_FS_EXFAT
-#define DEF_NAMBUF		WCHAR *lfn;	/* Pointer to LFN working buffer and directory entry block scratchpad buffer */
-#define INIT_NAMBUF(fs)	{ lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); }
-#define FREE_NAMBUF()	ff_memfree(lfn)
-#else
-#define DEF_NAMBUF		WCHAR *lfn;	/* Pointer to LFN working buffer */
-#define INIT_NAMBUF(fs)	{ lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; }
-#define FREE_NAMBUF()	ff_memfree(lfn)
-#endif
-#define LEAVE_MKFS(res)	{ if (!work) ff_memfree(buf); return res; }
-#define MAX_MALLOC	0x8000	/* Must be >=FF_MAX_SS */
-
-#else
-#error Wrong setting of FF_USE_LFN
-
-#endif	/* FF_USE_LFN == 1 */
-#endif	/* FF_USE_LFN == 0 */
-
-
-
-/*--------------------------------*/
-/* Code conversion tables         */
-/*--------------------------------*/
-
-#if FF_CODE_PAGE == 0		/* Run-time code page configuration */
-#define CODEPAGE CodePage
-static WORD CodePage;	/* Current code page */
-static const BYTE *ExCvt, *DbcTbl;	/* Pointer to current SBCS up-case table and DBCS code range table below */
-
-static const BYTE Ct437[] = TBL_CT437;
-static const BYTE Ct720[] = TBL_CT720;
-static const BYTE Ct737[] = TBL_CT737;
-static const BYTE Ct771[] = TBL_CT771;
-static const BYTE Ct775[] = TBL_CT775;
-static const BYTE Ct850[] = TBL_CT850;
-static const BYTE Ct852[] = TBL_CT852;
-static const BYTE Ct855[] = TBL_CT855;
-static const BYTE Ct857[] = TBL_CT857;
-static const BYTE Ct860[] = TBL_CT860;
-static const BYTE Ct861[] = TBL_CT861;
-static const BYTE Ct862[] = TBL_CT862;
-static const BYTE Ct863[] = TBL_CT863;
-static const BYTE Ct864[] = TBL_CT864;
-static const BYTE Ct865[] = TBL_CT865;
-static const BYTE Ct866[] = TBL_CT866;
-static const BYTE Ct869[] = TBL_CT869;
-static const BYTE Dc932[] = TBL_DC932;
-static const BYTE Dc936[] = TBL_DC936;
-static const BYTE Dc949[] = TBL_DC949;
-static const BYTE Dc950[] = TBL_DC950;
-
-#elif FF_CODE_PAGE < 900	/* Static code page configuration (SBCS) */
-#define CODEPAGE FF_CODE_PAGE
-static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE);
-
-#else					/* Static code page configuration (DBCS) */
-#define CODEPAGE FF_CODE_PAGE
-static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE);
-
-#endif
-
-
-
-
-/*--------------------------------------------------------------------------
-
-   Module Private Functions
-
----------------------------------------------------------------------------*/
-
-
-/*-----------------------------------------------------------------------*/
-/* Load/Store multi-byte word in the FAT structure                       */
-/*-----------------------------------------------------------------------*/
-
-static WORD ld_word (const BYTE* ptr)	/*	 Load a 2-byte little-endian word */
-{
-	WORD rv;
-
-	rv = ptr[1];
-	rv = rv << 8 | ptr[0];
-	return rv;
-}
-
-static DWORD ld_dword (const BYTE* ptr)	/* Load a 4-byte little-endian word */
-{
-	DWORD rv;
-
-	rv = ptr[3];
-	rv = rv << 8 | ptr[2];
-	rv = rv << 8 | ptr[1];
-	rv = rv << 8 | ptr[0];
-	return rv;
-}
-
-#if FF_FS_EXFAT
-static QWORD ld_qword (const BYTE* ptr)	/* Load an 8-byte little-endian word */
-{
-	QWORD rv;
-
-	rv = ptr[7];
-	rv = rv << 8 | ptr[6];
-	rv = rv << 8 | ptr[5];
-	rv = rv << 8 | ptr[4];
-	rv = rv << 8 | ptr[3];
-	rv = rv << 8 | ptr[2];
-	rv = rv << 8 | ptr[1];
-	rv = rv << 8 | ptr[0];
-	return rv;
-}
-#endif
-
-#if !FF_FS_READONLY
-static void st_word (BYTE* ptr, WORD val)	/* Store a 2-byte word in little-endian */
-{
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val;
-}
-
-static void st_dword (BYTE* ptr, DWORD val)	/* Store a 4-byte word in little-endian */
-{
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val;
-}
-
-#if FF_FS_EXFAT
-static void st_qword (BYTE* ptr, QWORD val)	/* Store an 8-byte word in little-endian */
-{
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val; val >>= 8;
-	*ptr++ = (BYTE)val;
-}
-#endif
-#endif	/* !FF_FS_READONLY */
-
-
-
-/*-----------------------------------------------------------------------*/
-/* String functions                                                      */
-/*-----------------------------------------------------------------------*/
-
-/* Copy memory to memory */
-static void mem_cpy (void* dst, const void* src, UINT cnt)
-{
-	BYTE *d = (BYTE*)dst;
-	const BYTE *s = (const BYTE*)src;
-
-	if (cnt != 0) {
-		do {
-			*d++ = *s++;
-		} while (--cnt);
-	}
-}
-
-
-/* Fill memory block */
-static void mem_set (void* dst, int val, UINT cnt)
-{
-	BYTE *d = (BYTE*)dst;
-
-	do {
-		*d++ = (BYTE)val;
-	} while (--cnt);
-}
-
-
-/* Compare memory block */
-static int mem_cmp (const void* dst, const void* src, UINT cnt)	/* ZR:same, NZ:different */
-{
-	const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
-	int r = 0;
-
-	do {
-		r = *d++ - *s++;
-	} while (--cnt && r == 0);
-
-	return r;
-}
-
-
-/* Check if chr is contained in the string */
-static int chk_chr (const char* str, int chr)	/* NZ:contained, ZR:not contained */
-{
-	while (*str && *str != chr) str++;
-	return *str;
-}
-
-
-/* Test if the character is DBC 1st byte */
-static int dbc_1st (BYTE c)
-{
-#if FF_CODE_PAGE == 0		/* Variable code page */
-	if (DbcTbl && c >= DbcTbl[0]) {
-		if (c <= DbcTbl[1]) return 1;					/* 1st byte range 1 */
-		if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1;	/* 1st byte range 2 */
-	}
-#elif FF_CODE_PAGE >= 900	/* DBCS fixed code page */
-	if (c >= DbcTbl[0]) {
-		if (c <= DbcTbl[1]) return 1;
-		if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1;
-	}
-#else						/* SBCS fixed code page */
-	if (c != 0) return 0;	/* Always false */
-#endif
-	return 0;
-}
-
-
-/* Test if the character is DBC 2nd byte */
-static int dbc_2nd (BYTE c)
-{
-#if FF_CODE_PAGE == 0		/* Variable code page */
-	if (DbcTbl && c >= DbcTbl[4]) {
-		if (c <= DbcTbl[5]) return 1;					/* 2nd byte range 1 */
-		if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1;	/* 2nd byte range 2 */
-		if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1;	/* 2nd byte range 3 */
-	}
-#elif FF_CODE_PAGE >= 900	/* DBCS fixed code page */
-	if (c >= DbcTbl[4]) {
-		if (c <= DbcTbl[5]) return 1;
-		if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1;
-		if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1;
-	}
-#else						/* SBCS fixed code page */
-	if (c != 0) return 0;	/* Always false */
-#endif
-	return 0;
-}
-
-
-#if FF_USE_LFN
-
-/* Get a character from TCHAR string in defined API encodeing */
-static DWORD tchar2uni (	/* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */
-	const TCHAR** str		/* Pointer to pointer to TCHAR string in configured encoding */
-)
-{
-	DWORD uc;
-	const TCHAR *p = *str;
-
-#if FF_LFN_UNICODE == 1		/* UTF-16 input */
-	WCHAR wc;
-
-	uc = *p++;	/* Get a unit */
-	if (IsSurrogate(uc)) {	/* Surrogate? */
-		wc = *p++;		/* Get low surrogate */
-		if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF;	/* Wrong surrogate? */
-		uc = uc << 16 | wc;
-	}
-
-#elif FF_LFN_UNICODE == 2	/* UTF-8 input */
-	BYTE b;
-	int nf;
-
-	uc = (BYTE)*p++;	/* Get a unit */
-	if (uc & 0x80) {	/* Multiple byte code? */
-		if ((uc & 0xE0) == 0xC0) {	/* 2-byte sequence? */
-			uc &= 0x1F; nf = 1;
-		} else {
-			if ((uc & 0xF0) == 0xE0) {	/* 3-byte sequence? */
-				uc &= 0x0F; nf = 2;
-			} else {
-				if ((uc & 0xF8) == 0xF0) {	/* 4-byte sequence? */
-					uc &= 0x07; nf = 3;
-				} else {					/* Wrong sequence */
-					return 0xFFFFFFFF;
-				}
-			}
-		}
-		do {	/* Get trailing bytes */
-			b = (BYTE)*p++;
-			if ((b & 0xC0) != 0x80) return 0xFFFFFFFF;	/* Wrong sequence? */
-			uc = uc << 6 | (b & 0x3F);
-		} while (--nf != 0);
-		if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF;	/* Wrong code? */
-		if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF);	/* Make a surrogate pair if needed */
-	}
-
-#elif FF_LFN_UNICODE == 3	/* UTF-32 input */
-	uc = (TCHAR)*p++;	/* Get a unit */
-	if (uc >= 0x110000) return 0xFFFFFFFF;	/* Wrong code? */
-	if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF);	/* Make a surrogate pair if needed */
-
-#else		/* ANSI/OEM input */
-	BYTE b;
-	WCHAR wc;
-
-	wc = (BYTE)*p++;			/* Get a byte */
-	if (dbc_1st((BYTE)wc)) {	/* Is it a DBC 1st byte? */
-		b = (BYTE)*p++;			/* Get 2nd byte */
-		if (!dbc_2nd(b)) return 0xFFFFFFFF;	/* Invalid code? */
-		wc = (wc << 8) + b;		/* Make a DBC */
-	}
-	if (wc != 0) {
-		wc = ff_oem2uni(wc, CODEPAGE);	/* ANSI/OEM ==> Unicode */
-		if (wc == 0) return 0xFFFFFFFF;	/* Invalid code? */
-	}
-	uc = wc;
-
-#endif
-	*str = p;	/* Next read pointer */
-	return uc;
-}
-
-
-/* Output a TCHAR string in defined API encoding */
-static BYTE put_utf (	/* Returns number of encoding units written (0:buffer overflow or wrong encoding) */
-	DWORD chr,	/* UTF-16 encoded character (Double encoding unit char if >=0x10000) */
-	TCHAR* buf,	/* Output buffer */
-	UINT szb	/* Size of the buffer */
-)
-{
-#if FF_LFN_UNICODE == 1	/* UTF-16 output */
-	WCHAR hs, wc;
-
-	hs = (WCHAR)(chr >> 16);
-	wc = (WCHAR)chr;
-	if (hs == 0) {	/* Single encoding unit? */
-		if (szb < 1 || IsSurrogate(wc)) return 0;	/* Buffer overflow or wrong code? */
-		*buf = wc;
-		return 1;
-	}
-	if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc)) return 0;	/* Buffer overflow or wrong surrogate? */
-	*buf++ = hs;
-	*buf++ = wc;
-	return 2;
-
-#elif FF_LFN_UNICODE == 2	/* UTF-8 output */
-	DWORD hc;
-
-	if (chr < 0x80) {	/* Single byte code? */
-		if (szb < 1) return 0;	/* Buffer overflow? */
-		*buf = (TCHAR)chr;
-		return 1;
-	}
-	if (chr < 0x800) {	/* 2-byte sequence? */
-		if (szb < 2) return 0;	/* Buffer overflow? */
-		*buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F));
-		*buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
-		return 2;
-	}
-	if (chr < 0x10000) {	/* 3-byte sequence? */
-		if (szb < 3 || IsSurrogate(chr)) return 0;	/* Buffer overflow or wrong code? */
-		*buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F));
-		*buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F));
-		*buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
-		return 3;
-	}
-	/* 4-byte sequence */
-	if (szb < 4) return 0;	/* Buffer overflow? */
-	hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6;	/* Get high 10 bits */
-	chr = (chr & 0xFFFF) - 0xDC00;					/* Get low 10 bits */
-	if (hc >= 0x100000 || chr >= 0x400) return 0;	/* Wrong surrogate? */
-	chr = (hc | chr) + 0x10000;
-	*buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07));
-	*buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F));
-	*buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F));
-	*buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
-	return 4;
-
-#elif FF_LFN_UNICODE == 3	/* UTF-32 output */
-	DWORD hc;
-
-	if (szb < 1) return 0;	/* Buffer overflow? */
-	if (chr >= 0x10000) {	/* Out of BMP? */
-		hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6;	/* Get high 10 bits */
-		chr = (chr & 0xFFFF) - 0xDC00;					/* Get low 10 bits */
-		if (hc >= 0x100000 || chr >= 0x400) return 0;	/* Wrong surrogate? */
-		chr = (hc | chr) + 0x10000;
-	}
-	*buf++ = (TCHAR)chr;
-	return 1;
-
-#else						/* ANSI/OEM output */
-	WCHAR wc;
-
-	wc = ff_uni2oem(chr, CODEPAGE);
-	if (wc >= 0x100) {	/* Is this a DBC? */
-		if (szb < 2) return 0;
-		*buf++ = (char)(wc >> 8);	/* Store DBC 1st byte */
-		*buf++ = (TCHAR)wc;			/* Store DBC 2nd byte */
-		return 2;
-	}
-	if (wc == 0 || szb < 1) return 0;	/* Invalid char or buffer overflow? */
-	*buf++ = (TCHAR)wc;					/* Store the character */
-	return 1;
-#endif
-}
-#endif	/* FF_USE_LFN */
-
-
-#if FF_FS_REENTRANT
-/*-----------------------------------------------------------------------*/
-/* Request/Release grant to access the volume                            */
-/*-----------------------------------------------------------------------*/
-static int lock_fs (		/* 1:Ok, 0:timeout */
-	FATFS* fs		/* Filesystem object */
-)
-{
-	return ff_req_grant(fs->sobj);
-}
-
-
-static void unlock_fs (
-	FATFS* fs,		/* Filesystem object */
-	FRESULT res		/* Result code to be returned */
-)
-{
-	if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) {
-		ff_rel_grant(fs->sobj);
-	}
-}
-
-#endif
-
-
-
-#if FF_FS_LOCK != 0
-/*-----------------------------------------------------------------------*/
-/* File lock control functions                                           */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT chk_lock (	/* Check if the file can be accessed */
-	DIR* dp,		/* Directory object pointing the file to be checked */
-	int acc			/* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */
-)
-{
-	UINT i, be;
-
-	/* Search open object table for the object */
-	be = 0;
-	for (i = 0; i < FF_FS_LOCK; i++) {
-		if (Files[i].fs) {	/* Existing entry */
-			if (Files[i].fs == dp->obj.fs &&	 	/* Check if the object matches with an open object */
-				Files[i].clu == dp->obj.sclust &&
-				Files[i].ofs == dp->dptr) break;
-		} else {			/* Blank entry */
-			be = 1;
-		}
-	}
-	if (i == FF_FS_LOCK) {	/* The object has not been opened */
-		return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK;	/* Is there a blank entry for new object? */
-	}
-
-	/* The object was opened. Reject any open against writing file and all write mode open */
-	return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
-}
-
-
-static int enq_lock (void)	/* Check if an entry is available for a new object */
-{
-	UINT i;
-
-	for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ;
-	return (i == FF_FS_LOCK) ? 0 : 1;
-}
-
-
-static UINT inc_lock (	/* Increment object open counter and returns its index (0:Internal error) */
-	DIR* dp,	/* Directory object pointing the file to register or increment */
-	int acc		/* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
-)
-{
-	UINT i;
-
-
-	for (i = 0; i < FF_FS_LOCK; i++) {	/* Find the object */
-		if (Files[i].fs == dp->obj.fs &&
-			Files[i].clu == dp->obj.sclust &&
-			Files[i].ofs == dp->dptr) break;
-	}
-
-	if (i == FF_FS_LOCK) {				/* Not opened. Register it as new. */
-		for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ;
-		if (i == FF_FS_LOCK) return 0;	/* No free entry to register (int err) */
-		Files[i].fs = dp->obj.fs;
-		Files[i].clu = dp->obj.sclust;
-		Files[i].ofs = dp->dptr;
-		Files[i].ctr = 0;
-	}
-
-	if (acc >= 1 && Files[i].ctr) return 0;	/* Access violation (int err) */
-
-	Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1;	/* Set semaphore value */
-
-	return i + 1;	/* Index number origin from 1 */
-}
-
-
-static FRESULT dec_lock (	/* Decrement object open counter */
-	UINT i			/* Semaphore index (1..) */
-)
-{
-	WORD n;
-	FRESULT res;
-
-
-	if (--i < FF_FS_LOCK) {	/* Index number origin from 0 */
-		n = Files[i].ctr;
-		if (n == 0x100) n = 0;		/* If write mode open, delete the entry */
-		if (n > 0) n--;				/* Decrement read mode open count */
-		Files[i].ctr = n;
-		if (n == 0) Files[i].fs = 0;	/* Delete the entry if open count gets zero */
-		res = FR_OK;
-	} else {
-		res = FR_INT_ERR;			/* Invalid index nunber */
-	}
-	return res;
-}
-
-
-static void clear_lock (	/* Clear lock entries of the volume */
-	FATFS *fs
-)
-{
-	UINT i;
-
-	for (i = 0; i < FF_FS_LOCK; i++) {
-		if (Files[i].fs == fs) Files[i].fs = 0;
-	}
-}
-
-#endif	/* FF_FS_LOCK != 0 */
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Move/Flush disk access window in the filesystem object                */
-/*-----------------------------------------------------------------------*/
-#if !FF_FS_READONLY
-static FRESULT sync_window (	/* Returns FR_OK or FR_DISK_ERR */
-	FATFS* fs			/* Filesystem object */
-)
-{
-	FRESULT res = FR_OK;
-
-
-	if (fs->wflag) {	/* Is the disk access window dirty */
-		if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) {	/* Write back the window */
-			fs->wflag = 0;	/* Clear window dirty flag */
-			if (fs->winsect - fs->fatbase < fs->fsize) {	/* Is it in the 1st FAT? */
-				if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1);	/* Reflect it to 2nd FAT if needed */
-			}
-		} else {
-			res = FR_DISK_ERR;
-		}
-	}
-	return res;
-}
-#endif
-
-
-static FRESULT move_window (	/* Returns FR_OK or FR_DISK_ERR */
-	FATFS* fs,			/* Filesystem object */
-	DWORD sector		/* Sector number to make appearance in the fs->win[] */
-)
-{
-	FRESULT res = FR_OK;
-
-
-	if (sector != fs->winsect) {	/* Window offset changed? */
-#if !FF_FS_READONLY
-		res = sync_window(fs);		/* Write-back changes */
-#endif
-		if (res == FR_OK) {			/* Fill sector window with new data */
-			if (disk_read(fs->pdrv, fs->win, sector, 1) != RES_OK) {
-				sector = 0xFFFFFFFF;	/* Invalidate window if read data is not valid */
-				res = FR_DISK_ERR;
-			}
-			fs->winsect = sector;
-		}
-	}
-	return res;
-}
-
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Synchronize filesystem and data on the storage                        */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT sync_fs (	/* Returns FR_OK or FR_DISK_ERR */
-	FATFS* fs		/* Filesystem object */
-)
-{
-	FRESULT res;
-
-
-	res = sync_window(fs);
-	if (res == FR_OK) {
-		if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {	/* FAT32: Update FSInfo sector if needed */
-			/* Create FSInfo structure */
-			mem_set(fs->win, 0, sizeof fs->win);
-			st_word(fs->win + BS_55AA, 0xAA55);
-			st_dword(fs->win + FSI_LeadSig, 0x41615252);
-			st_dword(fs->win + FSI_StrucSig, 0x61417272);
-			st_dword(fs->win + FSI_Free_Count, fs->free_clst);
-			st_dword(fs->win + FSI_Nxt_Free, fs->last_clst);
-			/* Write it into the FSInfo sector */
-			fs->winsect = fs->volbase + 1;
-			disk_write(fs->pdrv, fs->win, fs->winsect, 1);
-			fs->fsi_flag = 0;
-		}
-		/* Make sure that no pending write process in the lower layer */
-		if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR;
-	}
-
-	return res;
-}
-
-#endif
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Get physical sector number from cluster number                        */
-/*-----------------------------------------------------------------------*/
-
-static DWORD clst2sect (	/* !=0:Sector number, 0:Failed (invalid cluster#) */
-	FATFS* fs,		/* Filesystem object */
-	DWORD clst		/* Cluster# to be converted */
-)
-{
-	clst -= 2;		/* Cluster number is origin from 2 */
-	if (clst >= fs->n_fatent - 2) return 0;		/* Is it invalid cluster number? */
-	return fs->database + fs->csize * clst;		/* Start sector number of the cluster */
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* FAT access - Read value of a FAT entry                                */
-/*-----------------------------------------------------------------------*/
-
-static DWORD get_fat (		/* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */
-	FFOBJID* obj,	/* Corresponding object */
-	DWORD clst		/* Cluster number to get the value */
-)
-{
-	UINT wc, bc;
-	DWORD val;
-	FATFS *fs = obj->fs;
-
-
-	if (clst < 2 || clst >= fs->n_fatent) {	/* Check if in valid range */
-		val = 1;	/* Internal error */
-
-	} else {
-		val = 0xFFFFFFFF;	/* Default value falls on disk error */
-
-		switch (fs->fs_type) {
-		case FS_FAT12 :
-			bc = (UINT)clst; bc += bc / 2;
-			if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
-			wc = fs->win[bc++ % SS(fs)];		/* Get 1st byte of the entry */
-			if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
-			wc |= fs->win[bc % SS(fs)] << 8;	/* Merge 2nd byte of the entry */
-			val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF);	/* Adjust bit position */
-			break;
-
-		case FS_FAT16 :
-			if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break;
-			val = ld_word(fs->win + clst * 2 % SS(fs));		/* Simple WORD array */
-			break;
-
-		case FS_FAT32 :
-			if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
-			val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF;	/* Simple DWORD array but mask out upper 4 bits */
-			break;
-#if FF_FS_EXFAT
-		case FS_EXFAT :
-			if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) {	/* Object except root dir must have valid data length */
-				DWORD cofs = clst - obj->sclust;	/* Offset from start cluster */
-				DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize;	/* Number of clusters - 1 */
-
-				if (obj->stat == 2 && cofs <= clen) {	/* Is it a contiguous chain? */
-					val = (cofs == clen) ? 0x7FFFFFFF : clst + 1;	/* No data on the FAT, generate the value */
-					break;
-				}
-				if (obj->stat == 3 && cofs < obj->n_cont) {	/* Is it in the 1st fragment? */
-					val = clst + 1; 	/* Generate the value */
-					break;
-				}
-				if (obj->stat != 2) {	/* Get value from FAT if FAT chain is valid */
-					if (obj->n_frag != 0) {	/* Is it on the growing edge? */
-						val = 0x7FFFFFFF;	/* Generate EOC */
-					} else {
-						if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
-						val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF;
-					}
-					break;
-				}
-			}
-			/* go to default */
-#endif
-		default:
-			val = 1;	/* Internal error */
-		}
-	}
-
-	return val;
-}
-
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* FAT access - Change value of a FAT entry                              */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT put_fat (	/* FR_OK(0):succeeded, !=0:error */
-	FATFS* fs,		/* Corresponding filesystem object */
-	DWORD clst,		/* FAT index number (cluster number) to be changed */
-	DWORD val		/* New value to be set to the entry */
-)
-{
-	UINT bc;
-	BYTE *p;
-	FRESULT res = FR_INT_ERR;
-
-
-	if (clst >= 2 && clst < fs->n_fatent) {	/* Check if in valid range */
-		switch (fs->fs_type) {
-		case FS_FAT12 :
-			bc = (UINT)clst; bc += bc / 2;	/* bc: byte offset of the entry */
-			res = move_window(fs, fs->fatbase + (bc / SS(fs)));
-			if (res != FR_OK) break;
-			p = fs->win + bc++ % SS(fs);
-			*p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;		/* Put 1st byte */
-			fs->wflag = 1;
-			res = move_window(fs, fs->fatbase + (bc / SS(fs)));
-			if (res != FR_OK) break;
-			p = fs->win + bc % SS(fs);
-			*p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));	/* Put 2nd byte */
-			fs->wflag = 1;
-			break;
-
-		case FS_FAT16 :
-			res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
-			if (res != FR_OK) break;
-			st_word(fs->win + clst * 2 % SS(fs), (WORD)val);	/* Simple WORD array */
-			fs->wflag = 1;
-			break;
-
-		case FS_FAT32 :
-#if FF_FS_EXFAT
-		case FS_EXFAT :
-#endif
-			res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
-			if (res != FR_OK) break;
-			if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
-				val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000);
-			}
-			st_dword(fs->win + clst * 4 % SS(fs), val);
-			fs->wflag = 1;
-			break;
-		}
-	}
-	return res;
-}
-
-#endif /* !FF_FS_READONLY */
-
-
-
-
-#if FF_FS_EXFAT && !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* exFAT: Accessing FAT and Allocation Bitmap                            */
-/*-----------------------------------------------------------------------*/
-
-/*--------------------------------------*/
-/* Find a contiguous free cluster block */
-/*--------------------------------------*/
-
-static DWORD find_bitmap (	/* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */
-	FATFS* fs,	/* Filesystem object */
-	DWORD clst,	/* Cluster number to scan from */
-	DWORD ncl	/* Number of contiguous clusters to find (1..) */
-)
-{
-	BYTE bm, bv;
-	UINT i;
-	DWORD val, scl, ctr;
-
-
-	clst -= 2;	/* The first bit in the bitmap corresponds to cluster #2 */
-	if (clst >= fs->n_fatent - 2) clst = 0;
-	scl = val = clst; ctr = 0;
-	for (;;) {
-		if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF;
-		i = val / 8 % SS(fs); bm = 1 << (val % 8);
-		do {
-			do {
-				bv = fs->win[i] & bm; bm <<= 1;		/* Get bit value */
-				if (++val >= fs->n_fatent - 2) {	/* Next cluster (with wrap-around) */
-					val = 0; bm = 0; i = SS(fs);
-				}
-				if (bv == 0) {	/* Is it a free cluster? */
-					if (++ctr == ncl) return scl + 2;	/* Check if run length is sufficient for required */
-				} else {
-					scl = val; ctr = 0;		/* Encountered a cluster in-use, restart to scan */
-				}
-				if (val == clst) return 0;	/* All cluster scanned? */
-			} while (bm != 0);
-			bm = 1;
-		} while (++i < SS(fs));
-	}
-}
-
-
-/*----------------------------------------*/
-/* Set/Clear a block of allocation bitmap */
-/*----------------------------------------*/
-
-static FRESULT change_bitmap (
-	FATFS* fs,	/* Filesystem object */
-	DWORD clst,	/* Cluster number to change from */
-	DWORD ncl,	/* Number of clusters to be changed */
-	int bv		/* bit value to be set (0 or 1) */
-)
-{
-	BYTE bm;
-	UINT i;
-	DWORD sect;
-
-
-	clst -= 2;	/* The first bit corresponds to cluster #2 */
-	sect = fs->bitbase + clst / 8 / SS(fs);	/* Sector address */
-	i = clst / 8 % SS(fs);					/* Byte offset in the sector */
-	bm = 1 << (clst % 8);					/* Bit mask in the byte */
-	for (;;) {
-		if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
-		do {
-			do {
-				if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR;	/* Is the bit expected value? */
-				fs->win[i] ^= bm;	/* Flip the bit */
-				fs->wflag = 1;
-				if (--ncl == 0) return FR_OK;	/* All bits processed? */
-			} while (bm <<= 1);		/* Next bit */
-			bm = 1;
-		} while (++i < SS(fs));		/* Next byte */
-		i = 0;
-	}
-}
-
-
-/*---------------------------------------------*/
-/* Fill the first fragment of the FAT chain    */
-/*---------------------------------------------*/
-
-static FRESULT fill_first_frag (
-	FFOBJID* obj	/* Pointer to the corresponding object */
-)
-{
-	FRESULT res;
-	DWORD cl, n;
-
-
-	if (obj->stat == 3) {	/* Has the object been changed 'fragmented' in this session? */
-		for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) {	/* Create cluster chain on the FAT */
-			res = put_fat(obj->fs, cl, cl + 1);
-			if (res != FR_OK) return res;
-		}
-		obj->stat = 0;	/* Change status 'FAT chain is valid' */
-	}
-	return FR_OK;
-}
-
-
-/*---------------------------------------------*/
-/* Fill the last fragment of the FAT chain     */
-/*---------------------------------------------*/
-
-static FRESULT fill_last_frag (
-	FFOBJID* obj,	/* Pointer to the corresponding object */
-	DWORD lcl,		/* Last cluster of the fragment */
-	DWORD term		/* Value to set the last FAT entry */
-)
-{
-	FRESULT res;
-
-
-	while (obj->n_frag > 0) {	/* Create the chain of last fragment */
-		res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term);
-		if (res != FR_OK) return res;
-		obj->n_frag--;
-	}
-	return FR_OK;
-}
-
-#endif	/* FF_FS_EXFAT && !FF_FS_READONLY */
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* FAT handling - Remove a cluster chain                                 */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT remove_chain (	/* FR_OK(0):succeeded, !=0:error */
-	FFOBJID* obj,		/* Corresponding object */
-	DWORD clst,			/* Cluster to remove a chain from */
-	DWORD pclst			/* Previous cluster of clst (0 if entire chain) */
-)
-{
-	FRESULT res = FR_OK;
-	DWORD nxt;
-	FATFS *fs = obj->fs;
-#if FF_FS_EXFAT || FF_USE_TRIM
-	DWORD scl = clst, ecl = clst;
-#endif
-#if FF_USE_TRIM
-	DWORD rt[2];
-#endif
-
-	if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR;	/* Check if in valid range */
-
-	/* Mark the previous cluster 'EOC' on the FAT if it exists */
-	if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) {
-		res = put_fat(fs, pclst, 0xFFFFFFFF);
-		if (res != FR_OK) return res;
-	}
-
-	/* Remove the chain */
-	do {
-		nxt = get_fat(obj, clst);			/* Get cluster status */
-		if (nxt == 0) break;				/* Empty cluster? */
-		if (nxt == 1) return FR_INT_ERR;	/* Internal error? */
-		if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error? */
-		if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
-			res = put_fat(fs, clst, 0);		/* Mark the cluster 'free' on the FAT */
-			if (res != FR_OK) return res;
-		}
-		if (fs->free_clst < fs->n_fatent - 2) {	/* Update FSINFO */
-			fs->free_clst++;
-			fs->fsi_flag |= 1;
-		}
-#if FF_FS_EXFAT || FF_USE_TRIM
-		if (ecl + 1 == nxt) {	/* Is next cluster contiguous? */
-			ecl = nxt;
-		} else {				/* End of contiguous cluster block */
-#if FF_FS_EXFAT
-			if (fs->fs_type == FS_EXFAT) {
-				res = change_bitmap(fs, scl, ecl - scl + 1, 0);	/* Mark the cluster block 'free' on the bitmap */
-				if (res != FR_OK) return res;
-			}
-#endif
-#if FF_USE_TRIM
-			rt[0] = clst2sect(fs, scl);					/* Start of data area freed */
-			rt[1] = clst2sect(fs, ecl) + fs->csize - 1;	/* End of data area freed */
-			disk_ioctl(fs->pdrv, CTRL_TRIM, rt);		/* Inform device the data in the block is no longer needed */
-#endif
-			scl = ecl = nxt;
-		}
-#endif
-		clst = nxt;					/* Next cluster */
-	} while (clst < fs->n_fatent);	/* Repeat while not the last link */
-
-#if FF_FS_EXFAT
-	/* Some post processes for chain status */
-	if (fs->fs_type == FS_EXFAT) {
-		if (pclst == 0) {	/* Has the entire chain been removed? */
-			obj->stat = 0;		/* Change the chain status 'initial' */
-		} else {
-			if (obj->stat == 0) {	/* Is it a fragmented chain from the beginning of this session? */
-				clst = obj->sclust;		/* Follow the chain to check if it gets contiguous */
-				while (clst != pclst) {
-					nxt = get_fat(obj, clst);
-					if (nxt < 2) return FR_INT_ERR;
-					if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;
-					if (nxt != clst + 1) break;	/* Not contiguous? */
-					clst++;
-				}
-				if (clst == pclst) {	/* Has the chain got contiguous again? */
-					obj->stat = 2;		/* Change the chain status 'contiguous' */
-				}
-			} else {
-				if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) {	/* Was the chain fragmented in this session and got contiguous again? */
-					obj->stat = 2;	/* Change the chain status 'contiguous' */
-				}
-			}
-		}
-	}
-#endif
-	return FR_OK;
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* FAT handling - Stretch a chain or Create a new chain                  */
-/*-----------------------------------------------------------------------*/
-
-static DWORD create_chain (	/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
-	FFOBJID* obj,		/* Corresponding object */
-	DWORD clst			/* Cluster# to stretch, 0:Create a new chain */
-)
-{
-	DWORD cs, ncl, scl;
-	FRESULT res;
-	FATFS *fs = obj->fs;
-
-
-	if (clst == 0) {	/* Create a new chain */
-		scl = fs->last_clst;				/* Suggested cluster to start to find */
-		if (scl == 0 || scl >= fs->n_fatent) scl = 1;
-	}
-	else {				/* Stretch a chain */
-		cs = get_fat(obj, clst);			/* Check the cluster status */
-		if (cs < 2) return 1;				/* Test for insanity */
-		if (cs == 0xFFFFFFFF) return cs;	/* Test for disk error */
-		if (cs < fs->n_fatent) return cs;	/* It is already followed by next cluster */
-		scl = clst;							/* Cluster to start to find */
-	}
-	if (fs->free_clst == 0) return 0;		/* No free cluster */
-
-#if FF_FS_EXFAT
-	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
-		ncl = find_bitmap(fs, scl, 1);				/* Find a free cluster */
-		if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl;	/* No free cluster or hard error? */
-		res = change_bitmap(fs, ncl, 1, 1);			/* Mark the cluster 'in use' */
-		if (res == FR_INT_ERR) return 1;
-		if (res == FR_DISK_ERR) return 0xFFFFFFFF;
-		if (clst == 0) {							/* Is it a new chain? */
-			obj->stat = 2;							/* Set status 'contiguous' */
-		} else {									/* It is a stretched chain */
-			if (obj->stat == 2 && ncl != scl + 1) {	/* Is the chain got fragmented? */
-				obj->n_cont = scl - obj->sclust;	/* Set size of the contiguous part */
-				obj->stat = 3;						/* Change status 'just fragmented' */
-			}
-		}
-		if (obj->stat != 2) {	/* Is the file non-contiguous? */
-			if (ncl == clst + 1) {	/* Is the cluster next to previous one? */
-				obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2;	/* Increment size of last framgent */
-			} else {				/* New fragment */
-				if (obj->n_frag == 0) obj->n_frag = 1;
-				res = fill_last_frag(obj, clst, ncl);	/* Fill last fragment on the FAT and link it to new one */
-				if (res == FR_OK) obj->n_frag = 1;
-			}
-		}
-	} else
-#endif
-	{	/* On the FAT/FAT32 volume */
-		ncl = 0;
-		if (scl == clst) {						/* Stretching an existing chain? */
-			ncl = scl + 1;						/* Test if next cluster is free */
-			if (ncl >= fs->n_fatent) ncl = 2;
-			cs = get_fat(obj, ncl);				/* Get next cluster status */
-			if (cs == 1 || cs == 0xFFFFFFFF) return cs;	/* Test for error */
-			if (cs != 0) {						/* Not free? */
-				cs = fs->last_clst;				/* Start at suggested cluster if it is valid */
-				if (cs >= 2 && cs < fs->n_fatent) scl = cs;
-				ncl = 0;
-			}
-		}
-		if (ncl == 0) {	/* The new cluster cannot be contiguous and find another fragment */
-			ncl = scl;	/* Start cluster */
-			for (;;) {
-				ncl++;							/* Next cluster */
-				if (ncl >= fs->n_fatent) {		/* Check wrap-around */
-					ncl = 2;
-					if (ncl > scl) return 0;	/* No free cluster found? */
-				}
-				cs = get_fat(obj, ncl);			/* Get the cluster status */
-				if (cs == 0) break;				/* Found a free cluster? */
-				if (cs == 1 || cs == 0xFFFFFFFF) return cs;	/* Test for error */
-				if (ncl == scl) return 0;		/* No free cluster found? */
-			}
-		}
-		res = put_fat(fs, ncl, 0xFFFFFFFF);		/* Mark the new cluster 'EOC' */
-		if (res == FR_OK && clst != 0) {
-			res = put_fat(fs, clst, ncl);		/* Link it from the previous one if needed */
-		}
-	}
-
-	if (res == FR_OK) {			/* Update FSINFO if function succeeded. */
-		fs->last_clst = ncl;
-		if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--;
-		fs->fsi_flag |= 1;
-	} else {
-		ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;	/* Failed. Generate error status */
-	}
-
-	return ncl;		/* Return new cluster number or error status */
-}
-
-#endif /* !FF_FS_READONLY */
-
-
-
-
-#if FF_USE_FASTSEEK
-/*-----------------------------------------------------------------------*/
-/* FAT handling - Convert offset into cluster with link map table        */
-/*-----------------------------------------------------------------------*/
-
-static DWORD clmt_clust (	/* <2:Error, >=2:Cluster number */
-	FIL* fp,		/* Pointer to the file object */
-	FSIZE_t ofs		/* File offset to be converted to cluster# */
-)
-{
-	DWORD cl, ncl, *tbl;
-	FATFS *fs = fp->obj.fs;
-
-
-	tbl = fp->cltbl + 1;	/* Top of CLMT */
-	cl = (DWORD)(ofs / SS(fs) / fs->csize);	/* Cluster order from top of the file */
-	for (;;) {
-		ncl = *tbl++;			/* Number of cluters in the fragment */
-		if (ncl == 0) return 0;	/* End of table? (error) */
-		if (cl < ncl) break;	/* In this fragment? */
-		cl -= ncl; tbl++;		/* Next fragment */
-	}
-	return cl + *tbl;	/* Return the cluster number */
-}
-
-#endif	/* FF_USE_FASTSEEK */
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Directory handling - Fill a cluster with zeros                        */
-/*-----------------------------------------------------------------------*/
-
-#if !FF_FS_READONLY
-static FRESULT dir_clear (	/* Returns FR_OK or FR_DISK_ERR */
-	FATFS *fs,		/* Filesystem object */
-	DWORD clst		/* Directory table to clear */
-)
-{
-	DWORD sect;
-	UINT n, szb;
-	BYTE *ibuf;
-
-
-	if (sync_window(fs) != FR_OK) return FR_DISK_ERR;	/* Flush disk access window */
-	sect = clst2sect(fs, clst);		/* Top of the cluster */
-	fs->winsect = sect;				/* Set window to top of the cluster */
-	mem_set(fs->win, 0, sizeof fs->win);	/* Clear window buffer */
-#if FF_USE_LFN == 3		/* Quick table clear by using multi-secter write */
-	/* Allocate a temporary buffer */
-	for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
-	if (szb > SS(fs)) {		/* Buffer allocated? */
-		mem_set(ibuf, 0, szb);
-		szb /= SS(fs);		/* Bytes -> Sectors */
-		for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ;	/* Fill the cluster with 0 */
-		ff_memfree(ibuf);
-	} else
-#endif
-	{
-		ibuf = fs->win; szb = 1;	/* Use window buffer (many single-sector writes may take a time) */
-		for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ;	/* Fill the cluster with 0 */
-	}
-	return (n == fs->csize) ? FR_OK : FR_DISK_ERR;
-}
-#endif	/* !FF_FS_READONLY */
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Directory handling - Set directory index                              */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT dir_sdi (	/* FR_OK(0):succeeded, !=0:error */
-	DIR* dp,		/* Pointer to directory object */
-	DWORD ofs		/* Offset of directory table */
-)
-{
-	DWORD csz, clst;
-	FATFS *fs = dp->obj.fs;
-
-
-	if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) {	/* Check range of offset and alignment */
-		return FR_INT_ERR;
-	}
-	dp->dptr = ofs;				/* Set current offset */
-	clst = dp->obj.sclust;		/* Table start cluster (0:root) */
-	if (clst == 0 && fs->fs_type >= FS_FAT32) {	/* Replace cluster# 0 with root cluster# */
-		clst = fs->dirbase;
-		if (FF_FS_EXFAT) dp->obj.stat = 0;	/* exFAT: Root dir has an FAT chain */
-	}
-
-	if (clst == 0) {	/* Static table (root-directory on the FAT volume) */
-		if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR;	/* Is index out of range? */
-		dp->sect = fs->dirbase;
-
-	} else {			/* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */
-		csz = (DWORD)fs->csize * SS(fs);	/* Bytes per cluster */
-		while (ofs >= csz) {				/* Follow cluster chain */
-			clst = get_fat(&dp->obj, clst);				/* Get next cluster */
-			if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
-			if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR;	/* Reached to end of table or internal error */
-			ofs -= csz;
-		}
-		dp->sect = clst2sect(fs, clst);
-	}
-	dp->clust = clst;					/* Current cluster# */
-	if (dp->sect == 0) return FR_INT_ERR;
-	dp->sect += ofs / SS(fs);			/* Sector# of the directory entry */
-	dp->dir = fs->win + (ofs % SS(fs));	/* Pointer to the entry in the win[] */
-
-	return FR_OK;
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Directory handling - Move directory table index next                  */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT dir_next (	/* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */
-	DIR* dp,				/* Pointer to the directory object */
-	int stretch				/* 0: Do not stretch table, 1: Stretch table if needed */
-)
-{
-	DWORD ofs, clst;
-	FATFS *fs = dp->obj.fs;
-
-
-	ofs = dp->dptr + SZDIRE;	/* Next entry */
-	if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0;	/* Disable it if the offset reached the max value */
-	if (dp->sect == 0) return FR_NO_FILE;	/* Report EOT if it has been disabled */
-
-	if (ofs % SS(fs) == 0) {	/* Sector changed? */
-		dp->sect++;				/* Next sector */
-
-		if (dp->clust == 0) {	/* Static table */
-			if (ofs / SZDIRE >= fs->n_rootdir) {	/* Report EOT if it reached end of static table */
-				dp->sect = 0; return FR_NO_FILE;
-			}
-		}
-		else {					/* Dynamic table */
-			if ((ofs / SS(fs) & (fs->csize - 1)) == 0) {	/* Cluster changed? */
-				clst = get_fat(&dp->obj, dp->clust);		/* Get next cluster */
-				if (clst <= 1) return FR_INT_ERR;			/* Internal error */
-				if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
-				if (clst >= fs->n_fatent) {					/* It reached end of dynamic table */
-#if !FF_FS_READONLY
-					if (!stretch) {								/* If no stretch, report EOT */
-						dp->sect = 0; return FR_NO_FILE;
-					}
-					clst = create_chain(&dp->obj, dp->clust);	/* Allocate a cluster */
-					if (clst == 0) return FR_DENIED;			/* No free cluster */
-					if (clst == 1) return FR_INT_ERR;			/* Internal error */
-					if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
-					if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR;	/* Clean up the stretched table */
-					if (FF_FS_EXFAT) dp->obj.stat |= 4;			/* exFAT: The directory has been stretched */
-#else
-					if (!stretch) dp->sect = 0;					/* (this line is to suppress compiler warning) */
-					dp->sect = 0; return FR_NO_FILE;			/* Report EOT */
-#endif
-				}
-				dp->clust = clst;		/* Initialize data for new cluster */
-				dp->sect = clst2sect(fs, clst);
-			}
-		}
-	}
-	dp->dptr = ofs;						/* Current entry */
-	dp->dir = fs->win + ofs % SS(fs);	/* Pointer to the entry in the win[] */
-
-	return FR_OK;
-}
-
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Directory handling - Reserve a block of directory entries             */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT dir_alloc (	/* FR_OK(0):succeeded, !=0:error */
-	DIR* dp,				/* Pointer to the directory object */
-	UINT nent				/* Number of contiguous entries to allocate */
-)
-{
-	FRESULT res;
-	UINT n;
-	FATFS *fs = dp->obj.fs;
-
-
-	res = dir_sdi(dp, 0);
-	if (res == FR_OK) {
-		n = 0;
-		do {
-			res = move_window(fs, dp->sect);
-			if (res != FR_OK) break;
-#if FF_FS_EXFAT
-			if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) {
-#else
-			if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) {
-#endif
-				if (++n == nent) break;	/* A block of contiguous free entries is found */
-			} else {
-				n = 0;					/* Not a blank entry. Restart to search */
-			}
-			res = dir_next(dp, 1);
-		} while (res == FR_OK);	/* Next entry with table stretch enabled */
-	}
-
-	if (res == FR_NO_FILE) res = FR_DENIED;	/* No directory entry to allocate */
-	return res;
-}
-
-#endif	/* !FF_FS_READONLY */
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* FAT: Directory handling - Load/Store start cluster number             */
-/*-----------------------------------------------------------------------*/
-
-static DWORD ld_clust (	/* Returns the top cluster value of the SFN entry */
-	FATFS* fs,			/* Pointer to the fs object */
-	const BYTE* dir		/* Pointer to the key entry */
-)
-{
-	DWORD cl;
-
-	cl = ld_word(dir + DIR_FstClusLO);
-	if (fs->fs_type == FS_FAT32) {
-		cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16;
-	}
-
-	return cl;
-}
-
-
-#if !FF_FS_READONLY
-static void st_clust (
-	FATFS* fs,	/* Pointer to the fs object */
-	BYTE* dir,	/* Pointer to the key entry */
-	DWORD cl	/* Value to be set */
-)
-{
-	st_word(dir + DIR_FstClusLO, (WORD)cl);
-	if (fs->fs_type == FS_FAT32) {
-		st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16));
-	}
-}
-#endif
-
-
-
-#if FF_USE_LFN
-/*--------------------------------------------------------*/
-/* FAT-LFN: Compare a part of file name with an LFN entry */
-/*--------------------------------------------------------*/
-
-static int cmp_lfn (		/* 1:matched, 0:not matched */
-	const WCHAR* lfnbuf,	/* Pointer to the LFN working buffer to be compared */
-	BYTE* dir				/* Pointer to the directory entry containing the part of LFN */
-)
-{
-	UINT i, s;
-	WCHAR wc, uc;
-
-
-	if (ld_word(dir + LDIR_FstClusLO) != 0) return 0;	/* Check LDIR_FstClusLO */
-
-	i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13;	/* Offset in the LFN buffer */
-
-	for (wc = 1, s = 0; s < 13; s++) {		/* Process all characters in the entry */
-		uc = ld_word(dir + LfnOfs[s]);		/* Pick an LFN character */
-		if (wc != 0) {
-			if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) {	/* Compare it */
-				return 0;					/* Not matched */
-			}
-			wc = uc;
-		} else {
-			if (uc != 0xFFFF) return 0;		/* Check filler */
-		}
-	}
-
-	if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0;	/* Last segment matched but different length */
-
-	return 1;		/* The part of LFN matched */
-}
-
-
-#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT
-/*-----------------------------------------------------*/
-/* FAT-LFN: Pick a part of file name from an LFN entry */
-/*-----------------------------------------------------*/
-
-static int pick_lfn (	/* 1:succeeded, 0:buffer overflow or invalid LFN entry */
-	WCHAR* lfnbuf,		/* Pointer to the LFN working buffer */
-	BYTE* dir			/* Pointer to the LFN entry */
-)
-{
-	UINT i, s;
-	WCHAR wc, uc;
-
-
-	if (ld_word(dir + LDIR_FstClusLO) != 0) return 0;	/* Check LDIR_FstClusLO is 0 */
-
-	i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13;	/* Offset in the LFN buffer */
-
-	for (wc = 1, s = 0; s < 13; s++) {		/* Process all characters in the entry */
-		uc = ld_word(dir + LfnOfs[s]);		/* Pick an LFN character */
-		if (wc != 0) {
-			if (i >= FF_MAX_LFN) return 0;	/* Buffer overflow? */
-			lfnbuf[i++] = wc = uc;			/* Store it */
-		} else {
-			if (uc != 0xFFFF) return 0;		/* Check filler */
-		}
-	}
-
-	if (dir[LDIR_Ord] & LLEF) {				/* Put terminator if it is the last LFN part */
-		if (i >= FF_MAX_LFN) return 0;		/* Buffer overflow? */
-		lfnbuf[i] = 0;
-	}
-
-	return 1;		/* The part of LFN is valid */
-}
-#endif
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------*/
-/* FAT-LFN: Create an entry of LFN entries */
-/*-----------------------------------------*/
-
-static void put_lfn (
-	const WCHAR* lfn,	/* Pointer to the LFN */
-	BYTE* dir,			/* Pointer to the LFN entry to be created */
-	BYTE ord,			/* LFN order (1-20) */
-	BYTE sum			/* Checksum of the corresponding SFN */
-)
-{
-	UINT i, s;
-	WCHAR wc;
-
-
-	dir[LDIR_Chksum] = sum;			/* Set checksum */
-	dir[LDIR_Attr] = AM_LFN;		/* Set attribute. LFN entry */
-	dir[LDIR_Type] = 0;
-	st_word(dir + LDIR_FstClusLO, 0);
-
-	i = (ord - 1) * 13;				/* Get offset in the LFN working buffer */
-	s = wc = 0;
-	do {
-		if (wc != 0xFFFF) wc = lfn[i++];	/* Get an effective character */
-		st_word(dir + LfnOfs[s], wc);		/* Put it */
-		if (wc == 0) wc = 0xFFFF;		/* Padding characters for left locations */
-	} while (++s < 13);
-	if (wc == 0xFFFF || !lfn[i]) ord |= LLEF;	/* Last LFN part is the start of LFN sequence */
-	dir[LDIR_Ord] = ord;			/* Set the LFN order */
-}
-
-#endif	/* !FF_FS_READONLY */
-#endif	/* FF_USE_LFN */
-
-
-
-#if FF_USE_LFN && !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* FAT-LFN: Create a Numbered SFN                                        */
-/*-----------------------------------------------------------------------*/
-
-static void gen_numname (
-	BYTE* dst,			/* Pointer to the buffer to store numbered SFN */
-	const BYTE* src,	/* Pointer to SFN */
-	const WCHAR* lfn,	/* Pointer to LFN */
-	UINT seq			/* Sequence number */
-)
-{
-	BYTE ns[8], c;
-	UINT i, j;
-	WCHAR wc;
-	DWORD sr;
-
-
-	mem_cpy(dst, src, 11);
-
-	if (seq > 5) {	/* In case of many collisions, generate a hash number instead of sequential number */
-		sr = seq;
-		while (*lfn) {	/* Create a CRC as hash value */
-			wc = *lfn++;
-			for (i = 0; i < 16; i++) {
-				sr = (sr << 1) + (wc & 1);
-				wc >>= 1;
-				if (sr & 0x10000) sr ^= 0x11021;
-			}
-		}
-		seq = (UINT)sr;
-	}
-
-	/* itoa (hexdecimal) */
-	i = 7;
-	do {
-		c = (BYTE)((seq % 16) + '0');
-		if (c > '9') c += 7;
-		ns[i--] = c;
-		seq /= 16;
-	} while (seq);
-	ns[i] = '~';
-
-	/* Append the number to the SFN body */
-	for (j = 0; j < i && dst[j] != ' '; j++) {
-		if (dbc_1st(dst[j])) {
-			if (j == i - 1) break;
-			j++;
-		}
-	}
-	do {
-		dst[j++] = (i < 8) ? ns[i++] : ' ';
-	} while (j < 8);
-}
-#endif	/* FF_USE_LFN && !FF_FS_READONLY */
-
-
-
-#if FF_USE_LFN
-/*-----------------------------------------------------------------------*/
-/* FAT-LFN: Calculate checksum of an SFN entry                           */
-/*-----------------------------------------------------------------------*/
-
-static BYTE sum_sfn (
-	const BYTE* dir		/* Pointer to the SFN entry */
-)
-{
-	BYTE sum = 0;
-	UINT n = 11;
-
-	do {
-		sum = (sum >> 1) + (sum << 7) + *dir++;
-	} while (--n);
-	return sum;
-}
-
-#endif	/* FF_USE_LFN */
-
-
-
-#if FF_FS_EXFAT
-/*-----------------------------------------------------------------------*/
-/* exFAT: Checksum                                                       */
-/*-----------------------------------------------------------------------*/
-
-static WORD xdir_sum (	/* Get checksum of the directoly entry block */
-	const BYTE* dir		/* Directory entry block to be calculated */
-)
-{
-	UINT i, szblk;
-	WORD sum;
-
-
-	szblk = (dir[XDIR_NumSec] + 1) * SZDIRE;	/* Number of bytes of the entry block */
-	for (i = sum = 0; i < szblk; i++) {
-		if (i == XDIR_SetSum) {	/* Skip 2-byte sum field */
-			i++;
-		} else {
-			sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i];
-		}
-	}
-	return sum;
-}
-
-
-
-static WORD xname_sum (	/* Get check sum (to be used as hash) of the file name */
-	const WCHAR* name	/* File name to be calculated */
-)
-{
-	WCHAR chr;
-	WORD sum = 0;
-
-
-	while ((chr = *name++) != 0) {
-		chr = (WCHAR)ff_wtoupper(chr);		/* File name needs to be up-case converted */
-		sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF);
-		sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8);
-	}
-	return sum;
-}
-
-
-#if !FF_FS_READONLY && FF_USE_MKFS
-static DWORD xsum32 (	/* Returns 32-bit checksum */
-	BYTE  dat,			/* Byte to be calculated (byte-by-byte processing) */
-	DWORD sum			/* Previous sum value */
-)
-{
-	sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat;
-	return sum;
-}
-#endif
-
-
-#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2
-/*------------------------------------------------------*/
-/* exFAT: Get object information from a directory block */
-/*------------------------------------------------------*/
-
-static void get_xfileinfo (
-	BYTE* dirb,			/* Pointer to the direcotry entry block 85+C0+C1s */
-	FILINFO* fno		/* Buffer to store the extracted file information */
-)
-{
-	WCHAR wc, hs;
-	UINT di, si, nc;
-
-	/* Get file name from the entry block */
-	si = SZDIRE * 2;	/* 1st C1 entry */
-	nc = 0; hs = 0; di = 0;
-	while (nc < dirb[XDIR_NumName]) {
-		if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; }	/* Truncated directory block? */
-		if ((si % SZDIRE) == 0) si += 2;		/* Skip entry type field */
-		wc = ld_word(dirb + si); si += 2; nc++;	/* Get a character */
-		if (hs == 0 && IsSurrogate(wc)) {	/* Is it a surrogate? */
-			hs = wc; continue;	/* Get low surrogate */
-		}
-		wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di);	/* Store it in API encoding */
-		if (wc == 0) { di = 0; break; }	/* Buffer overflow or wrong encoding? */
-		di += wc;
-		hs = 0;
-	}
-	if (hs != 0) di = 0;					/* Broken surrogate pair? */
-	if (di == 0) fno->fname[di++] = '?';	/* Inaccessible object name? */
-	fno->fname[di] = 0;						/* Terminate the name */
-	fno->altname[0] = 0;					/* exFAT does not support SFN */
-
-	fno->fattrib = dirb[XDIR_Attr];			/* Attribute */
-	fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize);	/* Size */
-	fno->ftime = ld_word(dirb + XDIR_ModTime + 0);	/* Time */
-	fno->fdate = ld_word(dirb + XDIR_ModTime + 2);	/* Date */
-}
-
-#endif	/* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */
-
-
-/*-----------------------------------*/
-/* exFAT: Get a directry entry block */
-/*-----------------------------------*/
-
-static FRESULT load_xdir (	/* FR_INT_ERR: invalid entry block */
-	DIR* dp					/* Reading direcotry object pointing top of the entry block to load */
-)
-{
-	FRESULT res;
-	UINT i, sz_ent;
-	BYTE* dirb = dp->obj.fs->dirbuf;	/* Pointer to the on-memory direcotry entry block 85+C0+C1s */
-
-
-	/* Load file-directory entry */
-	res = move_window(dp->obj.fs, dp->sect);
-	if (res != FR_OK) return res;
-	if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR;	/* Invalid order */
-	mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
-	sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
-	if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
-
-	/* Load stream-extension entry */
-	res = dir_next(dp, 0);
-	if (res == FR_NO_FILE) res = FR_INT_ERR;	/* It cannot be */
-	if (res != FR_OK) return res;
-	res = move_window(dp->obj.fs, dp->sect);
-	if (res != FR_OK) return res;
-	if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR;	/* Invalid order */
-	mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
-	if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
-
-	/* Load file-name entries */
-	i = 2 * SZDIRE;	/* Name offset to load */
-	do {
-		res = dir_next(dp, 0);
-		if (res == FR_NO_FILE) res = FR_INT_ERR;	/* It cannot be */
-		if (res != FR_OK) return res;
-		res = move_window(dp->obj.fs, dp->sect);
-		if (res != FR_OK) return res;
-		if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR;	/* Invalid order */
-		if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
-	} while ((i += SZDIRE) < sz_ent);
-
-	/* Sanity check (do it for only accessible object) */
-	if (i <= MAXDIRB(FF_MAX_LFN)) {
-		if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR;
-	}
-	return FR_OK;
-}
-
-
-/*------------------------------------------------------------------*/
-/* exFAT: Initialize object allocation info with loaded entry block */
-/*------------------------------------------------------------------*/
-
-static void init_alloc_info (
-	FATFS* fs,		/* Filesystem object */
-	FFOBJID* obj	/* Object allocation information to be initialized */
-)
-{
-	obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus);		/* Start cluster */
-	obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize);	/* Size */
-	obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;				/* Allocation status */
-	obj->n_frag = 0;										/* No last fragment info */
-}
-
-
-
-#if !FF_FS_READONLY || FF_FS_RPATH != 0
-/*------------------------------------------------*/
-/* exFAT: Load the object's directory entry block */
-/*------------------------------------------------*/
-
-static FRESULT load_obj_xdir (
-	DIR* dp,			/* Blank directory object to be used to access containing direcotry */
-	const FFOBJID* obj	/* Object with its containing directory information */
-)
-{
-	FRESULT res;
-
-	/* Open object containing directory */
-	dp->obj.fs = obj->fs;
-	dp->obj.sclust = obj->c_scl;
-	dp->obj.stat = (BYTE)obj->c_size;
-	dp->obj.objsize = obj->c_size & 0xFFFFFF00;
-	dp->obj.n_frag = 0;
-	dp->blk_ofs = obj->c_ofs;
-
-	res = dir_sdi(dp, dp->blk_ofs);	/* Goto object's entry block */
-	if (res == FR_OK) {
-		res = load_xdir(dp);		/* Load the object's entry block */
-	}
-	return res;
-}
-#endif
-
-
-#if !FF_FS_READONLY
-/*----------------------------------------*/
-/* exFAT: Store the directory entry block */
-/*----------------------------------------*/
-
-static FRESULT store_xdir (
-	DIR* dp				/* Pointer to the direcotry object */
-)
-{
-	FRESULT res;
-	UINT nent;
-	BYTE* dirb = dp->obj.fs->dirbuf;	/* Pointer to the direcotry entry block 85+C0+C1s */
-
-	/* Create set sum */
-	st_word(dirb + XDIR_SetSum, xdir_sum(dirb));
-	nent = dirb[XDIR_NumSec] + 1;
-
-	/* Store the direcotry entry block to the directory */
-	res = dir_sdi(dp, dp->blk_ofs);
-	while (res == FR_OK) {
-		res = move_window(dp->obj.fs, dp->sect);
-		if (res != FR_OK) break;
-		mem_cpy(dp->dir, dirb, SZDIRE);
-		dp->obj.fs->wflag = 1;
-		if (--nent == 0) break;
-		dirb += SZDIRE;
-		res = dir_next(dp, 0);
-	}
-	return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR;
-}
-
-
-
-/*-------------------------------------------*/
-/* exFAT: Create a new directory enrty block */
-/*-------------------------------------------*/
-
-static void create_xdir (
-	BYTE* dirb,			/* Pointer to the direcotry entry block buffer */
-	const WCHAR* lfn	/* Pointer to the object name */
-)
-{
-	UINT i;
-	BYTE nc1, nlen;
-	WCHAR wc;
-
-
-	/* Create file-directory and stream-extension entry */
-	mem_set(dirb, 0, 2 * SZDIRE);
-	dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
-	dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
-
-	/* Create file-name entries */
-	i = SZDIRE * 2;	/* Top of file_name entries */
-	nlen = nc1 = 0; wc = 1;
-	do {
-		dirb[i++] = ET_FILENAME; dirb[i++] = 0;
-		do {	/* Fill name field */
-			if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++;	/* Get a character if exist */
-			st_word(dirb + i, wc); 		/* Store it */
-			i += 2;
-		} while (i % SZDIRE != 0);
-		nc1++;
-	} while (lfn[nlen]);	/* Fill next entry if any char follows */
-
-	dirb[XDIR_NumName] = nlen;		/* Set name length */
-	dirb[XDIR_NumSec] = 1 + nc1;	/* Set secondary count (C0 + C1s) */
-	st_word(dirb + XDIR_NameHash, xname_sum(lfn));	/* Set name hash */
-}
-
-#endif	/* !FF_FS_READONLY */
-#endif	/* FF_FS_EXFAT */
-
-
-
-#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT
-/*-----------------------------------------------------------------------*/
-/* Read an object from the directory                                     */
-/*-----------------------------------------------------------------------*/
-
-#define DIR_READ_FILE(dp) dir_read(dp, 0)
-#define DIR_READ_LABEL(dp) dir_read(dp, 1)
-
-static FRESULT dir_read (
-	DIR* dp,		/* Pointer to the directory object */
-	int vol			/* Filtered by 0:file/directory or 1:volume label */
-)
-{
-	FRESULT res = FR_NO_FILE;
-	FATFS *fs = dp->obj.fs;
-	BYTE attr, b;
-#if FF_USE_LFN
-	BYTE ord = 0xFF, sum = 0xFF;
-#endif
-
-	while (dp->sect) {
-		res = move_window(fs, dp->sect);
-		if (res != FR_OK) break;
-		b = dp->dir[DIR_Name];	/* Test for the entry type */
-		if (b == 0) {
-			res = FR_NO_FILE; break; /* Reached to end of the directory */
-		}
-#if FF_FS_EXFAT
-		if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
-			if (FF_USE_LABEL && vol) {
-				if (b == ET_VLABEL) break;	/* Volume label entry? */
-			} else {
-				if (b == ET_FILEDIR) {		/* Start of the file entry block? */
-					dp->blk_ofs = dp->dptr;	/* Get location of the block */
-					res = load_xdir(dp);	/* Load the entry block */
-					if (res == FR_OK) {
-						dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK;	/* Get attribute */
-					}
-					break;
-				}
-			}
-		} else
-#endif
-		{	/* On the FAT/FAT32 volume */
-			dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK;	/* Get attribute */
-#if FF_USE_LFN		/* LFN configuration */
-			if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) {	/* An entry without valid data */
-				ord = 0xFF;
-			} else {
-				if (attr == AM_LFN) {			/* An LFN entry is found */
-					if (b & LLEF) {			/* Is it start of an LFN sequence? */
-						sum = dp->dir[LDIR_Chksum];
-						b &= (BYTE)~LLEF; ord = b;
-						dp->blk_ofs = dp->dptr;
-					}
-					/* Check LFN validity and capture it */
-					ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
-				} else {					/* An SFN entry is found */
-					if (ord != 0 || sum != sum_sfn(dp->dir)) {	/* Is there a valid LFN? */
-						dp->blk_ofs = 0xFFFFFFFF;			/* It has no LFN. */
-					}
-					break;
-				}
-			}
-#else		/* Non LFN configuration */
-			if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) {	/* Is it a valid entry? */
-				break;
-			}
-#endif
-		}
-		res = dir_next(dp, 0);		/* Next entry */
-		if (res != FR_OK) break;
-	}
-
-	if (res != FR_OK) dp->sect = 0;		/* Terminate the read operation on error or EOT */
-	return res;
-}
-
-#endif	/* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Directory handling - Find an object in the directory                  */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT dir_find (	/* FR_OK(0):succeeded, !=0:error */
-	DIR* dp					/* Pointer to the directory object with the file name */
-)
-{
-	FRESULT res;
-	FATFS *fs = dp->obj.fs;
-	BYTE c;
-#if FF_USE_LFN
-	BYTE a, ord, sum;
-#endif
-
-	res = dir_sdi(dp, 0);			/* Rewind directory object */
-	if (res != FR_OK) return res;
-#if FF_FS_EXFAT
-	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
-		BYTE nc;
-		UINT di, ni;
-		WORD hash = xname_sum(fs->lfnbuf);		/* Hash value of the name to find */
-
-		while ((res = DIR_READ_FILE(dp)) == FR_OK) {	/* Read an item */
-#if FF_MAX_LFN < 255
-			if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue;			/* Skip comparison if inaccessible object name */
-#endif
-			if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue;	/* Skip comparison if hash mismatched */
-			for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) {	/* Compare the name */
-				if ((di % SZDIRE) == 0) di += 2;
-				if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break;
-			}
-			if (nc == 0 && !fs->lfnbuf[ni]) break;	/* Name matched? */
-		}
-		return res;
-	}
-#endif
-	/* On the FAT/FAT32 volume */
-#if FF_USE_LFN
-	ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF;	/* Reset LFN sequence */
-#endif
-	do {
-		res = move_window(fs, dp->sect);
-		if (res != FR_OK) break;
-		c = dp->dir[DIR_Name];
-		if (c == 0) { res = FR_NO_FILE; break; }	/* Reached to end of table */
-#if FF_USE_LFN		/* LFN configuration */
-		dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK;
-		if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) {	/* An entry without valid data */
-			ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF;	/* Reset LFN sequence */
-		} else {
-			if (a == AM_LFN) {			/* An LFN entry is found */
-				if (!(dp->fn[NSFLAG] & NS_NOLFN)) {
-					if (c & LLEF) {		/* Is it start of LFN sequence? */
-						sum = dp->dir[LDIR_Chksum];
-						c &= (BYTE)~LLEF; ord = c;	/* LFN start order */
-						dp->blk_ofs = dp->dptr;	/* Start offset of LFN */
-					}
-					/* Check validity of the LFN entry and compare it with given name */
-					ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
-				}
-			} else {					/* An SFN entry is found */
-				if (ord == 0 && sum == sum_sfn(dp->dir)) break;	/* LFN matched? */
-				if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break;	/* SFN matched? */
-				ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF;	/* Reset LFN sequence */
-			}
-		}
-#else		/* Non LFN configuration */
-		dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK;
-		if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break;	/* Is it a valid entry? */
-#endif
-		res = dir_next(dp, 0);	/* Next entry */
-	} while (res == FR_OK);
-
-	return res;
-}
-
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Register an object to the directory                                   */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT dir_register (	/* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */
-	DIR* dp						/* Target directory with object name to be created */
-)
-{
-	FRESULT res;
-	FATFS *fs = dp->obj.fs;
-#if FF_USE_LFN		/* LFN configuration */
-	UINT n, nlen, nent;
-	BYTE sn[12], sum;
-
-
-	if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME;	/* Check name validity */
-	for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ;	/* Get lfn length */
-
-#if FF_FS_EXFAT
-	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
-		nent = (nlen + 14) / 15 + 2;	/* Number of entries to allocate (85+C0+C1s) */
-		res = dir_alloc(dp, nent);		/* Allocate directory entries */
-		if (res != FR_OK) return res;
-		dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1);	/* Set the allocated entry block offset */
-
-		if (dp->obj.stat & 4) {			/* Has the directory been stretched by new allocation? */
-			dp->obj.stat &= ~4;
-			res = fill_first_frag(&dp->obj);	/* Fill the first fragment on the FAT if needed */
-			if (res != FR_OK) return res;
-			res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF);	/* Fill the last fragment on the FAT if needed */
-			if (res != FR_OK) return res;
-			if (dp->obj.sclust != 0) {		/* Is it a sub-directory? */
-				DIR dj;
-
-				res = load_obj_xdir(&dj, &dp->obj);	/* Load the object status */
-				if (res != FR_OK) return res;
-				dp->obj.objsize += (DWORD)fs->csize * SS(fs);			/* Increase the directory size by cluster size */
-				st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize);	/* Update the allocation status */
-				st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
-				fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
-				res = store_xdir(&dj);				/* Store the object status */
-				if (res != FR_OK) return res;
-			}
-		}
-
-		create_xdir(fs->dirbuf, fs->lfnbuf);	/* Create on-memory directory block to be written later */
-		return FR_OK;
-	}
-#endif
-	/* On the FAT/FAT32 volume */
-	mem_cpy(sn, dp->fn, 12);
-	if (sn[NSFLAG] & NS_LOSS) {			/* When LFN is out of 8.3 format, generate a numbered name */
-		dp->fn[NSFLAG] = NS_NOLFN;		/* Find only SFN */
-		for (n = 1; n < 100; n++) {
-			gen_numname(dp->fn, sn, fs->lfnbuf, n);	/* Generate a numbered name */
-			res = dir_find(dp);				/* Check if the name collides with existing SFN */
-			if (res != FR_OK) break;
-		}
-		if (n == 100) return FR_DENIED;		/* Abort if too many collisions */
-		if (res != FR_NO_FILE) return res;	/* Abort if the result is other than 'not collided' */
-		dp->fn[NSFLAG] = sn[NSFLAG];
-	}
-
-	/* Create an SFN with/without LFNs. */
-	nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1;	/* Number of entries to allocate */
-	res = dir_alloc(dp, nent);		/* Allocate entries */
-	if (res == FR_OK && --nent) {	/* Set LFN entry if needed */
-		res = dir_sdi(dp, dp->dptr - nent * SZDIRE);
-		if (res == FR_OK) {
-			sum = sum_sfn(dp->fn);	/* Checksum value of the SFN tied to the LFN */
-			do {					/* Store LFN entries in bottom first */
-				res = move_window(fs, dp->sect);
-				if (res != FR_OK) break;
-				put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum);
-				fs->wflag = 1;
-				res = dir_next(dp, 0);	/* Next entry */
-			} while (res == FR_OK && --nent);
-		}
-	}
-
-#else	/* Non LFN configuration */
-	res = dir_alloc(dp, 1);		/* Allocate an entry for SFN */
-
-#endif
-
-	/* Set SFN entry */
-	if (res == FR_OK) {
-		res = move_window(fs, dp->sect);
-		if (res == FR_OK) {
-			mem_set(dp->dir, 0, SZDIRE);	/* Clean the entry */
-			mem_cpy(dp->dir + DIR_Name, dp->fn, 11);	/* Put SFN */
-#if FF_USE_LFN
-			dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT);	/* Put NT flag */
-#endif
-			fs->wflag = 1;
-		}
-	}
-
-	return res;
-}
-
-#endif /* !FF_FS_READONLY */
-
-
-
-#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0
-/*-----------------------------------------------------------------------*/
-/* Remove an object from the directory                                   */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT dir_remove (	/* FR_OK:Succeeded, FR_DISK_ERR:A disk error */
-	DIR* dp					/* Directory object pointing the entry to be removed */
-)
-{
-	FRESULT res;
-	FATFS *fs = dp->obj.fs;
-#if FF_USE_LFN		/* LFN configuration */
-	DWORD last = dp->dptr;
-
-	res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs);	/* Goto top of the entry block if LFN is exist */
-	if (res == FR_OK) {
-		do {
-			res = move_window(fs, dp->sect);
-			if (res != FR_OK) break;
-			if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
-				dp->dir[XDIR_Type] &= 0x7F;	/* Clear the entry InUse flag. */
-			} else {									/* On the FAT/FAT32 volume */
-				dp->dir[DIR_Name] = DDEM;	/* Mark the entry 'deleted'. */
-			}
-			fs->wflag = 1;
-			if (dp->dptr >= last) break;	/* If reached last entry then all entries of the object has been deleted. */
-			res = dir_next(dp, 0);	/* Next entry */
-		} while (res == FR_OK);
-		if (res == FR_NO_FILE) res = FR_INT_ERR;
-	}
-#else			/* Non LFN configuration */
-
-	res = move_window(fs, dp->sect);
-	if (res == FR_OK) {
-		dp->dir[DIR_Name] = DDEM;	/* Mark the entry 'deleted'.*/
-		fs->wflag = 1;
-	}
-#endif
-
-	return res;
-}
-
-#endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */
-
-
-
-#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2
-/*-----------------------------------------------------------------------*/
-/* Get file information from directory entry                             */
-/*-----------------------------------------------------------------------*/
-
-static void get_fileinfo (
-	DIR* dp,			/* Pointer to the directory object */
-	FILINFO* fno		/* Pointer to the file information to be filled */
-)
-{
-	UINT si, di;
-#if FF_USE_LFN
-	WCHAR wc, hs;
-	FATFS *fs = dp->obj.fs;
-#else
-	TCHAR c;
-#endif
-
-
-	fno->fname[0] = 0;			/* Invaidate file info */
-	if (dp->sect == 0) return;	/* Exit if read pointer has reached end of directory */
-
-#if FF_USE_LFN		/* LFN configuration */
-#if FF_FS_EXFAT
-	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
-		get_xfileinfo(fs->dirbuf, fno);
-		return;
-	} else
-#endif
-	{	/* On the FAT/FAT32 volume */
-		if (dp->blk_ofs != 0xFFFFFFFF) {	/* Get LFN if available */
-			si = di = hs = 0;
-			while (fs->lfnbuf[si] != 0) {
-				wc = fs->lfnbuf[si++];		/* Get an LFN character (UTF-16) */
-				if (hs == 0 && IsSurrogate(wc)) {	/* Is it a surrogate? */
-					hs = wc; continue;		/* Get low surrogate */
-				}
-				wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di);	/* Store it in UTF-16 or UTF-8 encoding */
-				if (wc == 0) { di = 0; break; }	/* Invalid char or buffer overflow? */
-				di += wc;
-				hs = 0;
-			}
-			if (hs != 0) di = 0;	/* Broken surrogate pair? */
-			fno->fname[di] = 0;		/* Terminate the LFN (null string means LFN is invalid) */
-		}
-	}
-
-	si = di = 0;
-	while (si < 11) {		/* Get SFN from SFN entry */
-		wc = dp->dir[si++];			/* Get a char */
-		if (wc == ' ') continue;	/* Skip padding spaces */
-		if (wc == RDDEM) wc = DDEM;	/* Restore replaced DDEM character */
-		if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] = '.';	/* Insert a . if extension is exist */
-#if FF_LFN_UNICODE >= 1	/* Unicode output */
-		if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) {	/* Make a DBC if needed */
-			wc = wc << 8 | dp->dir[si++];
-		}
-		wc = ff_oem2uni(wc, CODEPAGE);		/* ANSI/OEM -> Unicode */
-		if (wc == 0) { di = 0; break; }		/* Wrong char in the current code page? */
-		wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di);	/* Store it in Unicode */
-		if (wc == 0) { di = 0; break; }		/* Buffer overflow? */
-		di += wc;
-#else					/* ANSI/OEM output */
-		fno->altname[di++] = (TCHAR)wc;	/* Store it without any conversion */
-#endif
-	}
-	fno->altname[di] = 0;	/* Terminate the SFN  (null string means SFN is invalid) */
-
-	if (fno->fname[0] == 0) {	/* If LFN is invalid, altname[] needs to be copied to fname[] */
-		if (di == 0) {	/* If LFN and SFN both are invalid, this object is inaccesible */
-			fno->fname[di++] = '?';
-		} else {
-			for (si = di = 0; fno->altname[si]; si++, di++) {	/* Copy altname[] to fname[] with case information */
-				wc = (WCHAR)fno->altname[si];
-				if (IsUpper(wc) && (dp->dir[DIR_NTres] & ((si >= 9) ? NS_EXT : NS_BODY))) wc += 0x20;
-				fno->fname[di] = (TCHAR)wc;
-			}
-		}
-		fno->fname[di] = 0;	/* Terminate the LFN */
-		if (!dp->dir[DIR_NTres]) fno->altname[0] = 0;	/* Altname is not needed if neither LFN nor case info is exist. */
-	}
-
-#else	/* Non-LFN configuration */
-	si = di = 0;
-	while (si < 11) {		/* Copy name body and extension */
-		c = (TCHAR)dp->dir[si++];
-		if (c == ' ') continue;		/* Skip padding spaces */
-		if (c == RDDEM) c = DDEM;	/* Restore replaced DDEM character */
-		if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */
-		fno->fname[di++] = c;
-	}
-	fno->fname[di] = 0;
-#endif
-
-	fno->fattrib = dp->dir[DIR_Attr];					/* Attribute */
-	fno->fsize = ld_dword(dp->dir + DIR_FileSize);		/* Size */
-	fno->ftime = ld_word(dp->dir + DIR_ModTime + 0);	/* Time */
-	fno->fdate = ld_word(dp->dir + DIR_ModTime + 2);	/* Date */
-}
-
-#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */
-
-
-
-#if FF_USE_FIND && FF_FS_MINIMIZE <= 1
-/*-----------------------------------------------------------------------*/
-/* Pattern matching                                                      */
-/*-----------------------------------------------------------------------*/
-
-static DWORD get_achar (	/* Get a character and advances ptr */
-	const TCHAR** ptr		/* Pointer to pointer to the ANSI/OEM or Unicode string */
-)
-{
-	DWORD chr;
-
-
-#if FF_USE_LFN && FF_LFN_UNICODE >= 1	/* Unicode input */
-	chr = tchar2uni(ptr);
-	if (chr == 0xFFFFFFFF) chr = 0;		/* Wrong UTF encoding is recognized as end of the string */
-	chr = ff_wtoupper(chr);
-
-#else									/* ANSI/OEM input */
-	chr = (BYTE)*(*ptr)++;				/* Get a byte */
-	if (IsLower(chr)) chr -= 0x20;		/* To upper ASCII char */
-#if FF_CODE_PAGE == 0
-	if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80];	/* To upper SBCS extended char */
-#elif FF_CODE_PAGE < 900
-	if (chr >= 0x80) chr = ExCvt[chr - 0x80];	/* To upper SBCS extended char */
-#endif
-#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900
-	if (dbc_1st((BYTE)chr)) {	/* Get DBC 2nd byte if needed */
-		chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0;
-	}
-#endif
-
-#endif
-	return chr;
-}
-
-
-static int pattern_matching (	/* 0:not matched, 1:matched */
-	const TCHAR* pat,	/* Matching pattern */
-	const TCHAR* nam,	/* String to be tested */
-	int skip,			/* Number of pre-skip chars (number of ?s) */
-	int inf				/* Infinite search (* specified) */
-)
-{
-	const TCHAR *pp, *np;
-	DWORD pc, nc;
-	int nm, nx;
-
-
-	while (skip--) {				/* Pre-skip name chars */
-		if (!get_achar(&nam)) return 0;	/* Branch mismatched if less name chars */
-	}
-	if (*pat == 0 && inf) return 1;	/* (short circuit) */
-
-	do {
-		pp = pat; np = nam;			/* Top of pattern and name to match */
-		for (;;) {
-			if (*pp == '?' || *pp == '*') {	/* Wildcard? */
-				nm = nx = 0;
-				do {				/* Analyze the wildcard block */
-					if (*pp++ == '?') nm++; else nx = 1;
-				} while (*pp == '?' || *pp == '*');
-				if (pattern_matching(pp, np, nm, nx)) return 1;	/* Test new branch (recurs upto number of wildcard blocks in the pattern) */
-				nc = *np; break;	/* Branch mismatched */
-			}
-			pc = get_achar(&pp);	/* Get a pattern char */
-			nc = get_achar(&np);	/* Get a name char */
-			if (pc != nc) break;	/* Branch mismatched? */
-			if (pc == 0) return 1;	/* Branch matched? (matched at end of both strings) */
-		}
-		get_achar(&nam);			/* nam++ */
-	} while (inf && nc);			/* Retry until end of name if infinite search is specified */
-
-	return 0;
-}
-
-#endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Pick a top segment and create the object name in directory form       */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT create_name (	/* FR_OK: successful, FR_INVALID_NAME: could not create */
-	DIR* dp,					/* Pointer to the directory object */
-	const TCHAR** path			/* Pointer to pointer to the segment in the path string */
-)
-{
-#if FF_USE_LFN		/* LFN configuration */
-	BYTE b, cf;
-	WCHAR wc, *lfn;
-	DWORD uc;
-	UINT i, ni, si, di;
-	const TCHAR *p;
-
-
-	/* Create LFN into LFN working buffer */
-	p = *path; lfn = dp->obj.fs->lfnbuf; di = 0;
-	for (;;) {
-		uc = tchar2uni(&p);			/* Get a character */
-		if (uc == 0xFFFFFFFF) return FR_INVALID_NAME;		/* Invalid code or UTF decode error */
-		if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16);	/* Store high surrogate if needed */
-		wc = (WCHAR)uc;
-		if (wc < ' ' || wc == '/' || wc == '\\') break;	/* Break if end of the path or a separator is found */
-		if (wc < 0x80 && chk_chr("\"*:<>\?|\x7F", wc)) return FR_INVALID_NAME;	/* Reject illegal characters for LFN */
-		if (di >= FF_MAX_LFN) return FR_INVALID_NAME;	/* Reject too long name */
-		lfn[di++] = wc;					/* Store the Unicode character */
-	}
-	while (*p == '/' || *p == '\\') p++;	/* Skip duplicated separators if exist */
-	*path = p;							/* Return pointer to the next segment */
-	cf = (wc < ' ') ? NS_LAST : 0;		/* Set last segment flag if end of the path */
-
-#if FF_FS_RPATH != 0
-	if ((di == 1 && lfn[di - 1] == '.') ||
-		(di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) {	/* Is this segment a dot name? */
-		lfn[di] = 0;
-		for (i = 0; i < 11; i++) {		/* Create dot name for SFN entry */
-			dp->fn[i] = (i < di) ? '.' : ' ';
-		}
-		dp->fn[i] = cf | NS_DOT;		/* This is a dot entry */
-		return FR_OK;
-	}
-#endif
-	while (di) {						/* Snip off trailing spaces and dots if exist */
-		wc = lfn[di - 1];
-		if (wc != ' ' && wc != '.') break;
-		di--;
-	}
-	lfn[di] = 0;							/* LFN is created into the working buffer */
-	if (di == 0) return FR_INVALID_NAME;	/* Reject null name */
-
-	/* Create SFN in directory form */
-	for (si = 0; lfn[si] == ' '; si++) ;	/* Remove leading spaces */
-	if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN;	/* Is there any leading space or dot? */
-	while (di > 0 && lfn[di - 1] != '.') di--;	/* Find last dot (di<=si: no extension) */
-
-	mem_set(dp->fn, ' ', 11);
-	i = b = 0; ni = 8;
-	for (;;) {
-		wc = lfn[si++];					/* Get an LFN character */
-		if (wc == 0) break;				/* Break on end of the LFN */
-		if (wc == ' ' || (wc == '.' && si != di)) {	/* Remove embedded spaces and dots */
-			cf |= NS_LOSS | NS_LFN;
-			continue;
-		}
-
-		if (i >= ni || si == di) {		/* End of field? */
-			if (ni == 11) {				/* Name extension overflow? */
-				cf |= NS_LOSS | NS_LFN;
-				break;
-			}
-			if (si != di) cf |= NS_LOSS | NS_LFN;	/* Name body overflow? */
-			if (si > di) break;						/* No name extension? */
-			si = di; i = 8; ni = 11; b <<= 2;		/* Enter name extension */
-			continue;
-		}
-
-		if (wc >= 0x80) {	/* Is this a non-ASCII character? */
-			cf |= NS_LFN;	/* LFN entry needs to be created */
-#if FF_CODE_PAGE == 0
-			if (ExCvt) {	/* At SBCS */
-				wc = ff_uni2oem(wc, CODEPAGE);			/* Unicode ==> ANSI/OEM code */
-				if (wc & 0x80) wc = ExCvt[wc & 0x7F];	/* Convert extended character to upper (SBCS) */
-			} else {		/* At DBCS */
-				wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE);	/* Unicode ==> Upper convert ==> ANSI/OEM code */
-			}
-#elif FF_CODE_PAGE < 900	/* SBCS cfg */
-			wc = ff_uni2oem(wc, CODEPAGE);			/* Unicode ==> ANSI/OEM code */
-			if (wc & 0x80) wc = ExCvt[wc & 0x7F];	/* Convert extended character to upper (SBCS) */
-#else						/* DBCS cfg */
-			wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE);	/* Unicode ==> Upper convert ==> ANSI/OEM code */
-#endif
-		}
-
-		if (wc >= 0x100) {				/* Is this a DBC? */
-			if (i >= ni - 1) {			/* Field overflow? */
-				cf |= NS_LOSS | NS_LFN;
-				i = ni; continue;		/* Next field */
-			}
-			dp->fn[i++] = (BYTE)(wc >> 8);	/* Put 1st byte */
-		} else {						/* SBC */
-			if (wc == 0 || chk_chr("+,;=[]", wc)) {	/* Replace illegal characters for SFN if needed */
-				wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
-			} else {
-				if (IsUpper(wc)) {		/* ASCII upper case? */
-					b |= 2;
-				}
-				if (IsLower(wc)) {		/* ASCII lower case? */
-					b |= 1; wc -= 0x20;
-				}
-			}
-		}
-		dp->fn[i++] = (BYTE)wc;
-	}
-
-	if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM;	/* If the first character collides with DDEM, replace it with RDDEM */
-
-	if (ni == 8) b <<= 2;				/* Shift capital flags if no extension */
-	if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN;	/* LFN entry needs to be created if composite capitals */
-	if (!(cf & NS_LFN)) {				/* When LFN is in 8.3 format without extended character, NT flags are created */
-		if (b & 0x01) cf |= NS_EXT;		/* NT flag (Extension has small capital letters only) */
-		if (b & 0x04) cf |= NS_BODY;	/* NT flag (Body has small capital letters only) */
-	}
-
-	dp->fn[NSFLAG] = cf;	/* SFN is created into dp->fn[] */
-
-	return FR_OK;
-
-
-#else	/* FF_USE_LFN : Non-LFN configuration */
-	BYTE c, d, *sfn;
-	UINT ni, si, i;
-	const char *p;
-
-	/* Create file name in directory form */
-	p = *path; sfn = dp->fn;
-	mem_set(sfn, ' ', 11);
-	si = i = 0; ni = 8;
-#if FF_FS_RPATH != 0
-	if (p[si] == '.') { /* Is this a dot entry? */
-		for (;;) {
-			c = (BYTE)p[si++];
-			if (c != '.' || si >= 3) break;
-			sfn[i++] = c;
-		}
-		if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
-		*path = p + si;								/* Return pointer to the next segment */
-		sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT;	/* Set last segment flag if end of the path */
-		return FR_OK;
-	}
-#endif
-	for (;;) {
-		c = (BYTE)p[si++];				/* Get a byte */
-		if (c <= ' ') break; 			/* Break if end of the path name */
-		if (c == '/' || c == '\\') {	/* Break if a separator is found */
-			while (p[si] == '/' || p[si] == '\\') si++;	/* Skip duplicated separator if exist */
-			break;
-		}
-		if (c == '.' || i >= ni) {		/* End of body or field overflow? */
-			if (ni == 11 || c != '.') return FR_INVALID_NAME;	/* Field overflow or invalid dot? */
-			i = 8; ni = 11;				/* Enter file extension field */
-			continue;
-		}
-#if FF_CODE_PAGE == 0
-		if (ExCvt && c >= 0x80) {		/* Is SBC extended character? */
-			c = ExCvt[c & 0x7F];		/* To upper SBC extended character */
-		}
-#elif FF_CODE_PAGE < 900
-		if (c >= 0x80) {				/* Is SBC extended character? */
-			c = ExCvt[c & 0x7F];		/* To upper SBC extended character */
-		}
-#endif
-		if (dbc_1st(c)) {				/* Check if it is a DBC 1st byte */
-			d = (BYTE)p[si++];			/* Get 2nd byte */
-			if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME;	/* Reject invalid DBC */
-			sfn[i++] = c;
-			sfn[i++] = d;
-		} else {						/* SBC */
-			if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME;	/* Reject illegal chrs for SFN */
-			if (IsLower(c)) c -= 0x20;	/* To upper */
-			sfn[i++] = c;
-		}
-	}
-	*path = p + si;						/* Return pointer to the next segment */
-	if (i == 0) return FR_INVALID_NAME;	/* Reject nul string */
-
-	if (sfn[0] == DDEM) sfn[0] = RDDEM;	/* If the first character collides with DDEM, replace it with RDDEM */
-	sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0;		/* Set last segment flag if end of the path */
-
-	return FR_OK;
-#endif /* FF_USE_LFN */
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Follow a file path                                                    */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
-	DIR* dp,					/* Directory object to return last directory and found object */
-	const TCHAR* path			/* Full-path string to find a file or directory */
-)
-{
-	FRESULT res;
-	BYTE ns;
-	FATFS *fs = dp->obj.fs;
-
-
-#if FF_FS_RPATH != 0
-	if (*path != '/' && *path != '\\') {	/* Without heading separator */
-		dp->obj.sclust = fs->cdir;				/* Start from current directory */
-	} else
-#endif
-	{										/* With heading separator */
-		while (*path == '/' || *path == '\\') path++;	/* Strip heading separator */
-		dp->obj.sclust = 0;					/* Start from root directory */
-	}
-#if FF_FS_EXFAT
-	dp->obj.n_frag = 0;	/* Invalidate last fragment counter of the object */
-#if FF_FS_RPATH != 0
-	if (fs->fs_type == FS_EXFAT && dp->obj.sclust) {	/* exFAT: Retrieve the sub-directory's status */
-		DIR dj;
-
-		dp->obj.c_scl = fs->cdc_scl;
-		dp->obj.c_size = fs->cdc_size;
-		dp->obj.c_ofs = fs->cdc_ofs;
-		res = load_obj_xdir(&dj, &dp->obj);
-		if (res != FR_OK) return res;
-		dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize);
-		dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
-	}
-#endif
-#endif
-
-	if ((UINT)*path < ' ') {				/* Null path name is the origin directory itself */
-		dp->fn[NSFLAG] = NS_NONAME;
-		res = dir_sdi(dp, 0);
-
-	} else {								/* Follow path */
-		for (;;) {
-			res = create_name(dp, &path);	/* Get a segment name of the path */
-			if (res != FR_OK) break;
-			res = dir_find(dp);				/* Find an object with the segment name */
-			ns = dp->fn[NSFLAG];
-			if (res != FR_OK) {				/* Failed to find the object */
-				if (res == FR_NO_FILE) {	/* Object is not found */
-					if (FF_FS_RPATH && (ns & NS_DOT)) {	/* If dot entry is not exist, stay there */
-						if (!(ns & NS_LAST)) continue;	/* Continue to follow if not last segment */
-						dp->fn[NSFLAG] = NS_NONAME;
-						res = FR_OK;
-					} else {							/* Could not find the object */
-						if (!(ns & NS_LAST)) res = FR_NO_PATH;	/* Adjust error code if not last segment */
-					}
-				}
-				break;
-			}
-			if (ns & NS_LAST) break;			/* Last segment matched. Function completed. */
-			/* Get into the sub-directory */
-			if (!(dp->obj.attr & AM_DIR)) {		/* It is not a sub-directory and cannot follow */
-				res = FR_NO_PATH; break;
-			}
-#if FF_FS_EXFAT
-			if (fs->fs_type == FS_EXFAT) {		/* Save containing directory information for next dir */
-				dp->obj.c_scl = dp->obj.sclust;
-				dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
-				dp->obj.c_ofs = dp->blk_ofs;
-				init_alloc_info(fs, &dp->obj);	/* Open next directory */
-			} else
-#endif
-			{
-				dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs));	/* Open next directory */
-			}
-		}
-	}
-
-	return res;
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Get logical drive number from path name                               */
-/*-----------------------------------------------------------------------*/
-
-static int get_ldnumber (	/* Returns logical drive number (-1:invalid drive number or null pointer) */
-	const TCHAR** path		/* Pointer to pointer to the path name */
-)
-{
-	const TCHAR *tp, *tt;
-	TCHAR tc;
-	int i, vol = -1;
-#if FF_STR_VOLUME_ID		/* Find string volume ID */
-	const char *sp;
-	char c;
-#endif
-
-	tt = tp = *path;
-	if (!tp) return vol;	/* Invalid path name? */
-	do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':');	/* Find a colon in the path */
-
-	if (tc == ':') {	/* DOS/Windows style volume ID? */
-		i = FF_VOLUMES;
-		if (IsDigit(*tp) && tp + 2 == tt) {	/* Is there a numeric volume ID + colon? */
-			i = (int)*tp - '0';	/* Get the LD number */
-		}
-#if FF_STR_VOLUME_ID == 1	/* Arbitrary string is enabled */
-		else {
-			i = 0;
-			do {
-				sp = VolumeStr[i]; tp = *path;	/* This string volume ID and path name */
-				do {	/* Compare the volume ID with path name */
-					c = *sp++; tc = *tp++;
-					if (IsLower(c)) c -= 0x20;
-					if (IsLower(tc)) tc -= 0x20;
-				} while (c && (TCHAR)c == tc);
-			} while ((c || tp != tt) && ++i < FF_VOLUMES);	/* Repeat for each id until pattern match */
-		}
-#endif
-		if (i < FF_VOLUMES) {	/* If a volume ID is found, get the drive number and strip it */
-			vol = i;		/* Drive number */
-			*path = tt;		/* Snip the drive prefix off */
-		}
-		return vol;
-	}
-#if FF_STR_VOLUME_ID == 2		/* Unix style volume ID is enabled */
-	if (*tp == '/') {
-		i = 0;
-		do {
-			sp = VolumeStr[i]; tp = *path;	/* This string volume ID and path name */
-			do {	/* Compare the volume ID with path name */
-				c = *sp++; tc = *(++tp);
-				if (IsLower(c)) c -= 0x20;
-				if (IsLower(tc)) tc -= 0x20;
-			} while (c && (TCHAR)c == tc);
-		} while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES);	/* Repeat for each ID until pattern match */
-		if (i < FF_VOLUMES) {	/* If a volume ID is found, get the drive number and strip it */
-			vol = i;		/* Drive number */
-			*path = tp;		/* Snip the drive prefix off */
-			return vol;
-		}
-	}
-#endif
-	/* No drive prefix is found */
-#if FF_FS_RPATH != 0
-	vol = CurrVol;	/* Default drive is current drive */
-#else
-	vol = 0;		/* Default drive is 0 */
-#endif
-	return vol;		/* Return the default drive */
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Load a sector and check if it is an FAT VBR                           */
-/*-----------------------------------------------------------------------*/
-
-static BYTE check_fs (	/* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */
-	FATFS* fs,			/* Filesystem object */
-	DWORD sect			/* Sector# (lba) to load and check if it is an FAT-VBR or not */
-)
-{
-	fs->wflag = 0; fs->winsect = 0xFFFFFFFF;		/* Invaidate window */
-	if (move_window(fs, sect) != FR_OK) return 4;	/* Load boot record */
-
-	if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3;	/* Check boot record signature (always here regardless of the sector size) */
-
-#if FF_FS_EXFAT
-	if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT   ", 11)) return 1;	/* Check if exFAT VBR */
-#endif
-	if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) {	/* Valid JumpBoot code? */
-		if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0;		/* Is it an FAT VBR? */
-		if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0;	/* Is it an FAT32 VBR? */
-	}
-	return 2;	/* Valid BS but not FAT */
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Determine logical drive number and mount the volume if needed         */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT find_volume (	/* FR_OK(0): successful, !=0: an error occurred */
-	const TCHAR** path,			/* Pointer to pointer to the path name (drive number) */
-	FATFS** rfs,				/* Pointer to pointer to the found filesystem object */
-	BYTE mode					/* !=0: Check write protection for write access */
-)
-{
-	BYTE fmt, *pt;
-	int vol;
-	DSTATUS stat;
-	DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
-	WORD nrsv;
-	FATFS *fs;
-	UINT i;
-
-
-	/* Get logical drive number */
-	*rfs = 0;
-	vol = get_ldnumber(path);
-	if (vol < 0) return FR_INVALID_DRIVE;
-
-	/* Check if the filesystem object is valid or not */
-	fs = FatFs[vol];					/* Get pointer to the filesystem object */
-	if (!fs) return FR_NOT_ENABLED;		/* Is the filesystem object available? */
-#if FF_FS_REENTRANT
-	if (!lock_fs(fs)) return FR_TIMEOUT;	/* Lock the volume */
-#endif
-	*rfs = fs;							/* Return pointer to the filesystem object */
-
-	mode &= (BYTE)~FA_READ;				/* Desired access mode, write access or not */
-	if (fs->fs_type != 0) {				/* If the volume has been mounted */
-		stat = disk_status(fs->pdrv);
-		if (!(stat & STA_NOINIT)) {		/* and the physical drive is kept initialized */
-			if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) {	/* Check write protection if needed */
-				return FR_WRITE_PROTECTED;
-			}
-			return FR_OK;				/* The filesystem object is valid */
-		}
-	}
-
-	/* The filesystem object is not valid. */
-	/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
-
-	fs->fs_type = 0;					/* Clear the filesystem object */
-	fs->pdrv = LD2PD(vol);				/* Bind the logical drive and a physical drive */
-	stat = disk_initialize(fs->pdrv);	/* Initialize the physical drive */
-	if (stat & STA_NOINIT) { 			/* Check if the initialization succeeded */
-		return FR_NOT_READY;			/* Failed to initialize due to no medium or hard error */
-	}
-	if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
-		return FR_WRITE_PROTECTED;
-	}
-#if FF_MAX_SS != FF_MIN_SS				/* Get sector size (multiple sector size cfg only) */
-	if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
-	if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
-#endif
-
-	/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */
-	bsect = 0;
-	fmt = check_fs(fs, bsect);			/* Load sector 0 and check if it is an FAT-VBR as SFD */
-	if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) {	/* Not an FAT-VBR or forced partition number */
-		for (i = 0; i < 4; i++) {		/* Get partition offset */
-			pt = fs->win + (MBR_Table + i * SZ_PTE);
-			br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0;
-		}
-		i = LD2PT(vol);					/* Partition number: 0:auto, 1-4:forced */
-		if (i != 0) i--;
-		do {							/* Find an FAT volume */
-			bsect = br[i];
-			fmt = bsect ? check_fs(fs, bsect) : 3;	/* Check the partition */
-		} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
-	}
-	if (fmt == 4) return FR_DISK_ERR;		/* An error occured in the disk I/O layer */
-	if (fmt >= 2) return FR_NO_FILESYSTEM;	/* No FAT volume is found */
-
-	/* An FAT volume is found (bsect). Following code initializes the filesystem object */
-
-#if FF_FS_EXFAT
-	if (fmt == 1) {
-		QWORD maxlba;
-		DWORD so, cv, bcl;
-
-		for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ;	/* Check zero filler */
-		if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
-
-		if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM;	/* Check exFAT version (must be version 1.0) */
-
-		if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) {	/* (BPB_BytsPerSecEx must be equal to the physical sector size) */
-			return FR_NO_FILESYSTEM;
-		}
-
-		maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect;	/* Last LBA + 1 of the volume */
-		if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM;	/* (It cannot be handled in 32-bit LBA) */
-
-		fs->fsize = ld_dword(fs->win + BPB_FatSzEx);	/* Number of sectors per FAT */
-
-		fs->n_fats = fs->win[BPB_NumFATsEx];			/* Number of FATs */
-		if (fs->n_fats != 1) return FR_NO_FILESYSTEM;	/* (Supports only 1 FAT) */
-
-		fs->csize = 1 << fs->win[BPB_SecPerClusEx];		/* Cluster size */
-		if (fs->csize == 0)	return FR_NO_FILESYSTEM;	/* (Must be 1..32768) */
-
-		nclst = ld_dword(fs->win + BPB_NumClusEx);		/* Number of clusters */
-		if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM;	/* (Too many clusters) */
-		fs->n_fatent = nclst + 2;
-
-		/* Boundaries and Limits */
-		fs->volbase = bsect;
-		fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
-		fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
-		if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM;	/* (Volume size must not be smaller than the size requiered) */
-		fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
-
-		/* Get bitmap location and check if it is contiguous (implementation assumption) */
-		so = i = 0;
-		for (;;) {	/* Find the bitmap entry in the root directory (in only first cluster) */
-			if (i == 0) {
-				if (so >= fs->csize) return FR_NO_FILESYSTEM;	/* Not found? */
-				if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) return FR_DISK_ERR;
-				so++;
-			}
-			if (fs->win[i] == ET_BITMAP) break;				/* Is it a bitmap entry? */
-			i = (i + SZDIRE) % SS(fs);	/* Next entry */
-		}
-		bcl = ld_dword(fs->win + i + 20);					/* Bitmap cluster */
-		if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM;
-		fs->bitbase = fs->database + fs->csize * (bcl - 2);	/* Bitmap sector */
-		for (;;) {	/* Check if bitmap is contiguous */
-			if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
-			cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
-			if (cv == 0xFFFFFFFF) break;				/* Last link? */
-			if (cv != ++bcl) return FR_NO_FILESYSTEM;	/* Fragmented? */
-		}
-
-#if !FF_FS_READONLY
-		fs->last_clst = fs->free_clst = 0xFFFFFFFF;		/* Initialize cluster allocation information */
-#endif
-		fmt = FS_EXFAT;			/* FAT sub-type */
-	} else
-#endif	/* FF_FS_EXFAT */
-	{
-		if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_BytsPerSec must be equal to the physical sector size) */
-
-		fasize = ld_word(fs->win + BPB_FATSz16);		/* Number of sectors per FAT */
-		if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
-		fs->fsize = fasize;
-
-		fs->n_fats = fs->win[BPB_NumFATs];				/* Number of FATs */
-		if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM;	/* (Must be 1 or 2) */
-		fasize *= fs->n_fats;							/* Number of sectors for FAT area */
-
-		fs->csize = fs->win[BPB_SecPerClus];			/* Cluster size */
-		if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM;	/* (Must be power of 2) */
-
-		fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt);	/* Number of root directory entries */
-		if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM;	/* (Must be sector aligned) */
-
-		tsect = ld_word(fs->win + BPB_TotSec16);		/* Number of sectors on the volume */
-		if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
-
-		nrsv = ld_word(fs->win + BPB_RsvdSecCnt);		/* Number of reserved sectors */
-		if (nrsv == 0) return FR_NO_FILESYSTEM;			/* (Must not be 0) */
-
-		/* Determine the FAT sub type */
-		sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE);	/* RSV + FAT + DIR */
-		if (tsect < sysect) return FR_NO_FILESYSTEM;	/* (Invalid volume size) */
-		nclst = (tsect - sysect) / fs->csize;			/* Number of clusters */
-		if (nclst == 0) return FR_NO_FILESYSTEM;		/* (Invalid volume size) */
-		fmt = 0;
-		if (nclst <= MAX_FAT32) fmt = FS_FAT32;
-		if (nclst <= MAX_FAT16) fmt = FS_FAT16;
-		if (nclst <= MAX_FAT12) fmt = FS_FAT12;
-		if (fmt == 0) return FR_NO_FILESYSTEM;
-
-		/* Boundaries and Limits */
-		fs->n_fatent = nclst + 2;						/* Number of FAT entries */
-		fs->volbase = bsect;							/* Volume start sector */
-		fs->fatbase = bsect + nrsv; 					/* FAT start sector */
-		fs->database = bsect + sysect;					/* Data start sector */
-		if (fmt == FS_FAT32) {
-			if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM;	/* (Must be FAT32 revision 0.0) */
-			if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must be 0) */
-			fs->dirbase = ld_dword(fs->win + BPB_RootClus32);	/* Root directory start cluster */
-			szbfat = fs->n_fatent * 4;					/* (Needed FAT size) */
-		} else {
-			if (fs->n_rootdir == 0)	return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must not be 0) */
-			fs->dirbase = fs->fatbase + fasize;			/* Root directory start sector */
-			szbfat = (fmt == FS_FAT16) ?				/* (Needed FAT size) */
-				fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
-		}
-		if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_FATSz must not be less than the size needed) */
-
-#if !FF_FS_READONLY
-		/* Get FSInfo if available */
-		fs->last_clst = fs->free_clst = 0xFFFFFFFF;		/* Initialize cluster allocation information */
-		fs->fsi_flag = 0x80;
-#if (FF_FS_NOFSINFO & 3) != 3
-		if (fmt == FS_FAT32				/* Allow to update FSInfo only if BPB_FSInfo32 == 1 */
-			&& ld_word(fs->win + BPB_FSInfo32) == 1
-			&& move_window(fs, bsect + 1) == FR_OK)
-		{
-			fs->fsi_flag = 0;
-			if (ld_word(fs->win + BS_55AA) == 0xAA55	/* Load FSInfo data if available */
-				&& ld_dword(fs->win + FSI_LeadSig) == 0x41615252
-				&& ld_dword(fs->win + FSI_StrucSig) == 0x61417272)
-			{
-#if (FF_FS_NOFSINFO & 1) == 0
-				fs->free_clst = ld_dword(fs->win + FSI_Free_Count);
-#endif
-#if (FF_FS_NOFSINFO & 2) == 0
-				fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free);
-#endif
-			}
-		}
-#endif	/* (FF_FS_NOFSINFO & 3) != 3 */
-#endif	/* !FF_FS_READONLY */
-	}
-
-	fs->fs_type = fmt;		/* FAT sub-type */
-	fs->id = ++Fsid;		/* Volume mount ID */
-#if FF_USE_LFN == 1
-	fs->lfnbuf = LfnBuf;	/* Static LFN working buffer */
-#if FF_FS_EXFAT
-	fs->dirbuf = DirBuf;	/* Static directory block scratchpad buuffer */
-#endif
-#endif
-#if FF_FS_RPATH != 0
-	fs->cdir = 0;			/* Initialize current directory */
-#endif
-#if FF_FS_LOCK != 0			/* Clear file lock semaphores */
-	clear_lock(fs);
-#endif
-	return FR_OK;
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Check if the file/directory object is valid or not                    */
-/*-----------------------------------------------------------------------*/
-
-static FRESULT validate (	/* Returns FR_OK or FR_INVALID_OBJECT */
-	FFOBJID* obj,			/* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */
-	FATFS** rfs				/* Pointer to pointer to the owner filesystem object to return */
-)
-{
-	FRESULT res = FR_INVALID_OBJECT;
-
-
-	if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) {	/* Test if the object is valid */
-#if FF_FS_REENTRANT
-		if (lock_fs(obj->fs)) {	/* Obtain the filesystem object */
-			if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
-				res = FR_OK;
-			} else {
-				unlock_fs(obj->fs, FR_OK);
-			}
-		} else {
-			res = FR_TIMEOUT;
-		}
-#else
-		if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
-			res = FR_OK;
-		}
-#endif
-	}
-	*rfs = (res == FR_OK) ? obj->fs : 0;	/* Corresponding filesystem object */
-	return res;
-}
-
-
-
-
-/*---------------------------------------------------------------------------
-
-   Public Functions (FatFs API)
-
-----------------------------------------------------------------------------*/
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Mount/Unmount a Logical Drive                                         */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_mount (
-	FATFS* fs,			/* Pointer to the filesystem object (NULL:unmount)*/
-	const TCHAR* path,	/* Logical drive number to be mounted/unmounted */
-	BYTE opt			/* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */
-)
-{
-	FATFS *cfs;
-	int vol;
-	FRESULT res;
-	const TCHAR *rp = path;
-
-
-	/* Get logical drive number */
-	vol = get_ldnumber(&rp);
-	if (vol < 0) return FR_INVALID_DRIVE;
-	cfs = FatFs[vol];					/* Pointer to fs object */
-
-	if (cfs) {
-#if FF_FS_LOCK != 0
-		clear_lock(cfs);
-#endif
-#if FF_FS_REENTRANT						/* Discard sync object of the current volume */
-		if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
-#endif
-		cfs->fs_type = 0;				/* Clear old fs object */
-	}
-
-	if (fs) {
-		fs->fs_type = 0;				/* Clear new fs object */
-#if FF_FS_REENTRANT						/* Create sync object for the new volume */
-		if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR;
-#endif
-	}
-	FatFs[vol] = fs;					/* Register new fs object */
-
-	if (opt == 0) return FR_OK;			/* Do not mount now, it will be mounted later */
-
-	res = find_volume(&path, &fs, 0);	/* Force mounted the volume */
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Open or Create a File                                                 */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_open (
-	FIL* fp,			/* Pointer to the blank file object */
-	const TCHAR* path,	/* Pointer to the file name */
-	BYTE mode			/* Access mode and file open mode flags */
-)
-{
-	FRESULT res;
-	DIR dj;
-	FATFS *fs;
-#if !FF_FS_READONLY
-	DWORD dw, cl, bcs, clst, sc;
-	FSIZE_t ofs;
-#endif
-	DEF_NAMBUF
-
-
-	if (!fp) return FR_INVALID_OBJECT;
-
-	/* Get logical drive number */
-	mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND;
-	res = find_volume(&path, &fs, mode);
-	if (res == FR_OK) {
-		dj.obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(&dj, path);	/* Follow the file path */
-#if !FF_FS_READONLY	/* Read/Write configuration */
-		if (res == FR_OK) {
-			if (dj.fn[NSFLAG] & NS_NONAME) {	/* Origin directory itself? */
-				res = FR_INVALID_NAME;
-			}
-#if FF_FS_LOCK != 0
-			else {
-				res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);		/* Check if the file can be used */
-			}
-#endif
-		}
-		/* Create or Open a file */
-		if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
-			if (res != FR_OK) {					/* No file, create new */
-				if (res == FR_NO_FILE) {		/* There is no file to open, create a new entry */
-#if FF_FS_LOCK != 0
-					res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
-#else
-					res = dir_register(&dj);
-#endif
-				}
-				mode |= FA_CREATE_ALWAYS;		/* File is created */
-			}
-			else {								/* Any object with the same name is already existing */
-				if (dj.obj.attr & (AM_RDO | AM_DIR)) {	/* Cannot overwrite it (R/O or DIR) */
-					res = FR_DENIED;
-				} else {
-					if (mode & FA_CREATE_NEW) res = FR_EXIST;	/* Cannot create as new file */
-				}
-			}
-			if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {	/* Truncate the file if overwrite mode */
-#if FF_FS_EXFAT
-				if (fs->fs_type == FS_EXFAT) {
-					/* Get current allocation info */
-					fp->obj.fs = fs;
-					init_alloc_info(fs, &fp->obj);
-					/* Set directory entry block initial state */
-					mem_set(fs->dirbuf + 2, 0, 30);		/* Clear 85 entry except for NumSec */
-					mem_set(fs->dirbuf + 38, 0, 26);	/* Clear C0 entry except for NumName and NameHash */
-					fs->dirbuf[XDIR_Attr] = AM_ARC;
-					st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME());
-					fs->dirbuf[XDIR_GenFlags] = 1;
-					res = store_xdir(&dj);
-					if (res == FR_OK && fp->obj.sclust != 0) {	/* Remove the cluster chain if exist */
-						res = remove_chain(&fp->obj, fp->obj.sclust, 0);
-						fs->last_clst = fp->obj.sclust - 1;		/* Reuse the cluster hole */
-					}
-				} else
-#endif
-				{
-					/* Set directory entry initial state */
-					cl = ld_clust(fs, dj.dir);			/* Get current cluster chain */
-					st_dword(dj.dir + DIR_CrtTime, GET_FATTIME());	/* Set created time */
-					dj.dir[DIR_Attr] = AM_ARC;			/* Reset attribute */
-					st_clust(fs, dj.dir, 0);			/* Reset file allocation info */
-					st_dword(dj.dir + DIR_FileSize, 0);
-					fs->wflag = 1;
-					if (cl != 0) {						/* Remove the cluster chain if exist */
-						dw = fs->winsect;
-						res = remove_chain(&dj.obj, cl, 0);
-						if (res == FR_OK) {
-							res = move_window(fs, dw);
-							fs->last_clst = cl - 1;		/* Reuse the cluster hole */
-						}
-					}
-				}
-			}
-		}
-		else {	/* Open an existing file */
-			if (res == FR_OK) {					/* Is the object exsiting? */
-				if (dj.obj.attr & AM_DIR) {		/* File open against a directory */
-					res = FR_NO_FILE;
-				} else {
-					if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */
-						res = FR_DENIED;
-					}
-				}
-			}
-		}
-		if (res == FR_OK) {
-			if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED;	/* Set file change flag if created or overwritten */
-			fp->dir_sect = fs->winsect;			/* Pointer to the directory entry */
-			fp->dir_ptr = dj.dir;
-#if FF_FS_LOCK != 0
-			fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);	/* Lock the file for this session */
-			if (fp->obj.lockid == 0) res = FR_INT_ERR;
-#endif
-		}
-#else		/* R/O configuration */
-		if (res == FR_OK) {
-			if (dj.fn[NSFLAG] & NS_NONAME) {	/* Is it origin directory itself? */
-				res = FR_INVALID_NAME;
-			} else {
-				if (dj.obj.attr & AM_DIR) {		/* Is it a directory? */
-					res = FR_NO_FILE;
-				}
-			}
-		}
-#endif
-
-		if (res == FR_OK) {
-#if FF_FS_EXFAT
-			if (fs->fs_type == FS_EXFAT) {
-				fp->obj.c_scl = dj.obj.sclust;							/* Get containing directory info */
-				fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
-				fp->obj.c_ofs = dj.blk_ofs;
-				init_alloc_info(fs, &fp->obj);
-			} else
-#endif
-			{
-				fp->obj.sclust = ld_clust(fs, dj.dir);					/* Get object allocation info */
-				fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize);
-			}
-#if FF_USE_FASTSEEK
-			fp->cltbl = 0;			/* Disable fast seek mode */
-#endif
-			fp->obj.fs = fs;	 	/* Validate the file object */
-			fp->obj.id = fs->id;
-			fp->flag = mode;		/* Set file access mode */
-			fp->err = 0;			/* Clear error flag */
-			fp->sect = 0;			/* Invalidate current data sector */
-			fp->fptr = 0;			/* Set file pointer top of the file */
-#if !FF_FS_READONLY
-#if !FF_FS_TINY
-			mem_set(fp->buf, 0, sizeof fp->buf);	/* Clear sector buffer */
-#endif
-			if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) {	/* Seek to end of file if FA_OPEN_APPEND is specified */
-				fp->fptr = fp->obj.objsize;			/* Offset to seek */
-				bcs = (DWORD)fs->csize * SS(fs);	/* Cluster size in byte */
-				clst = fp->obj.sclust;				/* Follow the cluster chain */
-				for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) {
-					clst = get_fat(&fp->obj, clst);
-					if (clst <= 1) res = FR_INT_ERR;
-					if (clst == 0xFFFFFFFF) res = FR_DISK_ERR;
-				}
-				fp->clust = clst;
-				if (res == FR_OK && ofs % SS(fs)) {	/* Fill sector buffer if not on the sector boundary */
-					if ((sc = clst2sect(fs, clst)) == 0) {
-						res = FR_INT_ERR;
-					} else {
-						fp->sect = sc + (DWORD)(ofs / SS(fs));
-#if !FF_FS_TINY
-						if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR;
-#endif
-					}
-				}
-			}
-#endif
-		}
-
-		FREE_NAMBUF();
-	}
-
-	if (res != FR_OK) fp->obj.fs = 0;	/* Invalidate file object on error */
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Read File                                                             */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_read (
-	FIL* fp, 	/* Pointer to the file object */
-	void* buff,	/* Pointer to data buffer */
-	UINT btr,	/* Number of bytes to read */
-	UINT* br	/* Pointer to number of bytes read */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD clst, sect;
-	FSIZE_t remain;
-	UINT rcnt, cc, csect;
-	BYTE *rbuff = (BYTE*)buff;
-
-
-	*br = 0;	/* Clear read byte counter */
-	res = validate(&fp->obj, &fs);				/* Check validity of the file object */
-	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);	/* Check validity */
-	if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
-	remain = fp->obj.objsize - fp->fptr;
-	if (btr > remain) btr = (UINT)remain;		/* Truncate btr by remaining bytes */
-
-	for ( ;  btr;								/* Repeat until btr bytes read */
-		btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) {
-		if (fp->fptr % SS(fs) == 0) {			/* On the sector boundary? */
-			csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));	/* Sector offset in the cluster */
-			if (csect == 0) {					/* On the cluster boundary? */
-				if (fp->fptr == 0) {			/* On the top of the file? */
-					clst = fp->obj.sclust;		/* Follow cluster chain from the origin */
-				} else {						/* Middle or end of the file */
-#if FF_USE_FASTSEEK
-					if (fp->cltbl) {
-						clst = clmt_clust(fp, fp->fptr);	/* Get cluster# from the CLMT */
-					} else
-#endif
-					{
-						clst = get_fat(&fp->obj, fp->clust);	/* Follow cluster chain on the FAT */
-					}
-				}
-				if (clst < 2) ABORT(fs, FR_INT_ERR);
-				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
-				fp->clust = clst;				/* Update current cluster */
-			}
-			sect = clst2sect(fs, fp->clust);	/* Get current sector */
-			if (sect == 0) ABORT(fs, FR_INT_ERR);
-			sect += csect;
-			cc = btr / SS(fs);					/* When remaining bytes >= sector size, */
-			if (cc > 0) {						/* Read maximum contiguous sectors directly */
-				if (csect + cc > fs->csize) {	/* Clip at cluster boundary */
-					cc = fs->csize - csect;
-				}
-				if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
-#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2		/* Replace one of the read sectors with cached data if it contains a dirty sector */
-#if FF_FS_TINY
-				if (fs->wflag && fs->winsect - sect < cc) {
-					mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
-				}
-#else
-				if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) {
-					mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
-				}
-#endif
-#endif
-				rcnt = SS(fs) * cc;				/* Number of bytes transferred */
-				continue;
-			}
-#if !FF_FS_TINY
-			if (fp->sect != sect) {			/* Load data sector if not in cache */
-#if !FF_FS_READONLY
-				if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
-					if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
-					fp->flag &= (BYTE)~FA_DIRTY;
-				}
-#endif
-				if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK)	ABORT(fs, FR_DISK_ERR);	/* Fill sector cache */
-			}
-#endif
-			fp->sect = sect;
-		}
-		rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes left in the sector */
-		if (rcnt > btr) rcnt = btr;					/* Clip it by btr if needed */
-#if FF_FS_TINY
-		if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window */
-		mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt);	/* Extract partial sector */
-#else
-		mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt);	/* Extract partial sector */
-#endif
-	}
-
-	LEAVE_FF(fs, FR_OK);
-}
-
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Write File                                                            */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_write (
-	FIL* fp,			/* Pointer to the file object */
-	const void* buff,	/* Pointer to the data to be written */
-	UINT btw,			/* Number of bytes to write */
-	UINT* bw			/* Pointer to number of bytes written */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD clst, sect;
-	UINT wcnt, cc, csect;
-	const BYTE *wbuff = (const BYTE*)buff;
-
-
-	*bw = 0;	/* Clear write byte counter */
-	res = validate(&fp->obj, &fs);			/* Check validity of the file object */
-	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);	/* Check validity */
-	if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */
-
-	/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
-	if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
-		btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
-	}
-
-	for ( ;  btw;							/* Repeat until all data written */
-		btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) {
-		if (fp->fptr % SS(fs) == 0) {		/* On the sector boundary? */
-			csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1);	/* Sector offset in the cluster */
-			if (csect == 0) {				/* On the cluster boundary? */
-				if (fp->fptr == 0) {		/* On the top of the file? */
-					clst = fp->obj.sclust;	/* Follow from the origin */
-					if (clst == 0) {		/* If no cluster is allocated, */
-						clst = create_chain(&fp->obj, 0);	/* create a new cluster chain */
-					}
-				} else {					/* On the middle or end of the file */
-#if FF_USE_FASTSEEK
-					if (fp->cltbl) {
-						clst = clmt_clust(fp, fp->fptr);	/* Get cluster# from the CLMT */
-					} else
-#endif
-					{
-						clst = create_chain(&fp->obj, fp->clust);	/* Follow or stretch cluster chain on the FAT */
-					}
-				}
-				if (clst == 0) break;		/* Could not allocate a new cluster (disk full) */
-				if (clst == 1) ABORT(fs, FR_INT_ERR);
-				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
-				fp->clust = clst;			/* Update current cluster */
-				if (fp->obj.sclust == 0) fp->obj.sclust = clst;	/* Set start cluster if the first write */
-			}
-#if FF_FS_TINY
-			if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Write-back sector cache */
-#else
-			if (fp->flag & FA_DIRTY) {		/* Write-back sector cache */
-				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
-				fp->flag &= (BYTE)~FA_DIRTY;
-			}
-#endif
-			sect = clst2sect(fs, fp->clust);	/* Get current sector */
-			if (sect == 0) ABORT(fs, FR_INT_ERR);
-			sect += csect;
-			cc = btw / SS(fs);				/* When remaining bytes >= sector size, */
-			if (cc > 0) {					/* Write maximum contiguous sectors directly */
-				if (csect + cc > fs->csize) {	/* Clip at cluster boundary */
-					cc = fs->csize - csect;
-				}
-				if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
-#if FF_FS_MINIMIZE <= 2
-#if FF_FS_TINY
-				if (fs->winsect - sect < cc) {	/* Refill sector cache if it gets invalidated by the direct write */
-					mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
-					fs->wflag = 0;
-				}
-#else
-				if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
-					mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
-					fp->flag &= (BYTE)~FA_DIRTY;
-				}
-#endif
-#endif
-				wcnt = SS(fs) * cc;		/* Number of bytes transferred */
-				continue;
-			}
-#if FF_FS_TINY
-			if (fp->fptr >= fp->obj.objsize) {	/* Avoid silly cache filling on the growing edge */
-				if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);
-				fs->winsect = sect;
-			}
-#else
-			if (fp->sect != sect && 		/* Fill sector cache with file data */
-				fp->fptr < fp->obj.objsize &&
-				disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
-					ABORT(fs, FR_DISK_ERR);
-			}
-#endif
-			fp->sect = sect;
-		}
-		wcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes left in the sector */
-		if (wcnt > btw) wcnt = btw;					/* Clip it by btw if needed */
-#if FF_FS_TINY
-		if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window */
-		mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt);	/* Fit data to the sector */
-		fs->wflag = 1;
-#else
-		mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt);	/* Fit data to the sector */
-		fp->flag |= FA_DIRTY;
-#endif
-	}
-
-	fp->flag |= FA_MODIFIED;				/* Set file change flag */
-
-	LEAVE_FF(fs, FR_OK);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Synchronize the File                                                  */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_sync (
-	FIL* fp		/* Pointer to the file object */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD tm;
-	BYTE *dir;
-
-
-	res = validate(&fp->obj, &fs);	/* Check validity of the file object */
-	if (res == FR_OK) {
-		if (fp->flag & FA_MODIFIED) {	/* Is there any change to the file? */
-#if !FF_FS_TINY
-			if (fp->flag & FA_DIRTY) {	/* Write-back cached data if needed */
-				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
-				fp->flag &= (BYTE)~FA_DIRTY;
-			}
-#endif
-			/* Update the directory entry */
-			tm = GET_FATTIME();				/* Modified time */
-#if FF_FS_EXFAT
-			if (fs->fs_type == FS_EXFAT) {
-				res = fill_first_frag(&fp->obj);	/* Fill first fragment on the FAT if needed */
-				if (res == FR_OK) {
-					res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
-				}
-				if (res == FR_OK) {
-					DIR dj;
-					DEF_NAMBUF
-
-					INIT_NAMBUF(fs);
-					res = load_obj_xdir(&dj, &fp->obj);	/* Load directory entry block */
-					if (res == FR_OK) {
-						fs->dirbuf[XDIR_Attr] |= AM_ARC;				/* Set archive attribute to indicate that the file has been changed */
-						fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1;	/* Update file allocation information */
-						st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust);
-						st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize);
-						st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize);
-						st_dword(fs->dirbuf + XDIR_ModTime, tm);		/* Update modified time */
-						fs->dirbuf[XDIR_ModTime10] = 0;
-						st_dword(fs->dirbuf + XDIR_AccTime, 0);
-						res = store_xdir(&dj);	/* Restore it to the directory */
-						if (res == FR_OK) {
-							res = sync_fs(fs);
-							fp->flag &= (BYTE)~FA_MODIFIED;
-						}
-					}
-					FREE_NAMBUF();
-				}
-			} else
-#endif
-			{
-				res = move_window(fs, fp->dir_sect);
-				if (res == FR_OK) {
-					dir = fp->dir_ptr;
-					dir[DIR_Attr] |= AM_ARC;						/* Set archive attribute to indicate that the file has been changed */
-					st_clust(fp->obj.fs, dir, fp->obj.sclust);		/* Update file allocation information  */
-					st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize);	/* Update file size */
-					st_dword(dir + DIR_ModTime, tm);				/* Update modified time */
-					st_word(dir + DIR_LstAccDate, 0);
-					fs->wflag = 1;
-					res = sync_fs(fs);					/* Restore it to the directory */
-					fp->flag &= (BYTE)~FA_MODIFIED;
-				}
-			}
-		}
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-#endif /* !FF_FS_READONLY */
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Close File                                                            */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_close (
-	FIL* fp		/* Pointer to the file object to be closed */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-
-#if !FF_FS_READONLY
-	res = f_sync(fp);					/* Flush cached data */
-	if (res == FR_OK)
-#endif
-	{
-		res = validate(&fp->obj, &fs);	/* Lock volume */
-		if (res == FR_OK) {
-#if FF_FS_LOCK != 0
-			res = dec_lock(fp->obj.lockid);		/* Decrement file open counter */
-			if (res == FR_OK) fp->obj.fs = 0;	/* Invalidate file object */
-#else
-			fp->obj.fs = 0;	/* Invalidate file object */
-#endif
-#if FF_FS_REENTRANT
-			unlock_fs(fs, FR_OK);		/* Unlock volume */
-#endif
-		}
-	}
-	return res;
-}
-
-
-
-
-#if FF_FS_RPATH >= 1
-/*-----------------------------------------------------------------------*/
-/* Change Current Directory or Current Drive, Get Current Directory      */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_chdrive (
-	const TCHAR* path		/* Drive number to set */
-)
-{
-	int vol;
-
-
-	/* Get logical drive number */
-	vol = get_ldnumber(&path);
-	if (vol < 0) return FR_INVALID_DRIVE;
-	CurrVol = (BYTE)vol;	/* Set it as current volume */
-
-	return FR_OK;
-}
-
-
-
-FRESULT f_chdir (
-	const TCHAR* path	/* Pointer to the directory path */
-)
-{
-#if FF_STR_VOLUME_ID == 2
-	UINT i;
-#endif
-	FRESULT res;
-	DIR dj;
-	FATFS *fs;
-	DEF_NAMBUF
-
-
-	/* Get logical drive */
-	res = find_volume(&path, &fs, 0);
-	if (res == FR_OK) {
-		dj.obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(&dj, path);		/* Follow the path */
-		if (res == FR_OK) {					/* Follow completed */
-			if (dj.fn[NSFLAG] & NS_NONAME) {	/* Is it the start directory itself? */
-				fs->cdir = dj.obj.sclust;
-#if FF_FS_EXFAT
-				if (fs->fs_type == FS_EXFAT) {
-					fs->cdc_scl = dj.obj.c_scl;
-					fs->cdc_size = dj.obj.c_size;
-					fs->cdc_ofs = dj.obj.c_ofs;
-				}
-#endif
-			} else {
-				if (dj.obj.attr & AM_DIR) {	/* It is a sub-directory */
-#if FF_FS_EXFAT
-					if (fs->fs_type == FS_EXFAT) {
-						fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus);		/* Sub-directory cluster */
-						fs->cdc_scl = dj.obj.sclust;						/* Save containing directory information */
-						fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
-						fs->cdc_ofs = dj.blk_ofs;
-					} else
-#endif
-					{
-						fs->cdir = ld_clust(fs, dj.dir);					/* Sub-directory cluster */
-					}
-				} else {
-					res = FR_NO_PATH;		/* Reached but a file */
-				}
-			}
-		}
-		FREE_NAMBUF();
-		if (res == FR_NO_FILE) res = FR_NO_PATH;
-#if FF_STR_VOLUME_ID == 2	/* Also current drive is changed at Unix style volume ID */
-		if (res == FR_OK) {
-			for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ;	/* Set current drive */
-			CurrVol = (BYTE)i;
-		}
-#endif
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-#if FF_FS_RPATH >= 2
-FRESULT f_getcwd (
-	TCHAR* buff,	/* Pointer to the directory path */
-	UINT len		/* Size of buff in unit of TCHAR */
-)
-{
-	FRESULT res;
-	DIR dj;
-	FATFS *fs;
-	UINT i, n;
-	DWORD ccl;
-	TCHAR *tp = buff;
-#if FF_VOLUMES >= 2
-	UINT vl;
-#endif
-#if FF_STR_VOLUME_ID
-	const char *vp;
-#endif
-	FILINFO fno;
-	DEF_NAMBUF
-
-
-	/* Get logical drive */
-	buff[0] = 0;	/* Set null string to get current volume */
-	res = find_volume((const TCHAR**)&buff, &fs, 0);	/* Get current volume */
-	if (res == FR_OK) {
-		dj.obj.fs = fs;
-		INIT_NAMBUF(fs);
-
-		/* Follow parent directories and create the path */
-		i = len;			/* Bottom of buffer (directory stack base) */
-		if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {	/* (Cannot do getcwd on exFAT and returns root path) */
-			dj.obj.sclust = fs->cdir;				/* Start to follow upper directory from current directory */
-			while ((ccl = dj.obj.sclust) != 0) {	/* Repeat while current directory is a sub-directory */
-				res = dir_sdi(&dj, 1 * SZDIRE);	/* Get parent directory */
-				if (res != FR_OK) break;
-				res = move_window(fs, dj.sect);
-				if (res != FR_OK) break;
-				dj.obj.sclust = ld_clust(fs, dj.dir);	/* Goto parent directory */
-				res = dir_sdi(&dj, 0);
-				if (res != FR_OK) break;
-				do {							/* Find the entry links to the child directory */
-					res = DIR_READ_FILE(&dj);
-					if (res != FR_OK) break;
-					if (ccl == ld_clust(fs, dj.dir)) break;	/* Found the entry */
-					res = dir_next(&dj, 0);
-				} while (res == FR_OK);
-				if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
-				if (res != FR_OK) break;
-				get_fileinfo(&dj, &fno);		/* Get the directory name and push it to the buffer */
-				for (n = 0; fno.fname[n]; n++) ;	/* Name length */
-				if (i < n + 1) {	/* Insufficient space to store the path name? */
-					res = FR_NOT_ENOUGH_CORE; break;
-				}
-				while (n) buff[--i] = fno.fname[--n];	/* Stack the name */
-				buff[--i] = '/';
-			}
-		}
-		if (res == FR_OK) {
-			if (i == len) buff[--i] = '/';	/* Is it the root-directory? */
-#if FF_VOLUMES >= 2			/* Put drive prefix */
-			vl = 0;
-#if FF_STR_VOLUME_ID >= 1	/* String volume ID */
-			for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ;
-			if (i >= n + 2) {
-				if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/';
-				for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ;
-				if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':';
-				vl++;
-			}
-#else						/* Numeric volume ID */
-			if (i >= 3) {
-				*tp++ = (TCHAR)'0' + CurrVol;
-				*tp++ = (TCHAR)':';
-				vl = 2;
-			}
-#endif
-			if (vl == 0) res = FR_NOT_ENOUGH_CORE;
-#endif
-			/* Add current directory path */
-			if (res == FR_OK) {
-				do *tp++ = buff[i++]; while (i < len);	/* Copy stacked path string */
-			}
-		}
-		FREE_NAMBUF();
-	}
-
-	*tp = 0;
-	LEAVE_FF(fs, res);
-}
-
-#endif /* FF_FS_RPATH >= 2 */
-#endif /* FF_FS_RPATH >= 1 */
-
-
-
-#if FF_FS_MINIMIZE <= 2
-/*-----------------------------------------------------------------------*/
-/* Seek File Read/Write Pointer                                          */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_lseek (
-	FIL* fp,		/* Pointer to the file object */
-	FSIZE_t ofs		/* File pointer from top of file */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD clst, bcs, nsect;
-	FSIZE_t ifptr;
-#if FF_USE_FASTSEEK
-	DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
-#endif
-
-	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
-	if (res == FR_OK) res = (FRESULT)fp->err;
-#if FF_FS_EXFAT && !FF_FS_READONLY
-	if (res == FR_OK && fs->fs_type == FS_EXFAT) {
-		res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
-	}
-#endif
-	if (res != FR_OK) LEAVE_FF(fs, res);
-
-#if FF_USE_FASTSEEK
-	if (fp->cltbl) {	/* Fast seek */
-		if (ofs == CREATE_LINKMAP) {	/* Create CLMT */
-			tbl = fp->cltbl;
-			tlen = *tbl++; ulen = 2;	/* Given table size and required table size */
-			cl = fp->obj.sclust;		/* Origin of the chain */
-			if (cl != 0) {
-				do {
-					/* Get a fragment */
-					tcl = cl; ncl = 0; ulen += 2;	/* Top, length and used items */
-					do {
-						pcl = cl; ncl++;
-						cl = get_fat(&fp->obj, cl);
-						if (cl <= 1) ABORT(fs, FR_INT_ERR);
-						if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
-					} while (cl == pcl + 1);
-					if (ulen <= tlen) {		/* Store the length and top of the fragment */
-						*tbl++ = ncl; *tbl++ = tcl;
-					}
-				} while (cl < fs->n_fatent);	/* Repeat until end of chain */
-			}
-			*fp->cltbl = ulen;	/* Number of items used */
-			if (ulen <= tlen) {
-				*tbl = 0;		/* Terminate table */
-			} else {
-				res = FR_NOT_ENOUGH_CORE;	/* Given table size is smaller than required */
-			}
-		} else {						/* Fast seek */
-			if (ofs > fp->obj.objsize) ofs = fp->obj.objsize;	/* Clip offset at the file size */
-			fp->fptr = ofs;				/* Set file pointer */
-			if (ofs > 0) {
-				fp->clust = clmt_clust(fp, ofs - 1);
-				dsc = clst2sect(fs, fp->clust);
-				if (dsc == 0) ABORT(fs, FR_INT_ERR);
-				dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1);
-				if (fp->fptr % SS(fs) && dsc != fp->sect) {	/* Refill sector cache if needed */
-#if !FF_FS_TINY
-#if !FF_FS_READONLY
-					if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
-						if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
-						fp->flag &= (BYTE)~FA_DIRTY;
-					}
-#endif
-					if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);	/* Load current sector */
-#endif
-					fp->sect = dsc;
-				}
-			}
-		}
-	} else
-#endif
-
-	/* Normal Seek */
-	{
-#if FF_FS_EXFAT
-		if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF;	/* Clip at 4 GiB - 1 if at FATxx */
-#endif
-		if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) {	/* In read-only mode, clip offset with the file size */
-			ofs = fp->obj.objsize;
-		}
-		ifptr = fp->fptr;
-		fp->fptr = nsect = 0;
-		if (ofs > 0) {
-			bcs = (DWORD)fs->csize * SS(fs);	/* Cluster size (byte) */
-			if (ifptr > 0 &&
-				(ofs - 1) / bcs >= (ifptr - 1) / bcs) {	/* When seek to same or following cluster, */
-				fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1);	/* start from the current cluster */
-				ofs -= fp->fptr;
-				clst = fp->clust;
-			} else {									/* When seek to back cluster, */
-				clst = fp->obj.sclust;					/* start from the first cluster */
-#if !FF_FS_READONLY
-				if (clst == 0) {						/* If no cluster chain, create a new chain */
-					clst = create_chain(&fp->obj, 0);
-					if (clst == 1) ABORT(fs, FR_INT_ERR);
-					if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
-					fp->obj.sclust = clst;
-				}
-#endif
-				fp->clust = clst;
-			}
-			if (clst != 0) {
-				while (ofs > bcs) {						/* Cluster following loop */
-					ofs -= bcs; fp->fptr += bcs;
-#if !FF_FS_READONLY
-					if (fp->flag & FA_WRITE) {			/* Check if in write mode or not */
-						if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) {	/* No FAT chain object needs correct objsize to generate FAT value */
-							fp->obj.objsize = fp->fptr;
-							fp->flag |= FA_MODIFIED;
-						}
-						clst = create_chain(&fp->obj, clst);	/* Follow chain with forceed stretch */
-						if (clst == 0) {				/* Clip file size in case of disk full */
-							ofs = 0; break;
-						}
-					} else
-#endif
-					{
-						clst = get_fat(&fp->obj, clst);	/* Follow cluster chain if not in write mode */
-					}
-					if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
-					if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR);
-					fp->clust = clst;
-				}
-				fp->fptr += ofs;
-				if (ofs % SS(fs)) {
-					nsect = clst2sect(fs, clst);	/* Current sector */
-					if (nsect == 0) ABORT(fs, FR_INT_ERR);
-					nsect += (DWORD)(ofs / SS(fs));
-				}
-			}
-		}
-		if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) {	/* Set file change flag if the file size is extended */
-			fp->obj.objsize = fp->fptr;
-			fp->flag |= FA_MODIFIED;
-		}
-		if (fp->fptr % SS(fs) && nsect != fp->sect) {	/* Fill sector cache if needed */
-#if !FF_FS_TINY
-#if !FF_FS_READONLY
-			if (fp->flag & FA_DIRTY) {			/* Write-back dirty sector cache */
-				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
-				fp->flag &= (BYTE)~FA_DIRTY;
-			}
-#endif
-			if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);	/* Fill sector cache */
-#endif
-			fp->sect = nsect;
-		}
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-#if FF_FS_MINIMIZE <= 1
-/*-----------------------------------------------------------------------*/
-/* Create a Directory Object                                             */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_opendir (
-	DIR* dp,			/* Pointer to directory object to create */
-	const TCHAR* path	/* Pointer to the directory path */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DEF_NAMBUF
-
-
-	if (!dp) return FR_INVALID_OBJECT;
-
-	/* Get logical drive */
-	res = find_volume(&path, &fs, 0);
-	if (res == FR_OK) {
-		dp->obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(dp, path);			/* Follow the path to the directory */
-		if (res == FR_OK) {						/* Follow completed */
-			if (!(dp->fn[NSFLAG] & NS_NONAME)) {	/* It is not the origin directory itself */
-				if (dp->obj.attr & AM_DIR) {		/* This object is a sub-directory */
-#if FF_FS_EXFAT
-					if (fs->fs_type == FS_EXFAT) {
-						dp->obj.c_scl = dp->obj.sclust;							/* Get containing directory inforamation */
-						dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
-						dp->obj.c_ofs = dp->blk_ofs;
-						init_alloc_info(fs, &dp->obj);	/* Get object allocation info */
-					} else
-#endif
-					{
-						dp->obj.sclust = ld_clust(fs, dp->dir);	/* Get object allocation info */
-					}
-				} else {						/* This object is a file */
-					res = FR_NO_PATH;
-				}
-			}
-			if (res == FR_OK) {
-				dp->obj.id = fs->id;
-				res = dir_sdi(dp, 0);			/* Rewind directory */
-#if FF_FS_LOCK != 0
-				if (res == FR_OK) {
-					if (dp->obj.sclust != 0) {
-						dp->obj.lockid = inc_lock(dp, 0);	/* Lock the sub directory */
-						if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES;
-					} else {
-						dp->obj.lockid = 0;	/* Root directory need not to be locked */
-					}
-				}
-#endif
-			}
-		}
-		FREE_NAMBUF();
-		if (res == FR_NO_FILE) res = FR_NO_PATH;
-	}
-	if (res != FR_OK) dp->obj.fs = 0;		/* Invalidate the directory object if function faild */
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Close Directory                                                       */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_closedir (
-	DIR *dp		/* Pointer to the directory object to be closed */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-
-
-	res = validate(&dp->obj, &fs);	/* Check validity of the file object */
-	if (res == FR_OK) {
-#if FF_FS_LOCK != 0
-		if (dp->obj.lockid) res = dec_lock(dp->obj.lockid);	/* Decrement sub-directory open counter */
-		if (res == FR_OK) dp->obj.fs = 0;	/* Invalidate directory object */
-#else
-		dp->obj.fs = 0;	/* Invalidate directory object */
-#endif
-#if FF_FS_REENTRANT
-		unlock_fs(fs, FR_OK);		/* Unlock volume */
-#endif
-	}
-	return res;
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Read Directory Entries in Sequence                                    */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_readdir (
-	DIR* dp,			/* Pointer to the open directory object */
-	FILINFO* fno		/* Pointer to file information to return */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DEF_NAMBUF
-
-
-	res = validate(&dp->obj, &fs);	/* Check validity of the directory object */
-	if (res == FR_OK) {
-		if (!fno) {
-			res = dir_sdi(dp, 0);			/* Rewind the directory object */
-		} else {
-			INIT_NAMBUF(fs);
-			res = DIR_READ_FILE(dp);		/* Read an item */
-			if (res == FR_NO_FILE) res = FR_OK;	/* Ignore end of directory */
-			if (res == FR_OK) {				/* A valid entry is found */
-				get_fileinfo(dp, fno);		/* Get the object information */
-				res = dir_next(dp, 0);		/* Increment index for next */
-				if (res == FR_NO_FILE) res = FR_OK;	/* Ignore end of directory now */
-			}
-			FREE_NAMBUF();
-		}
-	}
-	LEAVE_FF(fs, res);
-}
-
-
-
-#if FF_USE_FIND
-/*-----------------------------------------------------------------------*/
-/* Find Next File                                                        */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_findnext (
-	DIR* dp,		/* Pointer to the open directory object */
-	FILINFO* fno	/* Pointer to the file information structure */
-)
-{
-	FRESULT res;
-
-
-	for (;;) {
-		res = f_readdir(dp, fno);		/* Get a directory item */
-		if (res != FR_OK || !fno || !fno->fname[0]) break;	/* Terminate if any error or end of directory */
-		if (pattern_matching(dp->pat, fno->fname, 0, 0)) break;		/* Test for the file name */
-#if FF_USE_LFN && FF_USE_FIND == 2
-		if (pattern_matching(dp->pat, fno->altname, 0, 0)) break;	/* Test for alternative name if exist */
-#endif
-	}
-	return res;
-}
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Find First File                                                       */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_findfirst (
-	DIR* dp,				/* Pointer to the blank directory object */
-	FILINFO* fno,			/* Pointer to the file information structure */
-	const TCHAR* path,		/* Pointer to the directory to open */
-	const TCHAR* pattern	/* Pointer to the matching pattern */
-)
-{
-	FRESULT res;
-
-
-	dp->pat = pattern;		/* Save pointer to pattern string */
-	res = f_opendir(dp, path);		/* Open the target directory */
-	if (res == FR_OK) {
-		res = f_findnext(dp, fno);	/* Find the first item */
-	}
-	return res;
-}
-
-#endif	/* FF_USE_FIND */
-
-
-
-#if FF_FS_MINIMIZE == 0
-/*-----------------------------------------------------------------------*/
-/* Get File Status                                                       */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_stat (
-	const TCHAR* path,	/* Pointer to the file path */
-	FILINFO* fno		/* Pointer to file information to return */
-)
-{
-	FRESULT res;
-	DIR dj;
-	DEF_NAMBUF
-
-
-	/* Get logical drive */
-	res = find_volume(&path, &dj.obj.fs, 0);
-	if (res == FR_OK) {
-		INIT_NAMBUF(dj.obj.fs);
-		res = follow_path(&dj, path);	/* Follow the file path */
-		if (res == FR_OK) {				/* Follow completed */
-			if (dj.fn[NSFLAG] & NS_NONAME) {	/* It is origin directory */
-				res = FR_INVALID_NAME;
-			} else {							/* Found an object */
-				if (fno) get_fileinfo(&dj, fno);
-			}
-		}
-		FREE_NAMBUF();
-	}
-
-	LEAVE_FF(dj.obj.fs, res);
-}
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Get Number of Free Clusters                                           */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_getfree (
-	const TCHAR* path,	/* Logical drive number */
-	DWORD* nclst,		/* Pointer to a variable to return number of free clusters */
-	FATFS** fatfs		/* Pointer to return pointer to corresponding filesystem object */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD nfree, clst, sect, stat;
-	UINT i;
-	FFOBJID obj;
-
-
-	/* Get logical drive */
-	res = find_volume(&path, &fs, 0);
-	if (res == FR_OK) {
-		*fatfs = fs;				/* Return ptr to the fs object */
-		/* If free_clst is valid, return it without full FAT scan */
-		if (fs->free_clst <= fs->n_fatent - 2) {
-			*nclst = fs->free_clst;
-		} else {
-			/* Scan FAT to obtain number of free clusters */
-			nfree = 0;
-			if (fs->fs_type == FS_FAT12) {	/* FAT12: Scan bit field FAT entries */
-				clst = 2; obj.fs = fs;
-				do {
-					stat = get_fat(&obj, clst);
-					if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
-					if (stat == 1) { res = FR_INT_ERR; break; }
-					if (stat == 0) nfree++;
-				} while (++clst < fs->n_fatent);
-			} else {
-#if FF_FS_EXFAT
-				if (fs->fs_type == FS_EXFAT) {	/* exFAT: Scan allocation bitmap */
-					BYTE bm;
-					UINT b;
-
-					clst = fs->n_fatent - 2;	/* Number of clusters */
-					sect = fs->bitbase;			/* Bitmap sector */
-					i = 0;						/* Offset in the sector */
-					do {	/* Counts numbuer of bits with zero in the bitmap */
-						if (i == 0) {
-							res = move_window(fs, sect++);
-							if (res != FR_OK) break;
-						}
-						for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) {
-							if (!(bm & 1)) nfree++;
-							bm >>= 1;
-						}
-						i = (i + 1) % SS(fs);
-					} while (clst);
-				} else
-#endif
-				{	/* FAT16/32: Scan WORD/DWORD FAT entries */
-					clst = fs->n_fatent;	/* Number of entries */
-					sect = fs->fatbase;		/* Top of the FAT */
-					i = 0;					/* Offset in the sector */
-					do {	/* Counts numbuer of entries with zero in the FAT */
-						if (i == 0) {
-							res = move_window(fs, sect++);
-							if (res != FR_OK) break;
-						}
-						if (fs->fs_type == FS_FAT16) {
-							if (ld_word(fs->win + i) == 0) nfree++;
-							i += 2;
-						} else {
-							if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++;
-							i += 4;
-						}
-						i %= SS(fs);
-					} while (--clst);
-				}
-			}
-			*nclst = nfree;			/* Return the free clusters */
-			fs->free_clst = nfree;	/* Now free_clst is valid */
-			fs->fsi_flag |= 1;		/* FAT32: FSInfo is to be updated */
-		}
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Truncate File                                                         */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_truncate (
-	FIL* fp		/* Pointer to the file object */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD ncl;
-
-
-	res = validate(&fp->obj, &fs);	/* Check validity of the file object */
-	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
-	if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */
-
-	if (fp->fptr < fp->obj.objsize) {	/* Process when fptr is not on the eof */
-		if (fp->fptr == 0) {	/* When set file size to zero, remove entire cluster chain */
-			res = remove_chain(&fp->obj, fp->obj.sclust, 0);
-			fp->obj.sclust = 0;
-		} else {				/* When truncate a part of the file, remove remaining clusters */
-			ncl = get_fat(&fp->obj, fp->clust);
-			res = FR_OK;
-			if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
-			if (ncl == 1) res = FR_INT_ERR;
-			if (res == FR_OK && ncl < fs->n_fatent) {
-				res = remove_chain(&fp->obj, ncl, fp->clust);
-			}
-		}
-		fp->obj.objsize = fp->fptr;	/* Set file size to current read/write point */
-		fp->flag |= FA_MODIFIED;
-#if !FF_FS_TINY
-		if (res == FR_OK && (fp->flag & FA_DIRTY)) {
-			if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
-				res = FR_DISK_ERR;
-			} else {
-				fp->flag &= (BYTE)~FA_DIRTY;
-			}
-		}
-#endif
-		if (res != FR_OK) ABORT(fs, res);
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Delete a File/Directory                                               */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_unlink (
-	const TCHAR* path		/* Pointer to the file or directory path */
-)
-{
-	FRESULT res;
-	DIR dj, sdj;
-	DWORD dclst = 0;
-	FATFS *fs;
-#if FF_FS_EXFAT
-	FFOBJID obj;
-#endif
-	DEF_NAMBUF
-
-
-	/* Get logical drive */
-	res = find_volume(&path, &fs, FA_WRITE);
-	if (res == FR_OK) {
-		dj.obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(&dj, path);		/* Follow the file path */
-		if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) {
-			res = FR_INVALID_NAME;			/* Cannot remove dot entry */
-		}
-#if FF_FS_LOCK != 0
-		if (res == FR_OK) res = chk_lock(&dj, 2);	/* Check if it is an open object */
-#endif
-		if (res == FR_OK) {					/* The object is accessible */
-			if (dj.fn[NSFLAG] & NS_NONAME) {
-				res = FR_INVALID_NAME;		/* Cannot remove the origin directory */
-			} else {
-				if (dj.obj.attr & AM_RDO) {
-					res = FR_DENIED;		/* Cannot remove R/O object */
-				}
-			}
-			if (res == FR_OK) {
-#if FF_FS_EXFAT
-				obj.fs = fs;
-				if (fs->fs_type == FS_EXFAT) {
-					init_alloc_info(fs, &obj);
-					dclst = obj.sclust;
-				} else
-#endif
-				{
-					dclst = ld_clust(fs, dj.dir);
-				}
-				if (dj.obj.attr & AM_DIR) {			/* Is it a sub-directory? */
-#if FF_FS_RPATH != 0
-					if (dclst == fs->cdir) {		 	/* Is it the current directory? */
-						res = FR_DENIED;
-					} else
-#endif
-					{
-						sdj.obj.fs = fs;				/* Open the sub-directory */
-						sdj.obj.sclust = dclst;
-#if FF_FS_EXFAT
-						if (fs->fs_type == FS_EXFAT) {
-							sdj.obj.objsize = obj.objsize;
-							sdj.obj.stat = obj.stat;
-						}
-#endif
-						res = dir_sdi(&sdj, 0);
-						if (res == FR_OK) {
-							res = DIR_READ_FILE(&sdj);			/* Test if the directory is empty */
-							if (res == FR_OK) res = FR_DENIED;	/* Not empty? */
-							if (res == FR_NO_FILE) res = FR_OK;	/* Empty? */
-						}
-					}
-				}
-			}
-			if (res == FR_OK) {
-				res = dir_remove(&dj);			/* Remove the directory entry */
-				if (res == FR_OK && dclst != 0) {	/* Remove the cluster chain if exist */
-#if FF_FS_EXFAT
-					res = remove_chain(&obj, dclst, 0);
-#else
-					res = remove_chain(&dj.obj, dclst, 0);
-#endif
-				}
-				if (res == FR_OK) res = sync_fs(fs);
-			}
-		}
-		FREE_NAMBUF();
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Create a Directory                                                    */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_mkdir (
-	const TCHAR* path		/* Pointer to the directory path */
-)
-{
-	FRESULT res;
-	DIR dj;
-	FFOBJID sobj;
-	FATFS *fs;
-	DWORD dcl, pcl, tm;
-	DEF_NAMBUF
-
-
-	res = find_volume(&path, &fs, FA_WRITE);	/* Get logical drive */
-	if (res == FR_OK) {
-		dj.obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(&dj, path);			/* Follow the file path */
-		if (res == FR_OK) res = FR_EXIST;		/* Name collision? */
-		if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {	/* Invalid name? */
-			res = FR_INVALID_NAME;
-		}
-		if (res == FR_NO_FILE) {				/* It is clear to create a new directory */
-			sobj.fs = fs;						/* New object id to create a new chain */
-			dcl = create_chain(&sobj, 0);		/* Allocate a cluster for the new directory */
-			res = FR_OK;
-			if (dcl == 0) res = FR_DENIED;		/* No space to allocate a new cluster? */
-			if (dcl == 1) res = FR_INT_ERR;		/* Any insanity? */
-			if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;	/* Disk error? */
-			tm = GET_FATTIME();
-			if (res == FR_OK) {
-				res = dir_clear(fs, dcl);		/* Clean up the new table */
-				if (res == FR_OK) {
-					if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {	/* Create dot entries (FAT only) */
-						mem_set(fs->win + DIR_Name, ' ', 11);	/* Create "." entry */
-						fs->win[DIR_Name] = '.';
-						fs->win[DIR_Attr] = AM_DIR;
-						st_dword(fs->win + DIR_ModTime, tm);
-						st_clust(fs, fs->win, dcl);
-						mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
-						fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
-						st_clust(fs, fs->win + SZDIRE, pcl);
-						fs->wflag = 1;
-					}
-					res = dir_register(&dj);	/* Register the object to the parent directoy */
-				}
-			}
-			if (res == FR_OK) {
-#if FF_FS_EXFAT
-				if (fs->fs_type == FS_EXFAT) {	/* Initialize directory entry block */
-					st_dword(fs->dirbuf + XDIR_ModTime, tm);	/* Created time */
-					st_dword(fs->dirbuf + XDIR_FstClus, dcl);	/* Table start cluster */
-					st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs));	/* File size needs to be valid */
-					st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
-					fs->dirbuf[XDIR_GenFlags] = 3;				/* Initialize the object flag */
-					fs->dirbuf[XDIR_Attr] = AM_DIR;				/* Attribute */
-					res = store_xdir(&dj);
-				} else
-#endif
-				{
-					st_dword(dj.dir + DIR_ModTime, tm);	/* Created time */
-					st_clust(fs, dj.dir, dcl);			/* Table start cluster */
-					dj.dir[DIR_Attr] = AM_DIR;			/* Attribute */
-					fs->wflag = 1;
-				}
-				if (res == FR_OK) {
-					res = sync_fs(fs);
-				}
-			} else {
-				remove_chain(&sobj, dcl, 0);		/* Could not register, remove the allocated cluster */
-			}
-		}
-		FREE_NAMBUF();
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Rename a File/Directory                                               */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_rename (
-	const TCHAR* path_old,	/* Pointer to the object name to be renamed */
-	const TCHAR* path_new	/* Pointer to the new name */
-)
-{
-	FRESULT res;
-	DIR djo, djn;
-	FATFS *fs;
-	BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir;
-	DWORD dw;
-	DEF_NAMBUF
-
-
-	get_ldnumber(&path_new);						/* Snip the drive number of new name off */
-	res = find_volume(&path_old, &fs, FA_WRITE);	/* Get logical drive of the old object */
-	if (res == FR_OK) {
-		djo.obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(&djo, path_old);		/* Check old object */
-		if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check validity of name */
-#if FF_FS_LOCK != 0
-		if (res == FR_OK) {
-			res = chk_lock(&djo, 2);
-		}
-#endif
-		if (res == FR_OK) {						/* Object to be renamed is found */
-#if FF_FS_EXFAT
-			if (fs->fs_type == FS_EXFAT) {	/* At exFAT volume */
-				BYTE nf, nn;
-				WORD nh;
-
-				mem_cpy(buf, fs->dirbuf, SZDIRE * 2);	/* Save 85+C0 entry of old object */
-				mem_cpy(&djn, &djo, sizeof djo);
-				res = follow_path(&djn, path_new);		/* Make sure if new object name is not in use */
-				if (res == FR_OK) {						/* Is new name already in use by any other object? */
-					res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
-				}
-				if (res == FR_NO_FILE) { 				/* It is a valid path and no name collision */
-					res = dir_register(&djn);			/* Register the new entry */
-					if (res == FR_OK) {
-						nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName];
-						nh = ld_word(fs->dirbuf + XDIR_NameHash);
-						mem_cpy(fs->dirbuf, buf, SZDIRE * 2);	/* Restore 85+C0 entry */
-						fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
-						st_word(fs->dirbuf + XDIR_NameHash, nh);
-						if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC;	/* Set archive attribute if it is a file */
-/* Start of critical section where an interruption can cause a cross-link */
-						res = store_xdir(&djn);
-					}
-				}
-			} else
-#endif
-			{	/* At FAT/FAT32 volume */
-				mem_cpy(buf, djo.dir, SZDIRE);			/* Save directory entry of the object */
-				mem_cpy(&djn, &djo, sizeof (DIR));		/* Duplicate the directory object */
-				res = follow_path(&djn, path_new);		/* Make sure if new object name is not in use */
-				if (res == FR_OK) {						/* Is new name already in use by any other object? */
-					res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
-				}
-				if (res == FR_NO_FILE) { 				/* It is a valid path and no name collision */
-					res = dir_register(&djn);			/* Register the new entry */
-					if (res == FR_OK) {
-						dir = djn.dir;					/* Copy directory entry of the object except name */
-						mem_cpy(dir + 13, buf + 13, SZDIRE - 13);
-						dir[DIR_Attr] = buf[DIR_Attr];
-						if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC;	/* Set archive attribute if it is a file */
-						fs->wflag = 1;
-						if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) {	/* Update .. entry in the sub-directory if needed */
-							dw = clst2sect(fs, ld_clust(fs, dir));
-							if (dw == 0) {
-								res = FR_INT_ERR;
-							} else {
-/* Start of critical section where an interruption can cause a cross-link */
-								res = move_window(fs, dw);
-								dir = fs->win + SZDIRE * 1;	/* Ptr to .. entry */
-								if (res == FR_OK && dir[1] == '.') {
-									st_clust(fs, dir, djn.obj.sclust);
-									fs->wflag = 1;
-								}
-							}
-						}
-					}
-				}
-			}
-			if (res == FR_OK) {
-				res = dir_remove(&djo);		/* Remove old entry */
-				if (res == FR_OK) {
-					res = sync_fs(fs);
-				}
-			}
-/* End of the critical section */
-		}
-		FREE_NAMBUF();
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-#endif /* !FF_FS_READONLY */
-#endif /* FF_FS_MINIMIZE == 0 */
-#endif /* FF_FS_MINIMIZE <= 1 */
-#endif /* FF_FS_MINIMIZE <= 2 */
-
-
-
-#if FF_USE_CHMOD && !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Change Attribute                                                      */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_chmod (
-	const TCHAR* path,	/* Pointer to the file path */
-	BYTE attr,			/* Attribute bits */
-	BYTE mask			/* Attribute mask to change */
-)
-{
-	FRESULT res;
-	DIR dj;
-	FATFS *fs;
-	DEF_NAMBUF
-
-
-	res = find_volume(&path, &fs, FA_WRITE);	/* Get logical drive */
-	if (res == FR_OK) {
-		dj.obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(&dj, path);	/* Follow the file path */
-		if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check object validity */
-		if (res == FR_OK) {
-			mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC;	/* Valid attribute mask */
-#if FF_FS_EXFAT
-			if (fs->fs_type == FS_EXFAT) {
-				fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask);	/* Apply attribute change */
-				res = store_xdir(&dj);
-			} else
-#endif
-			{
-				dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask);	/* Apply attribute change */
-				fs->wflag = 1;
-			}
-			if (res == FR_OK) {
-				res = sync_fs(fs);
-			}
-		}
-		FREE_NAMBUF();
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Change Timestamp                                                      */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_utime (
-	const TCHAR* path,	/* Pointer to the file/directory name */
-	const FILINFO* fno	/* Pointer to the timestamp to be set */
-)
-{
-	FRESULT res;
-	DIR dj;
-	FATFS *fs;
-	DEF_NAMBUF
-
-
-	res = find_volume(&path, &fs, FA_WRITE);	/* Get logical drive */
-	if (res == FR_OK) {
-		dj.obj.fs = fs;
-		INIT_NAMBUF(fs);
-		res = follow_path(&dj, path);	/* Follow the file path */
-		if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check object validity */
-		if (res == FR_OK) {
-#if FF_FS_EXFAT
-			if (fs->fs_type == FS_EXFAT) {
-				st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
-				res = store_xdir(&dj);
-			} else
-#endif
-			{
-				st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
-				fs->wflag = 1;
-			}
-			if (res == FR_OK) {
-				res = sync_fs(fs);
-			}
-		}
-		FREE_NAMBUF();
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-#endif	/* FF_USE_CHMOD && !FF_FS_READONLY */
-
-
-
-#if FF_USE_LABEL
-/*-----------------------------------------------------------------------*/
-/* Get Volume Label                                                      */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_getlabel (
-	const TCHAR* path,	/* Logical drive number */
-	TCHAR* label,		/* Buffer to store the volume label */
-	DWORD* vsn			/* Variable to store the volume serial number */
-)
-{
-	FRESULT res;
-	DIR dj;
-	FATFS *fs;
-	UINT si, di;
-	WCHAR wc;
-
-	/* Get logical drive */
-	res = find_volume(&path, &fs, 0);
-
-	/* Get volume label */
-	if (res == FR_OK && label) {
-		dj.obj.fs = fs; dj.obj.sclust = 0;	/* Open root directory */
-		res = dir_sdi(&dj, 0);
-		if (res == FR_OK) {
-		 	res = DIR_READ_LABEL(&dj);		/* Find a volume label entry */
-		 	if (res == FR_OK) {
-#if FF_FS_EXFAT
-				if (fs->fs_type == FS_EXFAT) {
-					WCHAR hs;
-
-					for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) {	/* Extract volume label from 83 entry */
-						wc = ld_word(dj.dir + XDIR_Label + si * 2);
-						if (hs == 0 && IsSurrogate(wc)) {	/* Is the code a surrogate? */
-							hs = wc; continue;
-						}
-						wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4);
-						if (wc == 0) { di = 0; break; }
-						di += wc;
-						hs = 0;
-					}
-					if (hs != 0) di = 0;	/* Broken surrogate pair? */
-					label[di] = 0;
-				} else
-#endif
-				{
-					si = di = 0;		/* Extract volume label from AM_VOL entry */
-					while (si < 11) {
-						wc = dj.dir[si++];
-#if FF_USE_LFN && FF_LFN_UNICODE >= 1 	/* Unicode output */
-						if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++];	/* Is it a DBC? */
-						wc = ff_oem2uni(wc, CODEPAGE);					/* Convert it into Unicode */
-						if (wc != 0) wc = put_utf(wc, &label[di], 4);	/* Put it in Unicode */
-						if (wc == 0) { di = 0; break; }
-						di += wc;
-#else									/* ANSI/OEM output */
-						label[di++] = (TCHAR)wc;
-#endif
-					}
-					do {				/* Truncate trailing spaces */
-						label[di] = 0;
-						if (di == 0) break;
-					} while (label[--di] == ' ');
-				}
-			}
-		}
-		if (res == FR_NO_FILE) {	/* No label entry and return nul string */
-			label[0] = 0;
-			res = FR_OK;
-		}
-	}
-
-	/* Get volume serial number */
-	if (res == FR_OK && vsn) {
-		res = move_window(fs, fs->volbase);
-		if (res == FR_OK) {
-			switch (fs->fs_type) {
-			case FS_EXFAT:
-				di = BPB_VolIDEx; break;
-
-			case FS_FAT32:
-				di = BS_VolID32; break;
-
-			default:
-				di = BS_VolID;
-			}
-			*vsn = ld_dword(fs->win + di);
-		}
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-
-
-#if !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Set Volume Label                                                      */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_setlabel (
-	const TCHAR* label	/* Volume label to set with heading logical drive number */
-)
-{
-	FRESULT res;
-	DIR dj;
-	FATFS *fs;
-	BYTE dirvn[22];
-	UINT di;
-	WCHAR wc;
-	static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F";	/* [0..] for FAT, [7..] for exFAT */
-#if FF_USE_LFN
-	DWORD dc;
-#endif
-
-	/* Get logical drive */
-	res = find_volume(&label, &fs, FA_WRITE);
-	if (res != FR_OK) LEAVE_FF(fs, res);
-
-#if FF_FS_EXFAT
-	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
-		mem_set(dirvn, 0, 22);
-		di = 0;
-		while ((UINT)*label >= ' ') {	/* Create volume label */
-			dc = tchar2uni(&label);	/* Get a Unicode character */
-			if (dc >= 0x10000) {
-				if (dc == 0xFFFFFFFF || di >= 10) {	/* Wrong surrogate or buffer overflow */
-					dc = 0;
-				} else {
-					st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++;
-				}
-			}
-			if (dc == 0 || chk_chr(badchr + 7, (int)dc) || di >= 11) {	/* Check validity of the volume label */
-				LEAVE_FF(fs, FR_INVALID_NAME);
-			}
-			st_word(dirvn + di * 2, (WCHAR)dc); di++;
-		}
-	} else
-#endif
-	{	/* On the FAT/FAT32 volume */
-		mem_set(dirvn, ' ', 11);
-		di = 0;
-		while ((UINT)*label >= ' ') {	/* Create volume label */
-#if FF_USE_LFN
-			dc = tchar2uni(&label);
-			wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0;
-#else									/* ANSI/OEM input */
-			wc = (BYTE)*label++;
-			if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0;
-			if (IsLower(wc)) wc -= 0x20;		/* To upper ASCII characters */
-#if FF_CODE_PAGE == 0
-			if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80];	/* To upper extended characters (SBCS cfg) */
-#elif FF_CODE_PAGE < 900
-			if (wc >= 0x80) wc = ExCvt[wc - 0x80];	/* To upper extended characters (SBCS cfg) */
-#endif
-#endif
-			if (wc == 0 || chk_chr(badchr + 0, (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) {	/* Reject invalid characters for volume label */
-				LEAVE_FF(fs, FR_INVALID_NAME);
-			}
-			if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8);
-			dirvn[di++] = (BYTE)wc;
-		}
-		if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME);	/* Reject illegal name (heading DDEM) */
-		while (di && dirvn[di - 1] == ' ') di--;				/* Snip trailing spaces */
-	}
-
-	/* Set volume label */
-	dj.obj.fs = fs; dj.obj.sclust = 0;	/* Open root directory */
-	res = dir_sdi(&dj, 0);
-	if (res == FR_OK) {
-		res = DIR_READ_LABEL(&dj);	/* Get volume label entry */
-		if (res == FR_OK) {
-			if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
-				dj.dir[XDIR_NumLabel] = (BYTE)di;	/* Change the volume label */
-				mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
-			} else {
-				if (di != 0) {
-					mem_cpy(dj.dir, dirvn, 11);	/* Change the volume label */
-				} else {
-					dj.dir[DIR_Name] = DDEM;	/* Remove the volume label */
-				}
-			}
-			fs->wflag = 1;
-			res = sync_fs(fs);
-		} else {			/* No volume label entry or an error */
-			if (res == FR_NO_FILE) {
-				res = FR_OK;
-				if (di != 0) {	/* Create a volume label entry */
-					res = dir_alloc(&dj, 1);	/* Allocate an entry */
-					if (res == FR_OK) {
-						mem_set(dj.dir, 0, SZDIRE);	/* Clean the entry */
-						if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
-							dj.dir[XDIR_Type] = ET_VLABEL;	/* Create volume label entry */
-							dj.dir[XDIR_NumLabel] = (BYTE)di;
-							mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
-						} else {
-							dj.dir[DIR_Attr] = AM_VOL;		/* Create volume label entry */
-							mem_cpy(dj.dir, dirvn, 11);
-						}
-						fs->wflag = 1;
-						res = sync_fs(fs);
-					}
-				}
-			}
-		}
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-#endif /* !FF_FS_READONLY */
-#endif /* FF_USE_LABEL */
-
-
-
-#if FF_USE_EXPAND && !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Allocate a Contiguous Blocks to the File                              */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_expand (
-	FIL* fp,		/* Pointer to the file object */
-	FSIZE_t fsz,	/* File size to be expanded to */
-	BYTE opt		/* Operation mode 0:Find and prepare or 1:Find and allocate */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD n, clst, stcl, scl, ncl, tcl, lclst;
-
-
-	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
-	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
-	if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);
-#if FF_FS_EXFAT
-	if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED);	/* Check if in size limit */
-#endif
-	n = (DWORD)fs->csize * SS(fs);	/* Cluster size */
-	tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0);	/* Number of clusters required */
-	stcl = fs->last_clst; lclst = 0;
-	if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2;
-
-#if FF_FS_EXFAT
-	if (fs->fs_type == FS_EXFAT) {
-		scl = find_bitmap(fs, stcl, tcl);			/* Find a contiguous cluster block */
-		if (scl == 0) res = FR_DENIED;				/* No contiguous cluster block was found */
-		if (scl == 0xFFFFFFFF) res = FR_DISK_ERR;
-		if (res == FR_OK) {	/* A contiguous free area is found */
-			if (opt) {		/* Allocate it now */
-				res = change_bitmap(fs, scl, tcl, 1);	/* Mark the cluster block 'in use' */
-				lclst = scl + tcl - 1;
-			} else {		/* Set it as suggested point for next allocation */
-				lclst = scl - 1;
-			}
-		}
-	} else
-#endif
-	{
-		scl = clst = stcl; ncl = 0;
-		for (;;) {	/* Find a contiguous cluster block */
-			n = get_fat(&fp->obj, clst);
-			if (++clst >= fs->n_fatent) clst = 2;
-			if (n == 1) { res = FR_INT_ERR; break; }
-			if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
-			if (n == 0) {	/* Is it a free cluster? */
-				if (++ncl == tcl) break;	/* Break if a contiguous cluster block is found */
-			} else {
-				scl = clst; ncl = 0;		/* Not a free cluster */
-			}
-			if (clst == stcl) { res = FR_DENIED; break; }	/* No contiguous cluster? */
-		}
-		if (res == FR_OK) {	/* A contiguous free area is found */
-			if (opt) {		/* Allocate it now */
-				for (clst = scl, n = tcl; n; clst++, n--) {	/* Create a cluster chain on the FAT */
-					res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1);
-					if (res != FR_OK) break;
-					lclst = clst;
-				}
-			} else {		/* Set it as suggested point for next allocation */
-				lclst = scl - 1;
-			}
-		}
-	}
-
-	if (res == FR_OK) {
-		fs->last_clst = lclst;		/* Set suggested start cluster to start next */
-		if (opt) {	/* Is it allocated now? */
-			fp->obj.sclust = scl;		/* Update object allocation information */
-			fp->obj.objsize = fsz;
-			if (FF_FS_EXFAT) fp->obj.stat = 2;	/* Set status 'contiguous chain' */
-			fp->flag |= FA_MODIFIED;
-			if (fs->free_clst <= fs->n_fatent - 2) {	/* Update FSINFO */
-				fs->free_clst -= tcl;
-				fs->fsi_flag |= 1;
-			}
-		}
-	}
-
-	LEAVE_FF(fs, res);
-}
-
-#endif /* FF_USE_EXPAND && !FF_FS_READONLY */
-
-
-
-#if FF_USE_FORWARD
-/*-----------------------------------------------------------------------*/
-/* Forward Data to the Stream Directly                                   */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_forward (
-	FIL* fp, 						/* Pointer to the file object */
-	UINT (*func)(const BYTE*,UINT),	/* Pointer to the streaming function */
-	UINT btf,						/* Number of bytes to forward */
-	UINT* bf						/* Pointer to number of bytes forwarded */
-)
-{
-	FRESULT res;
-	FATFS *fs;
-	DWORD clst, sect;
-	FSIZE_t remain;
-	UINT rcnt, csect;
-	BYTE *dbuf;
-
-
-	*bf = 0;	/* Clear transfer byte counter */
-	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
-	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
-	if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */
-
-	remain = fp->obj.objsize - fp->fptr;
-	if (btf > remain) btf = (UINT)remain;			/* Truncate btf by remaining bytes */
-
-	for ( ;  btf && (*func)(0, 0);					/* Repeat until all data transferred or stream goes busy */
-		fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
-		csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));	/* Sector offset in the cluster */
-		if (fp->fptr % SS(fs) == 0) {				/* On the sector boundary? */
-			if (csect == 0) {						/* On the cluster boundary? */
-				clst = (fp->fptr == 0) ?			/* On the top of the file? */
-					fp->obj.sclust : get_fat(&fp->obj, fp->clust);
-				if (clst <= 1) ABORT(fs, FR_INT_ERR);
-				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
-				fp->clust = clst;					/* Update current cluster */
-			}
-		}
-		sect = clst2sect(fs, fp->clust);			/* Get current data sector */
-		if (sect == 0) ABORT(fs, FR_INT_ERR);
-		sect += csect;
-#if FF_FS_TINY
-		if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window to the file data */
-		dbuf = fs->win;
-#else
-		if (fp->sect != sect) {		/* Fill sector cache with file data */
-#if !FF_FS_READONLY
-			if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
-				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
-				fp->flag &= (BYTE)~FA_DIRTY;
-			}
-#endif
-			if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
-		}
-		dbuf = fp->buf;
-#endif
-		fp->sect = sect;
-		rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes left in the sector */
-		if (rcnt > btf) rcnt = btf;					/* Clip it by btr if needed */
-		rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt);	/* Forward the file data */
-		if (rcnt == 0) ABORT(fs, FR_INT_ERR);
-	}
-
-	LEAVE_FF(fs, FR_OK);
-}
-#endif /* FF_USE_FORWARD */
-
-
-
-#if FF_USE_MKFS && !FF_FS_READONLY
-/*-----------------------------------------------------------------------*/
-/* Create an FAT/exFAT volume                                            */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_mkfs (
-	const TCHAR* path,	/* Logical drive number */
-	BYTE opt,			/* Format option */
-	DWORD au,			/* Size of allocation unit (cluster) [byte] */
-	void* work,			/* Pointer to working buffer (null: use heap memory) */
-	UINT len			/* Size of working buffer [byte] */
-)
-{
-	const UINT n_fats = 1;		/* Number of FATs for FAT/FAT32 volume (1 or 2) */
-	const UINT n_rootdir = 512;	/* Number of root directory entries for FAT volume */
-	static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0};	/* Cluster size boundary for FAT volume (4Ks unit) */
-	static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0};	/* Cluster size boundary for FAT32 volume (128Ks unit) */
-	BYTE fmt, sys, *buf, *pte, pdrv, part;
-	WORD ss;	/* Sector size */
-	DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n;
-	DWORD b_vol, b_fat, b_data;				/* Base LBA for volume, fat, data */
-	DWORD sz_vol, sz_rsv, sz_fat, sz_dir;	/* Size for volume, fat, dir, data */
-	UINT i;
-	int vol;
-	DSTATUS stat;
-#if FF_USE_TRIM || FF_FS_EXFAT
-	DWORD tbl[3];
-#endif
-
-
-	/* Check mounted drive and clear work area */
-	vol = get_ldnumber(&path);					/* Get target logical drive */
-	if (vol < 0) return FR_INVALID_DRIVE;
-	if (FatFs[vol]) FatFs[vol]->fs_type = 0;	/* Clear the volume if mounted */
-	pdrv = LD2PD(vol);	/* Physical drive */
-	part = LD2PT(vol);	/* Partition (0:create as new, 1-4:get from partition table) */
-
-	/* Check physical drive status */
-	stat = disk_initialize(pdrv);
-	if (stat & STA_NOINIT) return FR_NOT_READY;
-	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
-	if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1;	/* Erase block to align data area */
-#if FF_MAX_SS != FF_MIN_SS		/* Get sector size of the medium if variable sector size cfg. */
-	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
-	if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
-#else
-	ss = FF_MAX_SS;
-#endif
-	if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER;	/* Check if au is valid */
-	au /= ss;	/* Cluster size in unit of sector */
-
-	/* Get working buffer */
-#if FF_USE_LFN == 3
-	if (!work) {	/* Use heap memory for working buffer */
-		for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ;
-		sz_buf = szb_buf / ss;		/* Size of working buffer (sector) */
-	} else
-#endif
-	{
-		buf = (BYTE*)work;		/* Working buffer */
-		sz_buf = len / ss;		/* Size of working buffer (sector) */
-		szb_buf = sz_buf * ss;	/* Size of working buffer (byte) */
-	}
-	if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE;
-
-	/* Determine where the volume to be located (b_vol, sz_vol) */
-	if (FF_MULTI_PARTITION && part != 0) {
-		/* Get partition information from partition table in the MBR */
-		if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Load MBR */
-		if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if MBR is valid */
-		pte = buf + (MBR_Table + (part - 1) * SZ_PTE);
-		if (pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED);	/* No partition? */
-		b_vol = ld_dword(pte + PTE_StLba);		/* Get volume start sector */
-		sz_vol = ld_dword(pte + PTE_SizLba);	/* Get volume size */
-	} else {
-		/* Create a single-partition in this function */
-		if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-		b_vol = (opt & FM_SFD) ? 0 : 63;		/* Volume start sector */
-		if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);
-		sz_vol -= b_vol;						/* Volume size */
-	}
-	if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if volume size is >=128s */
-
-	/* Pre-determine the FAT type */
-	do {
-		if (FF_FS_EXFAT && (opt & FM_EXFAT)) {	/* exFAT possible? */
-			if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) {	/* exFAT only, vol >= 64Ms or au > 128s ? */
-				fmt = FS_EXFAT; break;
-			}
-		}
-		if (au > 128) LEAVE_MKFS(FR_INVALID_PARAMETER);	/* Too large au for FAT/FAT32 */
-		if (opt & FM_FAT32) {	/* FAT32 possible? */
-			if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) {	/* FAT32 only or no-FAT? */
-				fmt = FS_FAT32; break;
-			}
-		}
-		if (!(opt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER);	/* no-FAT? */
-		fmt = FS_FAT16;
-	} while (0);
-
-#if FF_FS_EXFAT
-	if (fmt == FS_EXFAT) {	/* Create an exFAT volume */
-		DWORD szb_bit, szb_case, sum, nb, cl;
-		WCHAR ch, si;
-		UINT j, st;
-		BYTE b;
-
-		if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume? */
-#if FF_USE_TRIM
-		tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1;	/* Inform the device the volume area may be erased */
-		disk_ioctl(pdrv, CTRL_TRIM, tbl);
-#endif
-		/* Determine FAT location, data location and number of clusters */
-		if (au == 0) {	/* au auto-selection */
-			au = 8;
-			if (sz_vol >= 0x80000) au = 64;		/* >= 512Ks */
-			if (sz_vol >= 0x4000000) au = 256;	/* >= 64Ms */
-		}
-		b_fat = b_vol + 32;										/* FAT start at offset 32 */
-		sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss;			/* Number of FAT sectors */
-		b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1);	/* Align data area to the erase block boundary */
-		if (b_data >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume? */
-		n_clst = (sz_vol - (b_data - b_vol)) / au;				/* Number of clusters */
-		if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED);			/* Too few clusters? */
-		if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too many clusters? */
-
-		szb_bit = (n_clst + 7) / 8;						/* Size of allocation bitmap */
-		tbl[0] = (szb_bit + au * ss - 1) / (au * ss);	/* Number of allocation bitmap clusters */
-
-		/* Create a compressed up-case table */
-		sect = b_data + au * tbl[0];	/* Table start sector */
-		sum = 0;						/* Table checksum to be stored in the 82 entry */
-		st = 0; si = 0; i = 0; j = 0; szb_case = 0;
-		do {
-			switch (st) {
-			case 0:
-				ch = (WCHAR)ff_wtoupper(si);	/* Get an up-case char */
-				if (ch != si) {
-					si++; break;		/* Store the up-case char if exist */
-				}
-				for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ;	/* Get run length of no-case block */
-				if (j >= 128) {
-					ch = 0xFFFF; st = 2; break;	/* Compress the no-case block if run is >= 128 */
-				}
-				st = 1;			/* Do not compress short run */
-				/* go to next case */
-			case 1:
-				ch = si++;		/* Fill the short run */
-				if (--j == 0) st = 0;
-				break;
-
-			default:
-				ch = (WCHAR)j; si += (WCHAR)j;	/* Number of chars to skip */
-				st = 0;
-			}
-			sum = xsum32(buf[i + 0] = (BYTE)ch, sum);		/* Put it into the write buffer */
-			sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum);
-			i += 2; szb_case += 2;
-			if (si == 0 || i == szb_buf) {		/* Write buffered data when buffer full or end of process */
-				n = (i + ss - 1) / ss;
-				if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-				sect += n; i = 0;
-			}
-		} while (si);
-		tbl[1] = (szb_case + au * ss - 1) / (au * ss);	/* Number of up-case table clusters */
-		tbl[2] = 1;										/* Number of root dir clusters */
-
-		/* Initialize the allocation bitmap */
-		sect = b_data; nsect = (szb_bit + ss - 1) / ss;	/* Start of bitmap and number of sectors */
-		nb = tbl[0] + tbl[1] + tbl[2];					/* Number of clusters in-use by system */
-		do {
-			mem_set(buf, 0, szb_buf);
-			for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ;
-			for (b = 1; nb != 0 && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ;
-			n = (nsect > sz_buf) ? sz_buf : nsect;		/* Write the buffered data */
-			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-			sect += n; nsect -= n;
-		} while (nsect);
-
-		/* Initialize the FAT */
-		sect = b_fat; nsect = sz_fat;	/* Start of FAT and number of FAT sectors */
-		j = nb = cl = 0;
-		do {
-			mem_set(buf, 0, szb_buf); i = 0;	/* Clear work area and reset write index */
-			if (cl == 0) {	/* Set entry 0 and 1 */
-				st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++;
-				st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++;
-			}
-			do {			/* Create chains of bitmap, up-case and root dir */
-				while (nb != 0 && i < szb_buf) {			/* Create a chain */
-					st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF);
-					i += 4; cl++; nb--;
-				}
-				if (nb == 0 && j < 3) nb = tbl[j++];	/* Next chain */
-			} while (nb != 0 && i < szb_buf);
-			n = (nsect > sz_buf) ? sz_buf : nsect;	/* Write the buffered data */
-			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-			sect += n; nsect -= n;
-		} while (nsect);
-
-		/* Initialize the root directory */
-		mem_set(buf, 0, szb_buf);
-		buf[SZDIRE * 0 + 0] = ET_VLABEL;		/* Volume label entry */
-		buf[SZDIRE * 1 + 0] = ET_BITMAP;		/* Bitmap entry */
-		st_dword(buf + SZDIRE * 1 + 20, 2);				/* cluster */
-		st_dword(buf + SZDIRE * 1 + 24, szb_bit);		/* size */
-		buf[SZDIRE * 2 + 0] = ET_UPCASE;		/* Up-case table entry */
-		st_dword(buf + SZDIRE * 2 + 4, sum);			/* sum */
-		st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]);	/* cluster */
-		st_dword(buf + SZDIRE * 2 + 24, szb_case);		/* size */
-		sect = b_data + au * (tbl[0] + tbl[1]);	nsect = au;	/* Start of the root directory and number of sectors */
-		do {	/* Fill root directory sectors */
-			n = (nsect > sz_buf) ? sz_buf : nsect;
-			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-			mem_set(buf, 0, ss);
-			sect += n; nsect -= n;
-		} while (nsect);
-
-		/* Create two set of the exFAT VBR blocks */
-		sect = b_vol;
-		for (n = 0; n < 2; n++) {
-			/* Main record (+0) */
-			mem_set(buf, 0, ss);
-			mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT   ", 11);	/* Boot jump code (x86), OEM name */
-			st_dword(buf + BPB_VolOfsEx, b_vol);					/* Volume offset in the physical drive [sector] */
-			st_dword(buf + BPB_TotSecEx, sz_vol);					/* Volume size [sector] */
-			st_dword(buf + BPB_FatOfsEx, b_fat - b_vol);			/* FAT offset [sector] */
-			st_dword(buf + BPB_FatSzEx, sz_fat);					/* FAT size [sector] */
-			st_dword(buf + BPB_DataOfsEx, b_data - b_vol);			/* Data offset [sector] */
-			st_dword(buf + BPB_NumClusEx, n_clst);					/* Number of clusters */
-			st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]);	/* Root dir cluster # */
-			st_dword(buf + BPB_VolIDEx, GET_FATTIME());				/* VSN */
-			st_word(buf + BPB_FSVerEx, 0x100);						/* Filesystem version (1.00) */
-			for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ;	/* Log2 of sector size [byte] */
-			for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ;	/* Log2 of cluster size [sector] */
-			buf[BPB_NumFATsEx] = 1;					/* Number of FATs */
-			buf[BPB_DrvNumEx] = 0x80;				/* Drive number (for int13) */
-			st_word(buf + BS_BootCodeEx, 0xFEEB);	/* Boot code (x86) */
-			st_word(buf + BS_55AA, 0xAA55);			/* Signature (placed here regardless of sector size) */
-			for (i = sum = 0; i < ss; i++) {		/* VBR checksum */
-				if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum);
-			}
-			if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-			/* Extended bootstrap record (+1..+8) */
-			mem_set(buf, 0, ss);
-			st_word(buf + ss - 2, 0xAA55);	/* Signature (placed at end of sector) */
-			for (j = 1; j < 9; j++) {
-				for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;	/* VBR checksum */
-				if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-			}
-			/* OEM/Reserved record (+9..+10) */
-			mem_set(buf, 0, ss);
-			for ( ; j < 11; j++) {
-				for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;	/* VBR checksum */
-				if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-			}
-			/* Sum record (+11) */
-			for (i = 0; i < ss; i += 4) st_dword(buf + i, sum);		/* Fill with checksum value */
-			if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-		}
-
-	} else
-#endif	/* FF_FS_EXFAT */
-	{	/* Create an FAT/FAT32 volume */
-		do {
-			pau = au;
-			/* Pre-determine number of clusters and FAT sub-type */
-			if (fmt == FS_FAT32) {	/* FAT32 volume */
-				if (pau == 0) {	/* au auto-selection */
-					n = sz_vol / 0x20000;	/* Volume size in unit of 128KS */
-					for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ;	/* Get from table */
-				}
-				n_clst = sz_vol / pau;	/* Number of clusters */
-				sz_fat = (n_clst * 4 + 8 + ss - 1) / ss;	/* FAT size [sector] */
-				sz_rsv = 32;	/* Number of reserved sectors */
-				sz_dir = 0;		/* No static directory */
-				if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED);
-			} else {				/* FAT volume */
-				if (pau == 0) {	/* au auto-selection */
-					n = sz_vol / 0x1000;	/* Volume size in unit of 4KS */
-					for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ;	/* Get from table */
-				}
-				n_clst = sz_vol / pau;
-				if (n_clst > MAX_FAT12) {
-					n = n_clst * 2 + 4;		/* FAT size [byte] */
-				} else {
-					fmt = FS_FAT12;
-					n = (n_clst * 3 + 1) / 2 + 3;	/* FAT size [byte] */
-				}
-				sz_fat = (n + ss - 1) / ss;		/* FAT size [sector] */
-				sz_rsv = 1;						/* Number of reserved sectors */
-				sz_dir = (DWORD)n_rootdir * SZDIRE / ss;	/* Rootdir size [sector] */
-			}
-			b_fat = b_vol + sz_rsv;						/* FAT base */
-			b_data = b_fat + sz_fat * n_fats + sz_dir;	/* Data base */
-
-			/* Align data base to erase block boundary (for flash memory media) */
-			n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data;	/* Next nearest erase block from current data base */
-			if (fmt == FS_FAT32) {		/* FAT32: Move FAT base */
-				sz_rsv += n; b_fat += n;
-			} else {					/* FAT: Expand FAT size */
-				sz_fat += n / n_fats;
-			}
-
-			/* Determine number of clusters and final check of validity of the FAT sub-type */
-			if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume */
-			n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau;
-			if (fmt == FS_FAT32) {
-				if (n_clst <= MAX_FAT16) {	/* Too few clusters for FAT32 */
-					if (au == 0 && (au = pau / 2) != 0) continue;	/* Adjust cluster size and retry */
-					LEAVE_MKFS(FR_MKFS_ABORTED);
-				}
-			}
-			if (fmt == FS_FAT16) {
-				if (n_clst > MAX_FAT16) {	/* Too many clusters for FAT16 */
-					if (au == 0 && (pau * 2) <= 64) {
-						au = pau * 2; continue;		/* Adjust cluster size and retry */
-					}
-					if ((opt & FM_FAT32)) {
-						fmt = FS_FAT32; continue;	/* Switch type to FAT32 and retry */
-					}
-					if (au == 0 && (au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
-					LEAVE_MKFS(FR_MKFS_ABORTED);
-				}
-				if  (n_clst <= MAX_FAT12) {	/* Too few clusters for FAT16 */
-					if (au == 0 && (au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
-					LEAVE_MKFS(FR_MKFS_ABORTED);
-				}
-			}
-			if (fmt == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too many clusters for FAT12 */
-
-			/* Ok, it is the valid cluster configuration */
-			break;
-		} while (1);
-
-#if FF_USE_TRIM
-		tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1;	/* Inform the device the volume area can be erased */
-		disk_ioctl(pdrv, CTRL_TRIM, tbl);
-#endif
-		/* Create FAT VBR */
-		mem_set(buf, 0, ss);
-		mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */
-		st_word(buf + BPB_BytsPerSec, ss);				/* Sector size [byte] */
-		buf[BPB_SecPerClus] = (BYTE)pau;				/* Cluster size [sector] */
-		st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv);	/* Size of reserved area */
-		buf[BPB_NumFATs] = (BYTE)n_fats;				/* Number of FATs */
-		st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir));	/* Number of root directory entries */
-		if (sz_vol < 0x10000) {
-			st_word(buf + BPB_TotSec16, (WORD)sz_vol);	/* Volume size in 16-bit LBA */
-		} else {
-			st_dword(buf + BPB_TotSec32, sz_vol);		/* Volume size in 32-bit LBA */
-		}
-		buf[BPB_Media] = 0xF8;							/* Media descriptor byte */
-		st_word(buf + BPB_SecPerTrk, 63);				/* Number of sectors per track (for int13) */
-		st_word(buf + BPB_NumHeads, 255);				/* Number of heads (for int13) */
-		st_dword(buf + BPB_HiddSec, b_vol);				/* Volume offset in the physical drive [sector] */
-		if (fmt == FS_FAT32) {
-			st_dword(buf + BS_VolID32, GET_FATTIME());	/* VSN */
-			st_dword(buf + BPB_FATSz32, sz_fat);		/* FAT size [sector] */
-			st_dword(buf + BPB_RootClus32, 2);			/* Root directory cluster # (2) */
-			st_word(buf + BPB_FSInfo32, 1);				/* Offset of FSINFO sector (VBR + 1) */
-			st_word(buf + BPB_BkBootSec32, 6);			/* Offset of backup VBR (VBR + 6) */
-			buf[BS_DrvNum32] = 0x80;					/* Drive number (for int13) */
-			buf[BS_BootSig32] = 0x29;					/* Extended boot signature */
-			mem_cpy(buf + BS_VolLab32, "NO NAME    " "FAT32   ", 19);	/* Volume label, FAT signature */
-		} else {
-			st_dword(buf + BS_VolID, GET_FATTIME());	/* VSN */
-			st_word(buf + BPB_FATSz16, (WORD)sz_fat);	/* FAT size [sector] */
-			buf[BS_DrvNum] = 0x80;						/* Drive number (for int13) */
-			buf[BS_BootSig] = 0x29;						/* Extended boot signature */
-			mem_cpy(buf + BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
-		}
-		st_word(buf + BS_55AA, 0xAA55);					/* Signature (offset is fixed here regardless of sector size) */
-		if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the VBR sector */
-
-		/* Create FSINFO record if needed */
-		if (fmt == FS_FAT32) {
-			disk_write(pdrv, buf, b_vol + 6, 1);		/* Write backup VBR (VBR + 6) */
-			mem_set(buf, 0, ss);
-			st_dword(buf + FSI_LeadSig, 0x41615252);
-			st_dword(buf + FSI_StrucSig, 0x61417272);
-			st_dword(buf + FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
-			st_dword(buf + FSI_Nxt_Free, 2);			/* Last allocated cluster# */
-			st_word(buf + BS_55AA, 0xAA55);
-			disk_write(pdrv, buf, b_vol + 7, 1);		/* Write backup FSINFO (VBR + 7) */
-			disk_write(pdrv, buf, b_vol + 1, 1);		/* Write original FSINFO (VBR + 1) */
-		}
-
-		/* Initialize FAT area */
-		mem_set(buf, 0, (UINT)szb_buf);
-		sect = b_fat;		/* FAT start sector */
-		for (i = 0; i < n_fats; i++) {			/* Initialize FATs each */
-			if (fmt == FS_FAT32) {
-				st_dword(buf + 0, 0xFFFFFFF8);	/* Entry 0 */
-				st_dword(buf + 4, 0xFFFFFFFF);	/* Entry 1 */
-				st_dword(buf + 8, 0x0FFFFFFF);	/* Entry 2 (root directory) */
-			} else {
-				st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8);	/* Entry 0 and 1 */
-			}
-			nsect = sz_fat;		/* Number of FAT sectors */
-			do {	/* Fill FAT sectors */
-				n = (nsect > sz_buf) ? sz_buf : nsect;
-				if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-				mem_set(buf, 0, ss);
-				sect += n; nsect -= n;
-			} while (nsect);
-		}
-
-		/* Initialize root directory (fill with zero) */
-		nsect = (fmt == FS_FAT32) ? pau : sz_dir;	/* Number of root directory sectors */
-		do {
-			n = (nsect > sz_buf) ? sz_buf : nsect;
-			if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-			sect += n; nsect -= n;
-		} while (nsect);
-	}
-
-	/* Determine system ID in the partition table */
-	if (FF_FS_EXFAT && fmt == FS_EXFAT) {
-		sys = 0x07;			/* HPFS/NTFS/exFAT */
-	} else {
-		if (fmt == FS_FAT32) {
-			sys = 0x0C;		/* FAT32X */
-		} else {
-			if (sz_vol >= 0x10000) {
-				sys = 0x06;	/* FAT12/16 (large) */
-			} else {
-				sys = (fmt == FS_FAT16) ? 0x04 : 0x01;	/* FAT16 : FAT12 */
-			}
-		}
-	}
-
-	/* Update partition information */
-	if (FF_MULTI_PARTITION && part != 0) {	/* Created in the existing partition */
-		/* Update system ID in the partition table */
-		if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Read the MBR */
-		buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys;		/* Set system ID */
-		if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it back to the MBR */
-	} else {								/* Created as a new single partition */
-		if (!(opt & FM_SFD)) {	/* Create partition table if in FDISK format */
-			mem_set(buf, 0, ss);
-			st_word(buf + BS_55AA, 0xAA55);		/* MBR signature */
-			pte = buf + MBR_Table;				/* Create partition table for single partition in the drive */
-			pte[PTE_Boot] = 0;					/* Boot indicator */
-			pte[PTE_StHead] = 1;				/* Start head */
-			pte[PTE_StSec] = 1;					/* Start sector */
-			pte[PTE_StCyl] = 0;					/* Start cylinder */
-			pte[PTE_System] = sys;				/* System type */
-			n = (b_vol + sz_vol) / (63 * 255);	/* (End CHS may be invalid) */
-			pte[PTE_EdHead] = 254;				/* End head */
-			pte[PTE_EdSec] = (BYTE)(((n >> 2) & 0xC0) | 63);	/* End sector */
-			pte[PTE_EdCyl] = (BYTE)n;			/* End cylinder */
-			st_dword(pte + PTE_StLba, b_vol);	/* Start offset in LBA */
-			st_dword(pte + PTE_SizLba, sz_vol);	/* Size in sectors */
-			if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the MBR */
-		}
-	}
-
-	if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
-
-	LEAVE_MKFS(FR_OK);
-}
-
-
-
-#if FF_MULTI_PARTITION
-/*-----------------------------------------------------------------------*/
-/* Create Partition Table on the Physical Drive                          */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_fdisk (
-	BYTE pdrv,			/* Physical drive number */
-	const DWORD* szt,	/* Pointer to the size table for each partitions */
-	void* work			/* Pointer to the working buffer (null: use heap memory) */
-)
-{
-	UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
-	BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
-	DSTATUS stat;
-	DWORD sz_disk, sz_part, s_part;
-	FRESULT res;
-
-
-	stat = disk_initialize(pdrv);
-	if (stat & STA_NOINIT) return FR_NOT_READY;
-	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
-	if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
-
-	buf = (BYTE*)work;
-#if FF_USE_LFN == 3
-	if (!buf) buf = ff_memalloc(FF_MAX_SS);	/* Use heap memory for working buffer */
-#endif
-	if (!buf) return FR_NOT_ENOUGH_CORE;
-
-	/* Determine the CHS without any consideration of the drive geometry */
-	for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
-	if (n == 256) n--;
-	e_hd = (BYTE)(n - 1);
-	sz_cyl = 63 * n;
-	tot_cyl = sz_disk / sz_cyl;
-
-	/* Create partition table */
-	mem_set(buf, 0, FF_MAX_SS);
-	p = buf + MBR_Table; b_cyl = 0;
-	for (i = 0; i < 4; i++, p += SZ_PTE) {
-		p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;	/* Number of cylinders */
-		if (p_cyl == 0) continue;
-		s_part = (DWORD)sz_cyl * b_cyl;
-		sz_part = (DWORD)sz_cyl * p_cyl;
-		if (i == 0) {	/* Exclude first track of cylinder 0 */
-			s_hd = 1;
-			s_part += 63; sz_part -= 63;
-		} else {
-			s_hd = 0;
-		}
-		e_cyl = b_cyl + p_cyl - 1;	/* End cylinder */
-		if (e_cyl >= tot_cyl) LEAVE_MKFS(FR_INVALID_PARAMETER);
-
-		/* Set partition table */
-		p[1] = s_hd;						/* Start head */
-		p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1);	/* Start sector */
-		p[3] = (BYTE)b_cyl;					/* Start cylinder */
-		p[4] = 0x07;						/* System type (temporary setting) */
-		p[5] = e_hd;						/* End head */
-		p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63);	/* End sector */
-		p[7] = (BYTE)e_cyl;					/* End cylinder */
-		st_dword(p + 8, s_part);			/* Start sector in LBA */
-		st_dword(p + 12, sz_part);			/* Number of sectors */
-
-		/* Next partition */
-		b_cyl += p_cyl;
-	}
-	st_word(p, 0xAA55);		/* MBR signature (always at offset 510) */
-
-	/* Write it to the MBR */
-	res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
-	LEAVE_MKFS(res);
-}
-
-#endif /* FF_MULTI_PARTITION */
-#endif /* FF_USE_MKFS && !FF_FS_READONLY */
-
-
-
-
-#if FF_USE_STRFUNC
-#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3)
-#error Wrong FF_STRF_ENCODE setting
-#endif
-/*-----------------------------------------------------------------------*/
-/* Get a String from the File                                            */
-/*-----------------------------------------------------------------------*/
-
-TCHAR* f_gets (
-	TCHAR* buff,	/* Pointer to the string buffer to read */
-	int len,		/* Size of string buffer (items) */
-	FIL* fp			/* Pointer to the file object */
-)
-{
-	int nc = 0;
-	TCHAR *p = buff;
-	BYTE s[4];
-	UINT rc;
-	DWORD dc;
-#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2
-	WCHAR wc;
-#endif
-#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3
-	UINT ct;
-#endif
-
-#if FF_USE_LFN && FF_LFN_UNICODE			/* With code conversion (Unicode API) */
-	/* Make a room for the character and terminator  */
-	if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2;
-	if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4;
-	if (FF_LFN_UNICODE == 3) len -= 1;
-	while (nc < len) {
-#if FF_STRF_ENCODE == 0		/* Read a character in ANSI/OEM */
-		f_read(fp, s, 1, &rc);
-		if (rc != 1) break;
-		wc = s[0];
-		if (dbc_1st((BYTE)wc)) {
-			f_read(fp, s, 1, &rc);
-			if (rc != 1 || !dbc_2nd(s[0])) continue;
-			wc = wc << 8 | s[0];
-		}
-		dc = ff_oem2uni(wc, CODEPAGE);
-		if (dc == 0) continue;
-#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 	/* Read a character in UTF-16LE/BE */
-		f_read(fp, s, 2, &rc);
-		if (rc != 2) break;
-		dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
-		if (IsSurrogateL(dc)) continue;
-		if (IsSurrogateH(dc)) {
-			f_read(fp, s, 2, &rc);
-			if (rc != 2) break;
-			wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
-			if (!IsSurrogateL(wc)) continue;
-			dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF);
-		}
-#else	/* Read a character in UTF-8 */
-		f_read(fp, s, 1, &rc);
-		if (rc != 1) break;
-		dc = s[0];
-		if (dc >= 0x80) {	/* Multi-byte character? */
-			ct = 0;
-			if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; }	/* 2-byte? */
-			if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; }	/* 3-byte? */
-			if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; }	/* 4-byte? */
-			if (ct == 0) continue;
-			f_read(fp, s, ct, &rc);		/* Get trailing bytes */
-			if (rc != ct) break;
-			rc = 0;
-			do {	/* Merge trailing bytes */
-				if ((s[rc] & 0xC0) != 0x80) break;
-				dc = dc << 6 | (s[rc] & 0x3F);
-			} while (++rc < ct);
-			if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue;	/* Wrong encoding? */
-		}
-#endif
-		if (FF_USE_STRFUNC == 2 && dc == '\r') continue;	/* Strip \r off if needed */
-#if FF_LFN_UNICODE == 1	|| FF_LFN_UNICODE == 3	/* Output it in UTF-16/32 encoding */
-		if (FF_LFN_UNICODE == 1 && dc >= 0x10000) {	/* Out of BMP at UTF-16? */
-			*p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++;	/* Make and output high surrogate */
-			dc = 0xDC00 | (dc & 0x3FF);		/* Make low surrogate */
-		}
-		*p++ = (TCHAR)dc; nc++;
-		if (dc == '\n') break;	/* End of line? */
-#elif FF_LFN_UNICODE == 2		/* Output it in UTF-8 encoding */
-		if (dc < 0x80) {	/* 1-byte */
-			*p++ = (TCHAR)dc;
-			nc++;
-			if (dc == '\n') break;	/* End of line? */
-		} else {
-			if (dc < 0x800) {		/* 2-byte */
-				*p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F));
-				*p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
-				nc += 2;
-			} else {
-				if (dc < 0x10000) {	/* 3-byte */
-					*p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F));
-					*p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
-					*p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
-					nc += 3;
-				} else {			/* 4-byte */
-					*p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07));
-					*p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F));
-					*p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
-					*p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
-					nc += 4;
-				}
-			}
-		}
-#endif
-	}
-
-#else			/* Byte-by-byte without any conversion (ANSI/OEM API) */
-	len -= 1;	/* Make a room for the terminator */
-	while (nc < len) {
-		f_read(fp, s, 1, &rc);
-		if (rc != 1) break;
-		dc = s[0];
-		if (FF_USE_STRFUNC == 2 && dc == '\r') continue;
-		*p++ = (TCHAR)dc; nc++;
-		if (dc == '\n') break;
-	}
-#endif
-
-	*p = 0;		/* Terminate the string */
-	return nc ? buff : 0;	/* When no data read due to EOF or error, return with error. */
-}
-
-
-
-
-#if !FF_FS_READONLY
-#include <stdarg.h>
-/*-----------------------------------------------------------------------*/
-/* Put a Character to the File                                           */
-/*-----------------------------------------------------------------------*/
-
-typedef struct {	/* Putchar output buffer and work area */
-	FIL *fp;		/* Ptr to the writing file */
-	int idx, nchr;	/* Write index of buf[] (-1:error), number of encoding units written */
-#if FF_USE_LFN && FF_LFN_UNICODE == 1
-	WCHAR hs;
-#elif FF_USE_LFN && FF_LFN_UNICODE == 2
-	BYTE bs[4];
-	UINT wi, ct;
-#endif
-	BYTE buf[64];	/* Write buffer */
-} putbuff;
-
-
-static void putc_bfd (		/* Buffered write with code conversion */
-	putbuff* pb,
-	TCHAR c
-)
-{
-	UINT n;
-	int i, nc;
-#if FF_USE_LFN && FF_LFN_UNICODE
-	WCHAR hs, wc;
-#if FF_LFN_UNICODE == 2
-	DWORD dc;
-	TCHAR *tp;
-#endif
-#endif
-
-	if (FF_USE_STRFUNC == 2 && c == '\n') {	 /* LF -> CRLF conversion */
-		putc_bfd(pb, '\r');
-	}
-
-	i = pb->idx;			/* Write index of pb->buf[] */
-	if (i < 0) return;
-	nc = pb->nchr;			/* Write unit counter */
-
-#if FF_USE_LFN && FF_LFN_UNICODE
-#if FF_LFN_UNICODE == 1		/* UTF-16 input */
-	if (IsSurrogateH(c)) {
-		pb->hs = c; return;
-	}
-	hs = pb->hs; pb->hs = 0;
-	if (hs != 0) {
-		if (!IsSurrogateL(c)) hs = 0;
-	} else {
-		if (IsSurrogateL(c)) return;
-	}
-	wc = c;
-#elif FF_LFN_UNICODE == 2	/* UTF-8 input */
-	for (;;) {
-		if (pb->ct == 0) {	/* Out of multi-byte sequence? */
-			pb->bs[pb->wi = 0] = (BYTE)c;	/* Save 1st byte */
-			if ((BYTE)c < 0x80) break;					/* 1-byte? */
-			if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1;	/* 2-byte? */
-			if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2;	/* 3-byte? */
-			if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3;	/* 4-byte? */
-			return;
-		} else {				/* In the multi-byte sequence */
-			if (((BYTE)c & 0xC0) != 0x80) {	/* Broken sequence? */
-				pb->ct = 0; continue;
-			}
-			pb->bs[++pb->wi] = (BYTE)c;	/* Save the trailing byte */
-			if (--pb->ct == 0) break;	/* End of multi-byte sequence? */
-			return;
-		}
-	}
-	tp = (TCHAR*)pb->bs;
-	dc = tchar2uni(&tp);	/* UTF-8 ==> UTF-16 */
-	if (dc == 0xFFFFFFFF) return;
-	wc = (WCHAR)dc;
-	hs = (WCHAR)(dc >> 16);
-#elif FF_LFN_UNICODE == 3	/* UTF-32 input */
-	if (IsSurrogate(c) || c >= 0x110000) return;
-	if (c >= 0x10000) {
-		hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); 	/* Make high surrogate */
-		wc = 0xDC00 | (c & 0x3FF);					/* Make low surrogate */
-	} else {
-		hs = 0;
-		wc = (WCHAR)c;
-	}
-#endif
-
-#if FF_STRF_ENCODE == 1		/* Write a character in UTF-16LE */
-	if (hs != 0) {
-		st_word(&pb->buf[i], hs);
-		i += 2;
-		nc++;
-	}
-	st_word(&pb->buf[i], wc);
-	i += 2;
-#elif FF_STRF_ENCODE == 2	/* Write a character in UTF-16BE */
-	if (hs != 0) {
-		pb->buf[i++] = (BYTE)(hs >> 8);
-		pb->buf[i++] = (BYTE)hs;
-		nc++;
-	}
-	pb->buf[i++] = (BYTE)(wc >> 8);
-	pb->buf[i++] = (BYTE)wc;
-#elif FF_STRF_ENCODE == 3	/* Write it in UTF-8 */
-	if (hs != 0) {				/* 4-byte */
-		nc += 3;
-		hs = (hs & 0x3FF) + 0x40;
-		pb->buf[i++] = (BYTE)(0xF0 | hs >> 8);
-		pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F));
-		pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F));
-		pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F));
-	} else {
-		if (wc < 0x80) {		/* 1-byte */
-			pb->buf[i++] = (BYTE)wc;
-		} else {
-			if (wc < 0x800) {	/* 2-byte */
-				nc += 1;
-				pb->buf[i++] = (BYTE)(0xC0 | wc >> 6);
-			} else {			/* 3-byte */
-				nc += 2;
-				pb->buf[i++] = (BYTE)(0xE0 | wc >> 12);
-				pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F));
-			}
-			pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F));
-		}
-	}
-#else						/* Write it in ANSI/OEM */
-	if (hs != 0) return;
-	wc = ff_uni2oem(wc, CODEPAGE);	/* UTF-16 ==> ANSI/OEM */
-	if (wc == 0) return;
-	if (wc >= 0x100) {
-		pb->buf[i++] = (BYTE)(wc >> 8); nc++;
-	}
-	pb->buf[i++] = (BYTE)wc;
-#endif
-
-#else									/* ANSI/OEM input (without re-encode) */
-	pb->buf[i++] = (BYTE)c;
-#endif
-
-	if (i >= (int)(sizeof pb->buf) - 4) {	/* Write buffered characters to the file */
-		f_write(pb->fp, pb->buf, (UINT)i, &n);
-		i = (n == (UINT)i) ? 0 : -1;
-	}
-	pb->idx = i;
-	pb->nchr = nc + 1;
-}
-
-
-static int putc_flush (		/* Flush left characters in the buffer */
-	putbuff* pb
-)
-{
-	UINT nw;
-
-	if (   pb->idx >= 0	/* Flush buffered characters to the file */
-		&& f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK
-		&& (UINT)pb->idx == nw) return pb->nchr;
-	return EOF;
-}
-
-
-static void putc_init (		/* Initialize write buffer */
-	putbuff* pb,
-	FIL* fp
-)
-{
-	mem_set(pb, 0, sizeof (putbuff));
-	pb->fp = fp;
-}
-
-
-
-int f_putc (
-	TCHAR c,	/* A character to be output */
-	FIL* fp		/* Pointer to the file object */
-)
-{
-	putbuff pb;
-
-
-	putc_init(&pb, fp);
-	putc_bfd(&pb, c);	/* Put the character */
-	return putc_flush(&pb);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Put a String to the File                                              */
-/*-----------------------------------------------------------------------*/
-
-int f_puts (
-	const TCHAR* str,	/* Pointer to the string to be output */
-	FIL* fp				/* Pointer to the file object */
-)
-{
-	putbuff pb;
-
-
-	putc_init(&pb, fp);
-	while (*str) putc_bfd(&pb, *str++);		/* Put the string */
-	return putc_flush(&pb);
-}
-
-
-
-
-/*-----------------------------------------------------------------------*/
-/* Put a Formatted String to the File                                    */
-/*-----------------------------------------------------------------------*/
-
-int f_printf (
-	FIL* fp,			/* Pointer to the file object */
-	const TCHAR* fmt,	/* Pointer to the format string */
-	...					/* Optional arguments... */
-)
-{
-	va_list arp;
-	putbuff pb;
-	BYTE f, r;
-	UINT i, j, w;
-	DWORD v;
-	TCHAR c, d, str[32], *p;
-
-
-	putc_init(&pb, fp);
-
-	va_start(arp, fmt);
-
-	for (;;) {
-		c = *fmt++;
-		if (c == 0) break;			/* End of string */
-		if (c != '%') {				/* Non escape character */
-			putc_bfd(&pb, c);
-			continue;
-		}
-		w = f = 0;
-		c = *fmt++;
-		if (c == '0') {				/* Flag: '0' padding */
-			f = 1; c = *fmt++;
-		} else {
-			if (c == '-') {			/* Flag: left justified */
-				f = 2; c = *fmt++;
-			}
-		}
-		if (c == '*') {				/* Minimum width by argument */
-			w = va_arg(arp, int);
-			c = *fmt++;
-		} else {
-			while (IsDigit(c)) {	/* Minimum width */
-				w = w * 10 + c - '0';
-				c = *fmt++;
-			}
-		}
-		if (c == 'l' || c == 'L') {	/* Type prefix: Size is long int */
-			f |= 4; c = *fmt++;
-		}
-		if (c == 0) break;
-		d = c;
-		if (IsLower(d)) d -= 0x20;
-		switch (d) {				/* Atgument type is... */
-		case 'S' :					/* String */
-			p = va_arg(arp, TCHAR*);
-			for (j = 0; p[j]; j++) ;
-			if (!(f & 2)) {						/* Right padded */
-				while (j++ < w) putc_bfd(&pb, ' ') ;
-			}
-			while (*p) putc_bfd(&pb, *p++) ;		/* String body */
-			while (j++ < w) putc_bfd(&pb, ' ') ;	/* Left padded */
-			continue;
-
-		case 'C' :					/* Character */
-			putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue;
-
-		case 'B' :					/* Unsigned binary */
-			r = 2; break;
-
-		case 'O' :					/* Unsigned octal */
-			r = 8; break;
-
-		case 'D' :					/* Signed decimal */
-		case 'U' :					/* Unsigned decimal */
-			r = 10; break;
-
-		case 'X' :					/* Unsigned hexdecimal */
-			r = 16; break;
-
-		default:					/* Unknown type (pass-through) */
-			putc_bfd(&pb, c); continue;
-		}
-
-		/* Get an argument and put it in numeral */
-		v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int));
-		if (d == 'D' && (v & 0x80000000)) {
-			v = 0 - v;
-			f |= 8;
-		}
-		i = 0;
-		do {
-			d = (TCHAR)(v % r); v /= r;
-			if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
-			str[i++] = d + '0';
-		} while (v && i < sizeof str / sizeof *str);
-		if (f & 8) str[i++] = '-';
-		j = i; d = (f & 1) ? '0' : ' ';
-		if (!(f & 2)) {
-			while (j++ < w) putc_bfd(&pb, d);	/* Right pad */
-		}
-		do {
-			putc_bfd(&pb, str[--i]);			/* Number body */
-		} while (i);
-		while (j++ < w) putc_bfd(&pb, d);		/* Left pad */
-	}
-
-	va_end(arp);
-
-	return putc_flush(&pb);
-}
-
-#endif /* !FF_FS_READONLY */
-#endif /* FF_USE_STRFUNC */
-
-
-
-#if FF_CODE_PAGE == 0
-/*-----------------------------------------------------------------------*/
-/* Set Active Codepage for the Path Name                                 */
-/*-----------------------------------------------------------------------*/
-
-FRESULT f_setcp (
-	WORD cp		/* Value to be set as active code page */
-)
-{
-	static const WORD       validcp[] = {  437,   720,   737,   771,   775,   850,   852,   857,   860,   861,   862,   863,   864,   865,   866,   869,   932,   936,   949,   950, 0};
-	static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0};
-	UINT i;
-
-
-	for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ;	/* Find the code page */
-	if (validcp[i] != cp) return FR_INVALID_PARAMETER;	/* Not found? */
-
-	CodePage = cp;
-	if (cp >= 900) {	/* DBCS */
-		ExCvt = 0;
-		DbcTbl = tables[i];
-	} else {			/* SBCS */
-		ExCvt = tables[i];
-		DbcTbl = 0;
-	}
-	return FR_OK;
-}
-#endif	/* FF_CODE_PAGE == 0 */
-
+/*----------------------------------------------------------------------------/
+/  FatFs - Generic FAT Filesystem Module  R0.13c                              /
+/-----------------------------------------------------------------------------/
+/
+/ Copyright (C) 2018, ChaN, all right reserved.
+/
+/ FatFs module is an open source software. Redistribution and use of FatFs in
+/ source and binary forms, with or without modification, are permitted provided
+/ that the following condition is met:
+/
+/ 1. Redistributions of source code must retain the above copyright notice,
+/    this condition and the following disclaimer.
+/
+/ This software is provided by the copyright holder and contributors "AS IS"
+/ and any warranties related to this software are DISCLAIMED.
+/ The copyright owner or contributors be NOT LIABLE for any damages caused
+/ by use of this software.
+/
+/----------------------------------------------------------------------------*/
+
+
+#include "ff.h"			/* Declarations of FatFs API */
+#include "diskio.h"		/* Declarations of device I/O functions */
+
+
+/*--------------------------------------------------------------------------
+
+   Module Private Definitions
+
+---------------------------------------------------------------------------*/
+
+#if FF_DEFINED != 86604	/* Revision ID */
+#error Wrong include file (ff.h).
+#endif
+
+
+/* Limits and boundaries */
+#define MAX_DIR		0x200000		/* Max size of FAT directory */
+#define MAX_DIR_EX	0x10000000		/* Max size of exFAT directory */
+#define MAX_FAT12	0xFF5			/* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
+#define MAX_FAT16	0xFFF5			/* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
+#define MAX_FAT32	0x0FFFFFF5		/* Max FAT32 clusters (not specified, practical limit) */
+#define MAX_EXFAT	0x7FFFFFFD		/* Max exFAT clusters (differs from specs, implementation limit) */
+
+
+/* Character code support macros */
+#define IsUpper(c)		((c) >= 'A' && (c) <= 'Z')
+#define IsLower(c)		((c) >= 'a' && (c) <= 'z')
+#define IsDigit(c)		((c) >= '0' && (c) <= '9')
+#define IsSurrogate(c)	((c) >= 0xD800 && (c) <= 0xDFFF)
+#define IsSurrogateH(c)	((c) >= 0xD800 && (c) <= 0xDBFF)
+#define IsSurrogateL(c)	((c) >= 0xDC00 && (c) <= 0xDFFF)
+
+
+/* Additional file access control and file status flags for internal use */
+#define FA_SEEKEND	0x20	/* Seek to end of the file on file open */
+#define FA_MODIFIED	0x40	/* File has been modified */
+#define FA_DIRTY	0x80	/* FIL.buf[] needs to be written-back */
+
+
+/* Additional file attribute bits for internal use */
+#define AM_VOL		0x08	/* Volume label */
+#define AM_LFN		0x0F	/* LFN entry */
+#define AM_MASK		0x3F	/* Mask of defined bits */
+
+
+/* Name status flags in fn[11] */
+#define NSFLAG		11		/* Index of the name status byte */
+#define NS_LOSS		0x01	/* Out of 8.3 format */
+#define NS_LFN		0x02	/* Force to create LFN entry */
+#define NS_LAST		0x04	/* Last segment */
+#define NS_BODY		0x08	/* Lower case flag (body) */
+#define NS_EXT		0x10	/* Lower case flag (ext) */
+#define NS_DOT		0x20	/* Dot entry */
+#define NS_NOLFN	0x40	/* Do not find LFN */
+#define NS_NONAME	0x80	/* Not followed */
+
+
+/* exFAT directory entry types */
+#define	ET_BITMAP	0x81	/* Allocation bitmap */
+#define	ET_UPCASE	0x82	/* Up-case table */
+#define	ET_VLABEL	0x83	/* Volume label */
+#define	ET_FILEDIR	0x85	/* File and directory */
+#define	ET_STREAM	0xC0	/* Stream extension */
+#define	ET_FILENAME	0xC1	/* Name extension */
+
+
+/* FatFs refers the FAT structure as simple byte array instead of structure member
+/ because the C structure is not binary compatible between different platforms */
+
+#define BS_JmpBoot			0		/* x86 jump instruction (3-byte) */
+#define BS_OEMName			3		/* OEM name (8-byte) */
+#define BPB_BytsPerSec		11		/* Sector size [byte] (WORD) */
+#define BPB_SecPerClus		13		/* Cluster size [sector] (BYTE) */
+#define BPB_RsvdSecCnt		14		/* Size of reserved area [sector] (WORD) */
+#define BPB_NumFATs			16		/* Number of FATs (BYTE) */
+#define BPB_RootEntCnt		17		/* Size of root directory area for FAT [entry] (WORD) */
+#define BPB_TotSec16		19		/* Volume size (16-bit) [sector] (WORD) */
+#define BPB_Media			21		/* Media descriptor byte (BYTE) */
+#define BPB_FATSz16			22		/* FAT size (16-bit) [sector] (WORD) */
+#define BPB_SecPerTrk		24		/* Number of sectors per track for int13h [sector] (WORD) */
+#define BPB_NumHeads		26		/* Number of heads for int13h (WORD) */
+#define BPB_HiddSec			28		/* Volume offset from top of the drive (DWORD) */
+#define BPB_TotSec32		32		/* Volume size (32-bit) [sector] (DWORD) */
+#define BS_DrvNum			36		/* Physical drive number for int13h (BYTE) */
+#define BS_NTres			37		/* WindowsNT error flag (BYTE) */
+#define BS_BootSig			38		/* Extended boot signature (BYTE) */
+#define BS_VolID			39		/* Volume serial number (DWORD) */
+#define BS_VolLab			43		/* Volume label string (8-byte) */
+#define BS_FilSysType		54		/* Filesystem type string (8-byte) */
+#define BS_BootCode			62		/* Boot code (448-byte) */
+#define BS_55AA				510		/* Signature word (WORD) */
+
+#define BPB_FATSz32			36		/* FAT32: FAT size [sector] (DWORD) */
+#define BPB_ExtFlags32		40		/* FAT32: Extended flags (WORD) */
+#define BPB_FSVer32			42		/* FAT32: Filesystem version (WORD) */
+#define BPB_RootClus32		44		/* FAT32: Root directory cluster (DWORD) */
+#define BPB_FSInfo32		48		/* FAT32: Offset of FSINFO sector (WORD) */
+#define BPB_BkBootSec32		50		/* FAT32: Offset of backup boot sector (WORD) */
+#define BS_DrvNum32			64		/* FAT32: Physical drive number for int13h (BYTE) */
+#define BS_NTres32			65		/* FAT32: Error flag (BYTE) */
+#define BS_BootSig32		66		/* FAT32: Extended boot signature (BYTE) */
+#define BS_VolID32			67		/* FAT32: Volume serial number (DWORD) */
+#define BS_VolLab32			71		/* FAT32: Volume label string (8-byte) */
+#define BS_FilSysType32		82		/* FAT32: Filesystem type string (8-byte) */
+#define BS_BootCode32		90		/* FAT32: Boot code (420-byte) */
+
+#define BPB_ZeroedEx		11		/* exFAT: MBZ field (53-byte) */
+#define BPB_VolOfsEx		64		/* exFAT: Volume offset from top of the drive [sector] (QWORD) */
+#define BPB_TotSecEx		72		/* exFAT: Volume size [sector] (QWORD) */
+#define BPB_FatOfsEx		80		/* exFAT: FAT offset from top of the volume [sector] (DWORD) */
+#define BPB_FatSzEx			84		/* exFAT: FAT size [sector] (DWORD) */
+#define BPB_DataOfsEx		88		/* exFAT: Data offset from top of the volume [sector] (DWORD) */
+#define BPB_NumClusEx		92		/* exFAT: Number of clusters (DWORD) */
+#define BPB_RootClusEx		96		/* exFAT: Root directory start cluster (DWORD) */
+#define BPB_VolIDEx			100		/* exFAT: Volume serial number (DWORD) */
+#define BPB_FSVerEx			104		/* exFAT: Filesystem version (WORD) */
+#define BPB_VolFlagEx		106		/* exFAT: Volume flags (WORD) */
+#define BPB_BytsPerSecEx	108		/* exFAT: Log2 of sector size in unit of byte (BYTE) */
+#define BPB_SecPerClusEx	109		/* exFAT: Log2 of cluster size in unit of sector (BYTE) */
+#define BPB_NumFATsEx		110		/* exFAT: Number of FATs (BYTE) */
+#define BPB_DrvNumEx		111		/* exFAT: Physical drive number for int13h (BYTE) */
+#define BPB_PercInUseEx		112		/* exFAT: Percent in use (BYTE) */
+#define BPB_RsvdEx			113		/* exFAT: Reserved (7-byte) */
+#define BS_BootCodeEx		120		/* exFAT: Boot code (390-byte) */
+
+#define DIR_Name			0		/* Short file name (11-byte) */
+#define DIR_Attr			11		/* Attribute (BYTE) */
+#define DIR_NTres			12		/* Lower case flag (BYTE) */
+#define DIR_CrtTime10		13		/* Created time sub-second (BYTE) */
+#define DIR_CrtTime			14		/* Created time (DWORD) */
+#define DIR_LstAccDate		18		/* Last accessed date (WORD) */
+#define DIR_FstClusHI		20		/* Higher 16-bit of first cluster (WORD) */
+#define DIR_ModTime			22		/* Modified time (DWORD) */
+#define DIR_FstClusLO		26		/* Lower 16-bit of first cluster (WORD) */
+#define DIR_FileSize		28		/* File size (DWORD) */
+#define LDIR_Ord			0		/* LFN: LFN order and LLE flag (BYTE) */
+#define LDIR_Attr			11		/* LFN: LFN attribute (BYTE) */
+#define LDIR_Type			12		/* LFN: Entry type (BYTE) */
+#define LDIR_Chksum			13		/* LFN: Checksum of the SFN (BYTE) */
+#define LDIR_FstClusLO		26		/* LFN: MBZ field (WORD) */
+#define XDIR_Type			0		/* exFAT: Type of exFAT directory entry (BYTE) */
+#define XDIR_NumLabel		1		/* exFAT: Number of volume label characters (BYTE) */
+#define XDIR_Label			2		/* exFAT: Volume label (11-WORD) */
+#define XDIR_CaseSum		4		/* exFAT: Sum of case conversion table (DWORD) */
+#define XDIR_NumSec			1		/* exFAT: Number of secondary entries (BYTE) */
+#define XDIR_SetSum			2		/* exFAT: Sum of the set of directory entries (WORD) */
+#define XDIR_Attr			4		/* exFAT: File attribute (WORD) */
+#define XDIR_CrtTime		8		/* exFAT: Created time (DWORD) */
+#define XDIR_ModTime		12		/* exFAT: Modified time (DWORD) */
+#define XDIR_AccTime		16		/* exFAT: Last accessed time (DWORD) */
+#define XDIR_CrtTime10		20		/* exFAT: Created time subsecond (BYTE) */
+#define XDIR_ModTime10		21		/* exFAT: Modified time subsecond (BYTE) */
+#define XDIR_CrtTZ			22		/* exFAT: Created timezone (BYTE) */
+#define XDIR_ModTZ			23		/* exFAT: Modified timezone (BYTE) */
+#define XDIR_AccTZ			24		/* exFAT: Last accessed timezone (BYTE) */
+#define XDIR_GenFlags		33		/* exFAT: General secondary flags (BYTE) */
+#define XDIR_NumName		35		/* exFAT: Number of file name characters (BYTE) */
+#define XDIR_NameHash		36		/* exFAT: Hash of file name (WORD) */
+#define XDIR_ValidFileSize	40		/* exFAT: Valid file size (QWORD) */
+#define XDIR_FstClus		52		/* exFAT: First cluster of the file data (DWORD) */
+#define XDIR_FileSize		56		/* exFAT: File/Directory size (QWORD) */
+
+#define SZDIRE				32		/* Size of a directory entry */
+#define DDEM				0xE5	/* Deleted directory entry mark set to DIR_Name[0] */
+#define RDDEM				0x05	/* Replacement of the character collides with DDEM */
+#define LLEF				0x40	/* Last long entry flag in LDIR_Ord */
+
+#define FSI_LeadSig			0		/* FAT32 FSI: Leading signature (DWORD) */
+#define FSI_StrucSig		484		/* FAT32 FSI: Structure signature (DWORD) */
+#define FSI_Free_Count		488		/* FAT32 FSI: Number of free clusters (DWORD) */
+#define FSI_Nxt_Free		492		/* FAT32 FSI: Last allocated cluster (DWORD) */
+
+#define MBR_Table			446		/* MBR: Offset of partition table in the MBR */
+#define SZ_PTE				16		/* MBR: Size of a partition table entry */
+#define PTE_Boot			0		/* MBR PTE: Boot indicator */
+#define PTE_StHead			1		/* MBR PTE: Start head */
+#define PTE_StSec			2		/* MBR PTE: Start sector */
+#define PTE_StCyl			3		/* MBR PTE: Start cylinder */
+#define PTE_System			4		/* MBR PTE: System ID */
+#define PTE_EdHead			5		/* MBR PTE: End head */
+#define PTE_EdSec			6		/* MBR PTE: End sector */
+#define PTE_EdCyl			7		/* MBR PTE: End cylinder */
+#define PTE_StLba			8		/* MBR PTE: Start in LBA */
+#define PTE_SizLba			12		/* MBR PTE: Size in LBA */
+
+
+/* Post process on fatal error in the file operations */
+#define ABORT(fs, res)		{ fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
+
+
+/* Re-entrancy related */
+#if FF_FS_REENTRANT
+#if FF_USE_LFN == 1
+#error Static LFN work area cannot be used at thread-safe configuration
+#endif
+#define LEAVE_FF(fs, res)	{ unlock_fs(fs, res); return res; }
+#else
+#define LEAVE_FF(fs, res)	return res
+#endif
+
+
+/* Definitions of volume - physical location conversion */
+#if FF_MULTI_PARTITION
+#define LD2PD(vol) VolToPart[vol].pd	/* Get physical drive number */
+#define LD2PT(vol) VolToPart[vol].pt	/* Get partition index */
+#else
+#define LD2PD(vol) (BYTE)(vol)	/* Each logical drive is bound to the same physical drive number */
+#define LD2PT(vol) 0			/* Find first valid partition or in SFD */
+#endif
+
+
+/* Definitions of sector size */
+#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096)
+#error Wrong sector size configuration
+#endif
+#if FF_MAX_SS == FF_MIN_SS
+#define SS(fs)	((UINT)FF_MAX_SS)	/* Fixed sector size */
+#else
+#define SS(fs)	((fs)->ssize)	/* Variable sector size */
+#endif
+
+
+/* Timestamp */
+#if FF_FS_NORTC == 1
+#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31
+#error Invalid FF_FS_NORTC settings
+#endif
+#define GET_FATTIME()	((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16)
+#else
+#define GET_FATTIME()	get_fattime()
+#endif
+
+
+/* File lock controls */
+#if FF_FS_LOCK != 0
+#if FF_FS_READONLY
+#error FF_FS_LOCK must be 0 at read-only configuration
+#endif
+typedef struct {
+	FATFS *fs;		/* Object ID 1, volume (NULL:blank entry) */
+	DWORD clu;		/* Object ID 2, containing directory (0:root) */
+	DWORD ofs;		/* Object ID 3, offset in the directory */
+	WORD ctr;		/* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */
+} FILESEM;
+#endif
+
+
+/* SBCS up-case tables (\x80-\xFF) */
+#define TBL_CT437  {0x80,0x9A,0x45,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, \
+					0x41,0x49,0x4F,0x55,0xA5,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, \
+					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, \
+					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}
+#define TBL_CT720  {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, \
+					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, \
+					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, \
+					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}
+#define TBL_CT737  {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, \
+					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, \
+					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, \
+					0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
+					0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+#define TBL_CT771  {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, \
+					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, \
+					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,0xDC,0xDE,0xDE, \
+					0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+					0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF}
+#define TBL_CT775  {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, \
+					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, \
+					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, \
+					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}
+#define TBL_CT850  {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \
+					0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \
+					0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
+					0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+					0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
+					0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \
+					0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \
+					0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+#define TBL_CT852  {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,0xAC, \
+					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, \
+					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, \
+					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}
+#define TBL_CT855  {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, \
+					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, \
+					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, \
+					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}
+#define TBL_CT857  {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \
+					0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \
+					0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
+					0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+					0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
+					0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
+					0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \
+					0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}
+#define TBL_CT860  {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \
+					0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
+					0x86,0x8B,0x9F,0x96,0xA5,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, \
+					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, \
+					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}
+#define TBL_CT861  {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \
+					0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \
+					0xA4,0xA5,0xA6,0xA7,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, \
+					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, \
+					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}
+#define TBL_CT862  {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, \
+					0x41,0x49,0x4F,0x55,0xA5,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, \
+					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, \
+					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}
+#define TBL_CT863  {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \
+					0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \
+					0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
+					0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
+					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, \
+					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}
+#define TBL_CT864  {0x80,0x9A,0x45,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, \
+					0x41,0x49,0x4F,0x55,0xA5,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, \
+					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, \
+					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}
+#define TBL_CT865  {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, \
+					0x41,0x49,0x4F,0x55,0xA5,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, \
+					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, \
+					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}
+#define TBL_CT866  {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, \
+					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, \
+					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, \
+					0x90,0x91,0x92,0x93,0x94,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}
+#define TBL_CT869  {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,0x86,0x9C,0x8D,0x8F,0x90, \
+					0x91,0x90,0x92,0x95,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, \
+					0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
+					0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \
+					0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \
+					0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF}
+
+
+/* DBCS code range |----- 1st byte -----|  |----------- 2nd byte -----------| */
+#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00}
+#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00}
+#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE}
+#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00}
+
+
+/* Macros for table definitions */
+#define MERGE_2STR(a, b) a ## b
+#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp)
+
+
+
+
+/*--------------------------------------------------------------------------
+
+   Module Private Work Area
+
+---------------------------------------------------------------------------*/
+/* Remark: Variables defined here without initial value shall be guaranteed
+/  zero/null at start-up. If not, the linker option or start-up routine is
+/  not compliance with C standard. */
+
+/*--------------------------------*/
+/* File/Volume controls           */
+/*--------------------------------*/
+
+#if FF_VOLUMES < 1 || FF_VOLUMES > 10
+#error Wrong FF_VOLUMES setting
+#endif
+static FATFS* FatFs[FF_VOLUMES];	/* Pointer to the filesystem objects (logical drives) */
+static WORD Fsid;					/* Filesystem mount ID */
+
+#if FF_FS_RPATH != 0
+static BYTE CurrVol;				/* Current drive */
+#endif
+
+#if FF_FS_LOCK != 0
+static FILESEM Files[FF_FS_LOCK];	/* Open object lock semaphores */
+#endif
+
+#if FF_STR_VOLUME_ID
+#ifdef FF_VOLUME_STRS
+static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS};	/* Pre-defined volume ID */
+#endif
+#endif
+
+
+/*--------------------------------*/
+/* LFN/Directory working buffer   */
+/*--------------------------------*/
+
+#if FF_USE_LFN == 0		/* Non-LFN configuration */
+#if FF_FS_EXFAT
+#error LFN must be enabled when enable exFAT
+#endif
+#define DEF_NAMBUF
+#define INIT_NAMBUF(fs)
+#define FREE_NAMBUF()
+#define LEAVE_MKFS(res)	return res
+
+#else					/* LFN configurations */
+#if FF_MAX_LFN < 12 || FF_MAX_LFN > 255
+#error Wrong setting of FF_MAX_LFN
+#endif
+#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12
+#error Wrong setting of FF_LFN_BUF or FF_SFN_BUF
+#endif
+#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3
+#error Wrong setting of FF_LFN_UNICODE
+#endif
+static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30};	/* FAT: Offset of LFN characters in the directory entry */
+#define MAXDIRB(nc)	((nc + 44U) / 15 * SZDIRE)	/* exFAT: Size of directory entry block scratchpad buffer needed for the name length */
+
+#if FF_USE_LFN == 1		/* LFN enabled with static working buffer */
+#if FF_FS_EXFAT
+static BYTE	DirBuf[MAXDIRB(FF_MAX_LFN)];	/* Directory entry block scratchpad buffer */
+#endif
+static WCHAR LfnBuf[FF_MAX_LFN + 1];		/* LFN working buffer */
+#define DEF_NAMBUF
+#define INIT_NAMBUF(fs)
+#define FREE_NAMBUF()
+#define LEAVE_MKFS(res)	return res
+
+#elif FF_USE_LFN == 2 	/* LFN enabled with dynamic working buffer on the stack */
+#if FF_FS_EXFAT
+#define DEF_NAMBUF		WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)];	/* LFN working buffer and directory entry block scratchpad buffer */
+#define INIT_NAMBUF(fs)	{ (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; }
+#define FREE_NAMBUF()
+#else
+#define DEF_NAMBUF		WCHAR lbuf[FF_MAX_LFN+1];	/* LFN working buffer */
+#define INIT_NAMBUF(fs)	{ (fs)->lfnbuf = lbuf; }
+#define FREE_NAMBUF()
+#endif
+#define LEAVE_MKFS(res)	return res
+
+#elif FF_USE_LFN == 3 	/* LFN enabled with dynamic working buffer on the heap */
+#if FF_FS_EXFAT
+#define DEF_NAMBUF		WCHAR *lfn;	/* Pointer to LFN working buffer and directory entry block scratchpad buffer */
+#define INIT_NAMBUF(fs)	{ lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); }
+#define FREE_NAMBUF()	ff_memfree(lfn)
+#else
+#define DEF_NAMBUF		WCHAR *lfn;	/* Pointer to LFN working buffer */
+#define INIT_NAMBUF(fs)	{ lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; }
+#define FREE_NAMBUF()	ff_memfree(lfn)
+#endif
+#define LEAVE_MKFS(res)	{ if (!work) ff_memfree(buf); return res; }
+#define MAX_MALLOC	0x8000	/* Must be >=FF_MAX_SS */
+
+#else
+#error Wrong setting of FF_USE_LFN
+
+#endif	/* FF_USE_LFN == 1 */
+#endif	/* FF_USE_LFN == 0 */
+
+
+
+/*--------------------------------*/
+/* Code conversion tables         */
+/*--------------------------------*/
+
+#if FF_CODE_PAGE == 0		/* Run-time code page configuration */
+#define CODEPAGE CodePage
+static WORD CodePage;	/* Current code page */
+static const BYTE *ExCvt, *DbcTbl;	/* Pointer to current SBCS up-case table and DBCS code range table below */
+
+static const BYTE Ct437[] = TBL_CT437;
+static const BYTE Ct720[] = TBL_CT720;
+static const BYTE Ct737[] = TBL_CT737;
+static const BYTE Ct771[] = TBL_CT771;
+static const BYTE Ct775[] = TBL_CT775;
+static const BYTE Ct850[] = TBL_CT850;
+static const BYTE Ct852[] = TBL_CT852;
+static const BYTE Ct855[] = TBL_CT855;
+static const BYTE Ct857[] = TBL_CT857;
+static const BYTE Ct860[] = TBL_CT860;
+static const BYTE Ct861[] = TBL_CT861;
+static const BYTE Ct862[] = TBL_CT862;
+static const BYTE Ct863[] = TBL_CT863;
+static const BYTE Ct864[] = TBL_CT864;
+static const BYTE Ct865[] = TBL_CT865;
+static const BYTE Ct866[] = TBL_CT866;
+static const BYTE Ct869[] = TBL_CT869;
+static const BYTE Dc932[] = TBL_DC932;
+static const BYTE Dc936[] = TBL_DC936;
+static const BYTE Dc949[] = TBL_DC949;
+static const BYTE Dc950[] = TBL_DC950;
+
+#elif FF_CODE_PAGE < 900	/* Static code page configuration (SBCS) */
+#define CODEPAGE FF_CODE_PAGE
+static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE);
+
+#else					/* Static code page configuration (DBCS) */
+#define CODEPAGE FF_CODE_PAGE
+static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE);
+
+#endif
+
+
+
+
+/*--------------------------------------------------------------------------
+
+   Module Private Functions
+
+---------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* Load/Store multi-byte word in the FAT structure                       */
+/*-----------------------------------------------------------------------*/
+
+static WORD ld_word (const BYTE* ptr)	/*	 Load a 2-byte little-endian word */
+{
+	WORD rv;
+
+	rv = ptr[1];
+	rv = rv << 8 | ptr[0];
+	return rv;
+}
+
+static DWORD ld_dword (const BYTE* ptr)	/* Load a 4-byte little-endian word */
+{
+	DWORD rv;
+
+	rv = ptr[3];
+	rv = rv << 8 | ptr[2];
+	rv = rv << 8 | ptr[1];
+	rv = rv << 8 | ptr[0];
+	return rv;
+}
+
+#if FF_FS_EXFAT
+static QWORD ld_qword (const BYTE* ptr)	/* Load an 8-byte little-endian word */
+{
+	QWORD rv;
+
+	rv = ptr[7];
+	rv = rv << 8 | ptr[6];
+	rv = rv << 8 | ptr[5];
+	rv = rv << 8 | ptr[4];
+	rv = rv << 8 | ptr[3];
+	rv = rv << 8 | ptr[2];
+	rv = rv << 8 | ptr[1];
+	rv = rv << 8 | ptr[0];
+	return rv;
+}
+#endif
+
+#if !FF_FS_READONLY
+static void st_word (BYTE* ptr, WORD val)	/* Store a 2-byte word in little-endian */
+{
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val;
+}
+
+static void st_dword (BYTE* ptr, DWORD val)	/* Store a 4-byte word in little-endian */
+{
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val;
+}
+
+#if FF_FS_EXFAT
+static void st_qword (BYTE* ptr, QWORD val)	/* Store an 8-byte word in little-endian */
+{
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val; val >>= 8;
+	*ptr++ = (BYTE)val;
+}
+#endif
+#endif	/* !FF_FS_READONLY */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* String functions                                                      */
+/*-----------------------------------------------------------------------*/
+
+/* Copy memory to memory */
+static void mem_cpy (void* dst, const void* src, UINT cnt)
+{
+	BYTE *d = (BYTE*)dst;
+	const BYTE *s = (const BYTE*)src;
+
+	if (cnt != 0) {
+		do {
+			*d++ = *s++;
+		} while (--cnt);
+	}
+}
+
+
+/* Fill memory block */
+static void mem_set (void* dst, int val, UINT cnt)
+{
+	BYTE *d = (BYTE*)dst;
+
+	do {
+		*d++ = (BYTE)val;
+	} while (--cnt);
+}
+
+
+/* Compare memory block */
+static int mem_cmp (const void* dst, const void* src, UINT cnt)	/* ZR:same, NZ:different */
+{
+	const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
+	int r = 0;
+
+	do {
+		r = *d++ - *s++;
+	} while (--cnt && r == 0);
+
+	return r;
+}
+
+
+/* Check if chr is contained in the string */
+static int chk_chr (const char* str, int chr)	/* NZ:contained, ZR:not contained */
+{
+	while (*str && *str != chr) str++;
+	return *str;
+}
+
+
+/* Test if the character is DBC 1st byte */
+static int dbc_1st (BYTE c)
+{
+#if FF_CODE_PAGE == 0		/* Variable code page */
+	if (DbcTbl && c >= DbcTbl[0]) {
+		if (c <= DbcTbl[1]) return 1;					/* 1st byte range 1 */
+		if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1;	/* 1st byte range 2 */
+	}
+#elif FF_CODE_PAGE >= 900	/* DBCS fixed code page */
+	if (c >= DbcTbl[0]) {
+		if (c <= DbcTbl[1]) return 1;
+		if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1;
+	}
+#else						/* SBCS fixed code page */
+	if (c != 0) return 0;	/* Always false */
+#endif
+	return 0;
+}
+
+
+/* Test if the character is DBC 2nd byte */
+static int dbc_2nd (BYTE c)
+{
+#if FF_CODE_PAGE == 0		/* Variable code page */
+	if (DbcTbl && c >= DbcTbl[4]) {
+		if (c <= DbcTbl[5]) return 1;					/* 2nd byte range 1 */
+		if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1;	/* 2nd byte range 2 */
+		if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1;	/* 2nd byte range 3 */
+	}
+#elif FF_CODE_PAGE >= 900	/* DBCS fixed code page */
+	if (c >= DbcTbl[4]) {
+		if (c <= DbcTbl[5]) return 1;
+		if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1;
+		if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1;
+	}
+#else						/* SBCS fixed code page */
+	if (c != 0) return 0;	/* Always false */
+#endif
+	return 0;
+}
+
+
+#if FF_USE_LFN
+
+/* Get a character from TCHAR string in defined API encodeing */
+static DWORD tchar2uni (	/* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */
+	const TCHAR** str		/* Pointer to pointer to TCHAR string in configured encoding */
+)
+{
+	DWORD uc;
+	const TCHAR *p = *str;
+
+#if FF_LFN_UNICODE == 1		/* UTF-16 input */
+	WCHAR wc;
+
+	uc = *p++;	/* Get a unit */
+	if (IsSurrogate(uc)) {	/* Surrogate? */
+		wc = *p++;		/* Get low surrogate */
+		if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF;	/* Wrong surrogate? */
+		uc = uc << 16 | wc;
+	}
+
+#elif FF_LFN_UNICODE == 2	/* UTF-8 input */
+	BYTE b;
+	int nf;
+
+	uc = (BYTE)*p++;	/* Get a unit */
+	if (uc & 0x80) {	/* Multiple byte code? */
+		if ((uc & 0xE0) == 0xC0) {	/* 2-byte sequence? */
+			uc &= 0x1F; nf = 1;
+		} else {
+			if ((uc & 0xF0) == 0xE0) {	/* 3-byte sequence? */
+				uc &= 0x0F; nf = 2;
+			} else {
+				if ((uc & 0xF8) == 0xF0) {	/* 4-byte sequence? */
+					uc &= 0x07; nf = 3;
+				} else {					/* Wrong sequence */
+					return 0xFFFFFFFF;
+				}
+			}
+		}
+		do {	/* Get trailing bytes */
+			b = (BYTE)*p++;
+			if ((b & 0xC0) != 0x80) return 0xFFFFFFFF;	/* Wrong sequence? */
+			uc = uc << 6 | (b & 0x3F);
+		} while (--nf != 0);
+		if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF;	/* Wrong code? */
+		if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF);	/* Make a surrogate pair if needed */
+	}
+
+#elif FF_LFN_UNICODE == 3	/* UTF-32 input */
+	uc = (TCHAR)*p++;	/* Get a unit */
+	if (uc >= 0x110000) return 0xFFFFFFFF;	/* Wrong code? */
+	if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF);	/* Make a surrogate pair if needed */
+
+#else		/* ANSI/OEM input */
+	BYTE b;
+	WCHAR wc;
+
+	wc = (BYTE)*p++;			/* Get a byte */
+	if (dbc_1st((BYTE)wc)) {	/* Is it a DBC 1st byte? */
+		b = (BYTE)*p++;			/* Get 2nd byte */
+		if (!dbc_2nd(b)) return 0xFFFFFFFF;	/* Invalid code? */
+		wc = (wc << 8) + b;		/* Make a DBC */
+	}
+	if (wc != 0) {
+		wc = ff_oem2uni(wc, CODEPAGE);	/* ANSI/OEM ==> Unicode */
+		if (wc == 0) return 0xFFFFFFFF;	/* Invalid code? */
+	}
+	uc = wc;
+
+#endif
+	*str = p;	/* Next read pointer */
+	return uc;
+}
+
+
+/* Output a TCHAR string in defined API encoding */
+static BYTE put_utf (	/* Returns number of encoding units written (0:buffer overflow or wrong encoding) */
+	DWORD chr,	/* UTF-16 encoded character (Double encoding unit char if >=0x10000) */
+	TCHAR* buf,	/* Output buffer */
+	UINT szb	/* Size of the buffer */
+)
+{
+#if FF_LFN_UNICODE == 1	/* UTF-16 output */
+	WCHAR hs, wc;
+
+	hs = (WCHAR)(chr >> 16);
+	wc = (WCHAR)chr;
+	if (hs == 0) {	/* Single encoding unit? */
+		if (szb < 1 || IsSurrogate(wc)) return 0;	/* Buffer overflow or wrong code? */
+		*buf = wc;
+		return 1;
+	}
+	if (szb < 2 || !IsSurrogateH(hs) || !IsSurrogateL(wc)) return 0;	/* Buffer overflow or wrong surrogate? */
+	*buf++ = hs;
+	*buf++ = wc;
+	return 2;
+
+#elif FF_LFN_UNICODE == 2	/* UTF-8 output */
+	DWORD hc;
+
+	if (chr < 0x80) {	/* Single byte code? */
+		if (szb < 1) return 0;	/* Buffer overflow? */
+		*buf = (TCHAR)chr;
+		return 1;
+	}
+	if (chr < 0x800) {	/* 2-byte sequence? */
+		if (szb < 2) return 0;	/* Buffer overflow? */
+		*buf++ = (TCHAR)(0xC0 | (chr >> 6 & 0x1F));
+		*buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
+		return 2;
+	}
+	if (chr < 0x10000) {	/* 3-byte sequence? */
+		if (szb < 3 || IsSurrogate(chr)) return 0;	/* Buffer overflow or wrong code? */
+		*buf++ = (TCHAR)(0xE0 | (chr >> 12 & 0x0F));
+		*buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F));
+		*buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
+		return 3;
+	}
+	/* 4-byte sequence */
+	if (szb < 4) return 0;	/* Buffer overflow? */
+	hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6;	/* Get high 10 bits */
+	chr = (chr & 0xFFFF) - 0xDC00;					/* Get low 10 bits */
+	if (hc >= 0x100000 || chr >= 0x400) return 0;	/* Wrong surrogate? */
+	chr = (hc | chr) + 0x10000;
+	*buf++ = (TCHAR)(0xF0 | (chr >> 18 & 0x07));
+	*buf++ = (TCHAR)(0x80 | (chr >> 12 & 0x3F));
+	*buf++ = (TCHAR)(0x80 | (chr >> 6 & 0x3F));
+	*buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F));
+	return 4;
+
+#elif FF_LFN_UNICODE == 3	/* UTF-32 output */
+	DWORD hc;
+
+	if (szb < 1) return 0;	/* Buffer overflow? */
+	if (chr >= 0x10000) {	/* Out of BMP? */
+		hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6;	/* Get high 10 bits */
+		chr = (chr & 0xFFFF) - 0xDC00;					/* Get low 10 bits */
+		if (hc >= 0x100000 || chr >= 0x400) return 0;	/* Wrong surrogate? */
+		chr = (hc | chr) + 0x10000;
+	}
+	*buf++ = (TCHAR)chr;
+	return 1;
+
+#else						/* ANSI/OEM output */
+	WCHAR wc;
+
+	wc = ff_uni2oem(chr, CODEPAGE);
+	if (wc >= 0x100) {	/* Is this a DBC? */
+		if (szb < 2) return 0;
+		*buf++ = (char)(wc >> 8);	/* Store DBC 1st byte */
+		*buf++ = (TCHAR)wc;			/* Store DBC 2nd byte */
+		return 2;
+	}
+	if (wc == 0 || szb < 1) return 0;	/* Invalid char or buffer overflow? */
+	*buf++ = (TCHAR)wc;					/* Store the character */
+	return 1;
+#endif
+}
+#endif	/* FF_USE_LFN */
+
+
+#if FF_FS_REENTRANT
+/*-----------------------------------------------------------------------*/
+/* Request/Release grant to access the volume                            */
+/*-----------------------------------------------------------------------*/
+static int lock_fs (		/* 1:Ok, 0:timeout */
+	FATFS* fs		/* Filesystem object */
+)
+{
+	return ff_req_grant(fs->sobj);
+}
+
+
+static void unlock_fs (
+	FATFS* fs,		/* Filesystem object */
+	FRESULT res		/* Result code to be returned */
+)
+{
+	if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) {
+		ff_rel_grant(fs->sobj);
+	}
+}
+
+#endif
+
+
+
+#if FF_FS_LOCK != 0
+/*-----------------------------------------------------------------------*/
+/* File lock control functions                                           */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT chk_lock (	/* Check if the file can be accessed */
+	DIR* dp,		/* Directory object pointing the file to be checked */
+	int acc			/* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */
+)
+{
+	UINT i, be;
+
+	/* Search open object table for the object */
+	be = 0;
+	for (i = 0; i < FF_FS_LOCK; i++) {
+		if (Files[i].fs) {	/* Existing entry */
+			if (Files[i].fs == dp->obj.fs &&	 	/* Check if the object matches with an open object */
+				Files[i].clu == dp->obj.sclust &&
+				Files[i].ofs == dp->dptr) break;
+		} else {			/* Blank entry */
+			be = 1;
+		}
+	}
+	if (i == FF_FS_LOCK) {	/* The object has not been opened */
+		return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK;	/* Is there a blank entry for new object? */
+	}
+
+	/* The object was opened. Reject any open against writing file and all write mode open */
+	return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK;
+}
+
+
+static int enq_lock (void)	/* Check if an entry is available for a new object */
+{
+	UINT i;
+
+	for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ;
+	return (i == FF_FS_LOCK) ? 0 : 1;
+}
+
+
+static UINT inc_lock (	/* Increment object open counter and returns its index (0:Internal error) */
+	DIR* dp,	/* Directory object pointing the file to register or increment */
+	int acc		/* Desired access (0:Read, 1:Write, 2:Delete/Rename) */
+)
+{
+	UINT i;
+
+
+	for (i = 0; i < FF_FS_LOCK; i++) {	/* Find the object */
+		if (Files[i].fs == dp->obj.fs &&
+			Files[i].clu == dp->obj.sclust &&
+			Files[i].ofs == dp->dptr) break;
+	}
+
+	if (i == FF_FS_LOCK) {				/* Not opened. Register it as new. */
+		for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ;
+		if (i == FF_FS_LOCK) return 0;	/* No free entry to register (int err) */
+		Files[i].fs = dp->obj.fs;
+		Files[i].clu = dp->obj.sclust;
+		Files[i].ofs = dp->dptr;
+		Files[i].ctr = 0;
+	}
+
+	if (acc >= 1 && Files[i].ctr) return 0;	/* Access violation (int err) */
+
+	Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1;	/* Set semaphore value */
+
+	return i + 1;	/* Index number origin from 1 */
+}
+
+
+static FRESULT dec_lock (	/* Decrement object open counter */
+	UINT i			/* Semaphore index (1..) */
+)
+{
+	WORD n;
+	FRESULT res;
+
+
+	if (--i < FF_FS_LOCK) {	/* Index number origin from 0 */
+		n = Files[i].ctr;
+		if (n == 0x100) n = 0;		/* If write mode open, delete the entry */
+		if (n > 0) n--;				/* Decrement read mode open count */
+		Files[i].ctr = n;
+		if (n == 0) Files[i].fs = 0;	/* Delete the entry if open count gets zero */
+		res = FR_OK;
+	} else {
+		res = FR_INT_ERR;			/* Invalid index nunber */
+	}
+	return res;
+}
+
+
+static void clear_lock (	/* Clear lock entries of the volume */
+	FATFS *fs
+)
+{
+	UINT i;
+
+	for (i = 0; i < FF_FS_LOCK; i++) {
+		if (Files[i].fs == fs) Files[i].fs = 0;
+	}
+}
+
+#endif	/* FF_FS_LOCK != 0 */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Move/Flush disk access window in the filesystem object                */
+/*-----------------------------------------------------------------------*/
+#if !FF_FS_READONLY
+static FRESULT sync_window (	/* Returns FR_OK or FR_DISK_ERR */
+	FATFS* fs			/* Filesystem object */
+)
+{
+	FRESULT res = FR_OK;
+
+
+	if (fs->wflag) {	/* Is the disk access window dirty */
+		if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) {	/* Write back the window */
+			fs->wflag = 0;	/* Clear window dirty flag */
+			if (fs->winsect - fs->fatbase < fs->fsize) {	/* Is it in the 1st FAT? */
+				if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1);	/* Reflect it to 2nd FAT if needed */
+			}
+		} else {
+			res = FR_DISK_ERR;
+		}
+	}
+	return res;
+}
+#endif
+
+
+static FRESULT move_window (	/* Returns FR_OK or FR_DISK_ERR */
+	FATFS* fs,			/* Filesystem object */
+	DWORD sector		/* Sector number to make appearance in the fs->win[] */
+)
+{
+	FRESULT res = FR_OK;
+
+
+	if (sector != fs->winsect) {	/* Window offset changed? */
+#if !FF_FS_READONLY
+		res = sync_window(fs);		/* Write-back changes */
+#endif
+		if (res == FR_OK) {			/* Fill sector window with new data */
+			if (disk_read(fs->pdrv, fs->win, sector, 1) != RES_OK) {
+				sector = 0xFFFFFFFF;	/* Invalidate window if read data is not valid */
+				res = FR_DISK_ERR;
+			}
+			fs->winsect = sector;
+		}
+	}
+	return res;
+}
+
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Synchronize filesystem and data on the storage                        */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT sync_fs (	/* Returns FR_OK or FR_DISK_ERR */
+	FATFS* fs		/* Filesystem object */
+)
+{
+	FRESULT res;
+
+
+	res = sync_window(fs);
+	if (res == FR_OK) {
+		if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {	/* FAT32: Update FSInfo sector if needed */
+			/* Create FSInfo structure */
+			mem_set(fs->win, 0, sizeof fs->win);
+			st_word(fs->win + BS_55AA, 0xAA55);
+			st_dword(fs->win + FSI_LeadSig, 0x41615252);
+			st_dword(fs->win + FSI_StrucSig, 0x61417272);
+			st_dword(fs->win + FSI_Free_Count, fs->free_clst);
+			st_dword(fs->win + FSI_Nxt_Free, fs->last_clst);
+			/* Write it into the FSInfo sector */
+			fs->winsect = fs->volbase + 1;
+			disk_write(fs->pdrv, fs->win, fs->winsect, 1);
+			fs->fsi_flag = 0;
+		}
+		/* Make sure that no pending write process in the lower layer */
+		if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR;
+	}
+
+	return res;
+}
+
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get physical sector number from cluster number                        */
+/*-----------------------------------------------------------------------*/
+
+static DWORD clst2sect (	/* !=0:Sector number, 0:Failed (invalid cluster#) */
+	FATFS* fs,		/* Filesystem object */
+	DWORD clst		/* Cluster# to be converted */
+)
+{
+	clst -= 2;		/* Cluster number is origin from 2 */
+	if (clst >= fs->n_fatent - 2) return 0;		/* Is it invalid cluster number? */
+	return fs->database + fs->csize * clst;		/* Start sector number of the cluster */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT access - Read value of a FAT entry                                */
+/*-----------------------------------------------------------------------*/
+
+static DWORD get_fat (		/* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */
+	FFOBJID* obj,	/* Corresponding object */
+	DWORD clst		/* Cluster number to get the value */
+)
+{
+	UINT wc, bc;
+	DWORD val;
+	FATFS *fs = obj->fs;
+
+
+	if (clst < 2 || clst >= fs->n_fatent) {	/* Check if in valid range */
+		val = 1;	/* Internal error */
+
+	} else {
+		val = 0xFFFFFFFF;	/* Default value falls on disk error */
+
+		switch (fs->fs_type) {
+		case FS_FAT12 :
+			bc = (UINT)clst; bc += bc / 2;
+			if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
+			wc = fs->win[bc++ % SS(fs)];		/* Get 1st byte of the entry */
+			if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
+			wc |= fs->win[bc % SS(fs)] << 8;	/* Merge 2nd byte of the entry */
+			val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF);	/* Adjust bit position */
+			break;
+
+		case FS_FAT16 :
+			if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break;
+			val = ld_word(fs->win + clst * 2 % SS(fs));		/* Simple WORD array */
+			break;
+
+		case FS_FAT32 :
+			if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
+			val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF;	/* Simple DWORD array but mask out upper 4 bits */
+			break;
+#if FF_FS_EXFAT
+		case FS_EXFAT :
+			if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) {	/* Object except root dir must have valid data length */
+				DWORD cofs = clst - obj->sclust;	/* Offset from start cluster */
+				DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize;	/* Number of clusters - 1 */
+
+				if (obj->stat == 2 && cofs <= clen) {	/* Is it a contiguous chain? */
+					val = (cofs == clen) ? 0x7FFFFFFF : clst + 1;	/* No data on the FAT, generate the value */
+					break;
+				}
+				if (obj->stat == 3 && cofs < obj->n_cont) {	/* Is it in the 1st fragment? */
+					val = clst + 1; 	/* Generate the value */
+					break;
+				}
+				if (obj->stat != 2) {	/* Get value from FAT if FAT chain is valid */
+					if (obj->n_frag != 0) {	/* Is it on the growing edge? */
+						val = 0x7FFFFFFF;	/* Generate EOC */
+					} else {
+						if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
+						val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF;
+					}
+					break;
+				}
+			}
+			/* go to default */
+#endif
+		default:
+			val = 1;	/* Internal error */
+		}
+	}
+
+	return val;
+}
+
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* FAT access - Change value of a FAT entry                              */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT put_fat (	/* FR_OK(0):succeeded, !=0:error */
+	FATFS* fs,		/* Corresponding filesystem object */
+	DWORD clst,		/* FAT index number (cluster number) to be changed */
+	DWORD val		/* New value to be set to the entry */
+)
+{
+	UINT bc;
+	BYTE *p;
+	FRESULT res = FR_INT_ERR;
+
+
+	if (clst >= 2 && clst < fs->n_fatent) {	/* Check if in valid range */
+		switch (fs->fs_type) {
+		case FS_FAT12 :
+			bc = (UINT)clst; bc += bc / 2;	/* bc: byte offset of the entry */
+			res = move_window(fs, fs->fatbase + (bc / SS(fs)));
+			if (res != FR_OK) break;
+			p = fs->win + bc++ % SS(fs);
+			*p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val;		/* Put 1st byte */
+			fs->wflag = 1;
+			res = move_window(fs, fs->fatbase + (bc / SS(fs)));
+			if (res != FR_OK) break;
+			p = fs->win + bc % SS(fs);
+			*p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F));	/* Put 2nd byte */
+			fs->wflag = 1;
+			break;
+
+		case FS_FAT16 :
+			res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
+			if (res != FR_OK) break;
+			st_word(fs->win + clst * 2 % SS(fs), (WORD)val);	/* Simple WORD array */
+			fs->wflag = 1;
+			break;
+
+		case FS_FAT32 :
+#if FF_FS_EXFAT
+		case FS_EXFAT :
+#endif
+			res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
+			if (res != FR_OK) break;
+			if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
+				val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000);
+			}
+			st_dword(fs->win + clst * 4 % SS(fs), val);
+			fs->wflag = 1;
+			break;
+		}
+	}
+	return res;
+}
+
+#endif /* !FF_FS_READONLY */
+
+
+
+
+#if FF_FS_EXFAT && !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* exFAT: Accessing FAT and Allocation Bitmap                            */
+/*-----------------------------------------------------------------------*/
+
+/*--------------------------------------*/
+/* Find a contiguous free cluster block */
+/*--------------------------------------*/
+
+static DWORD find_bitmap (	/* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */
+	FATFS* fs,	/* Filesystem object */
+	DWORD clst,	/* Cluster number to scan from */
+	DWORD ncl	/* Number of contiguous clusters to find (1..) */
+)
+{
+	BYTE bm, bv;
+	UINT i;
+	DWORD val, scl, ctr;
+
+
+	clst -= 2;	/* The first bit in the bitmap corresponds to cluster #2 */
+	if (clst >= fs->n_fatent - 2) clst = 0;
+	scl = val = clst; ctr = 0;
+	for (;;) {
+		if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF;
+		i = val / 8 % SS(fs); bm = 1 << (val % 8);
+		do {
+			do {
+				bv = fs->win[i] & bm; bm <<= 1;		/* Get bit value */
+				if (++val >= fs->n_fatent - 2) {	/* Next cluster (with wrap-around) */
+					val = 0; bm = 0; i = SS(fs);
+				}
+				if (bv == 0) {	/* Is it a free cluster? */
+					if (++ctr == ncl) return scl + 2;	/* Check if run length is sufficient for required */
+				} else {
+					scl = val; ctr = 0;		/* Encountered a cluster in-use, restart to scan */
+				}
+				if (val == clst) return 0;	/* All cluster scanned? */
+			} while (bm != 0);
+			bm = 1;
+		} while (++i < SS(fs));
+	}
+}
+
+
+/*----------------------------------------*/
+/* Set/Clear a block of allocation bitmap */
+/*----------------------------------------*/
+
+static FRESULT change_bitmap (
+	FATFS* fs,	/* Filesystem object */
+	DWORD clst,	/* Cluster number to change from */
+	DWORD ncl,	/* Number of clusters to be changed */
+	int bv		/* bit value to be set (0 or 1) */
+)
+{
+	BYTE bm;
+	UINT i;
+	DWORD sect;
+
+
+	clst -= 2;	/* The first bit corresponds to cluster #2 */
+	sect = fs->bitbase + clst / 8 / SS(fs);	/* Sector address */
+	i = clst / 8 % SS(fs);					/* Byte offset in the sector */
+	bm = 1 << (clst % 8);					/* Bit mask in the byte */
+	for (;;) {
+		if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
+		do {
+			do {
+				if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR;	/* Is the bit expected value? */
+				fs->win[i] ^= bm;	/* Flip the bit */
+				fs->wflag = 1;
+				if (--ncl == 0) return FR_OK;	/* All bits processed? */
+			} while (bm <<= 1);		/* Next bit */
+			bm = 1;
+		} while (++i < SS(fs));		/* Next byte */
+		i = 0;
+	}
+}
+
+
+/*---------------------------------------------*/
+/* Fill the first fragment of the FAT chain    */
+/*---------------------------------------------*/
+
+static FRESULT fill_first_frag (
+	FFOBJID* obj	/* Pointer to the corresponding object */
+)
+{
+	FRESULT res;
+	DWORD cl, n;
+
+
+	if (obj->stat == 3) {	/* Has the object been changed 'fragmented' in this session? */
+		for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) {	/* Create cluster chain on the FAT */
+			res = put_fat(obj->fs, cl, cl + 1);
+			if (res != FR_OK) return res;
+		}
+		obj->stat = 0;	/* Change status 'FAT chain is valid' */
+	}
+	return FR_OK;
+}
+
+
+/*---------------------------------------------*/
+/* Fill the last fragment of the FAT chain     */
+/*---------------------------------------------*/
+
+static FRESULT fill_last_frag (
+	FFOBJID* obj,	/* Pointer to the corresponding object */
+	DWORD lcl,		/* Last cluster of the fragment */
+	DWORD term		/* Value to set the last FAT entry */
+)
+{
+	FRESULT res;
+
+
+	while (obj->n_frag > 0) {	/* Create the chain of last fragment */
+		res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term);
+		if (res != FR_OK) return res;
+		obj->n_frag--;
+	}
+	return FR_OK;
+}
+
+#endif	/* FF_FS_EXFAT && !FF_FS_READONLY */
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* FAT handling - Remove a cluster chain                                 */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT remove_chain (	/* FR_OK(0):succeeded, !=0:error */
+	FFOBJID* obj,		/* Corresponding object */
+	DWORD clst,			/* Cluster to remove a chain from */
+	DWORD pclst			/* Previous cluster of clst (0 if entire chain) */
+)
+{
+	FRESULT res = FR_OK;
+	DWORD nxt;
+	FATFS *fs = obj->fs;
+#if FF_FS_EXFAT || FF_USE_TRIM
+	DWORD scl = clst, ecl = clst;
+#endif
+#if FF_USE_TRIM
+	DWORD rt[2];
+#endif
+
+	if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR;	/* Check if in valid range */
+
+	/* Mark the previous cluster 'EOC' on the FAT if it exists */
+	if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) {
+		res = put_fat(fs, pclst, 0xFFFFFFFF);
+		if (res != FR_OK) return res;
+	}
+
+	/* Remove the chain */
+	do {
+		nxt = get_fat(obj, clst);			/* Get cluster status */
+		if (nxt == 0) break;				/* Empty cluster? */
+		if (nxt == 1) return FR_INT_ERR;	/* Internal error? */
+		if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error? */
+		if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {
+			res = put_fat(fs, clst, 0);		/* Mark the cluster 'free' on the FAT */
+			if (res != FR_OK) return res;
+		}
+		if (fs->free_clst < fs->n_fatent - 2) {	/* Update FSINFO */
+			fs->free_clst++;
+			fs->fsi_flag |= 1;
+		}
+#if FF_FS_EXFAT || FF_USE_TRIM
+		if (ecl + 1 == nxt) {	/* Is next cluster contiguous? */
+			ecl = nxt;
+		} else {				/* End of contiguous cluster block */
+#if FF_FS_EXFAT
+			if (fs->fs_type == FS_EXFAT) {
+				res = change_bitmap(fs, scl, ecl - scl + 1, 0);	/* Mark the cluster block 'free' on the bitmap */
+				if (res != FR_OK) return res;
+			}
+#endif
+#if FF_USE_TRIM
+			rt[0] = clst2sect(fs, scl);					/* Start of data area freed */
+			rt[1] = clst2sect(fs, ecl) + fs->csize - 1;	/* End of data area freed */
+			disk_ioctl(fs->pdrv, CTRL_TRIM, rt);		/* Inform device the data in the block is no longer needed */
+#endif
+			scl = ecl = nxt;
+		}
+#endif
+		clst = nxt;					/* Next cluster */
+	} while (clst < fs->n_fatent);	/* Repeat while not the last link */
+
+#if FF_FS_EXFAT
+	/* Some post processes for chain status */
+	if (fs->fs_type == FS_EXFAT) {
+		if (pclst == 0) {	/* Has the entire chain been removed? */
+			obj->stat = 0;		/* Change the chain status 'initial' */
+		} else {
+			if (obj->stat == 0) {	/* Is it a fragmented chain from the beginning of this session? */
+				clst = obj->sclust;		/* Follow the chain to check if it gets contiguous */
+				while (clst != pclst) {
+					nxt = get_fat(obj, clst);
+					if (nxt < 2) return FR_INT_ERR;
+					if (nxt == 0xFFFFFFFF) return FR_DISK_ERR;
+					if (nxt != clst + 1) break;	/* Not contiguous? */
+					clst++;
+				}
+				if (clst == pclst) {	/* Has the chain got contiguous again? */
+					obj->stat = 2;		/* Change the chain status 'contiguous' */
+				}
+			} else {
+				if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) {	/* Was the chain fragmented in this session and got contiguous again? */
+					obj->stat = 2;	/* Change the chain status 'contiguous' */
+				}
+			}
+		}
+	}
+#endif
+	return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT handling - Stretch a chain or Create a new chain                  */
+/*-----------------------------------------------------------------------*/
+
+static DWORD create_chain (	/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */
+	FFOBJID* obj,		/* Corresponding object */
+	DWORD clst			/* Cluster# to stretch, 0:Create a new chain */
+)
+{
+	DWORD cs, ncl, scl;
+	FRESULT res;
+	FATFS *fs = obj->fs;
+
+
+	if (clst == 0) {	/* Create a new chain */
+		scl = fs->last_clst;				/* Suggested cluster to start to find */
+		if (scl == 0 || scl >= fs->n_fatent) scl = 1;
+	}
+	else {				/* Stretch a chain */
+		cs = get_fat(obj, clst);			/* Check the cluster status */
+		if (cs < 2) return 1;				/* Test for insanity */
+		if (cs == 0xFFFFFFFF) return cs;	/* Test for disk error */
+		if (cs < fs->n_fatent) return cs;	/* It is already followed by next cluster */
+		scl = clst;							/* Cluster to start to find */
+	}
+	if (fs->free_clst == 0) return 0;		/* No free cluster */
+
+#if FF_FS_EXFAT
+	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
+		ncl = find_bitmap(fs, scl, 1);				/* Find a free cluster */
+		if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl;	/* No free cluster or hard error? */
+		res = change_bitmap(fs, ncl, 1, 1);			/* Mark the cluster 'in use' */
+		if (res == FR_INT_ERR) return 1;
+		if (res == FR_DISK_ERR) return 0xFFFFFFFF;
+		if (clst == 0) {							/* Is it a new chain? */
+			obj->stat = 2;							/* Set status 'contiguous' */
+		} else {									/* It is a stretched chain */
+			if (obj->stat == 2 && ncl != scl + 1) {	/* Is the chain got fragmented? */
+				obj->n_cont = scl - obj->sclust;	/* Set size of the contiguous part */
+				obj->stat = 3;						/* Change status 'just fragmented' */
+			}
+		}
+		if (obj->stat != 2) {	/* Is the file non-contiguous? */
+			if (ncl == clst + 1) {	/* Is the cluster next to previous one? */
+				obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2;	/* Increment size of last framgent */
+			} else {				/* New fragment */
+				if (obj->n_frag == 0) obj->n_frag = 1;
+				res = fill_last_frag(obj, clst, ncl);	/* Fill last fragment on the FAT and link it to new one */
+				if (res == FR_OK) obj->n_frag = 1;
+			}
+		}
+	} else
+#endif
+	{	/* On the FAT/FAT32 volume */
+		ncl = 0;
+		if (scl == clst) {						/* Stretching an existing chain? */
+			ncl = scl + 1;						/* Test if next cluster is free */
+			if (ncl >= fs->n_fatent) ncl = 2;
+			cs = get_fat(obj, ncl);				/* Get next cluster status */
+			if (cs == 1 || cs == 0xFFFFFFFF) return cs;	/* Test for error */
+			if (cs != 0) {						/* Not free? */
+				cs = fs->last_clst;				/* Start at suggested cluster if it is valid */
+				if (cs >= 2 && cs < fs->n_fatent) scl = cs;
+				ncl = 0;
+			}
+		}
+		if (ncl == 0) {	/* The new cluster cannot be contiguous and find another fragment */
+			ncl = scl;	/* Start cluster */
+			for (;;) {
+				ncl++;							/* Next cluster */
+				if (ncl >= fs->n_fatent) {		/* Check wrap-around */
+					ncl = 2;
+					if (ncl > scl) return 0;	/* No free cluster found? */
+				}
+				cs = get_fat(obj, ncl);			/* Get the cluster status */
+				if (cs == 0) break;				/* Found a free cluster? */
+				if (cs == 1 || cs == 0xFFFFFFFF) return cs;	/* Test for error */
+				if (ncl == scl) return 0;		/* No free cluster found? */
+			}
+		}
+		res = put_fat(fs, ncl, 0xFFFFFFFF);		/* Mark the new cluster 'EOC' */
+		if (res == FR_OK && clst != 0) {
+			res = put_fat(fs, clst, ncl);		/* Link it from the previous one if needed */
+		}
+	}
+
+	if (res == FR_OK) {			/* Update FSINFO if function succeeded. */
+		fs->last_clst = ncl;
+		if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--;
+		fs->fsi_flag |= 1;
+	} else {
+		ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;	/* Failed. Generate error status */
+	}
+
+	return ncl;		/* Return new cluster number or error status */
+}
+
+#endif /* !FF_FS_READONLY */
+
+
+
+
+#if FF_USE_FASTSEEK
+/*-----------------------------------------------------------------------*/
+/* FAT handling - Convert offset into cluster with link map table        */
+/*-----------------------------------------------------------------------*/
+
+static DWORD clmt_clust (	/* <2:Error, >=2:Cluster number */
+	FIL* fp,		/* Pointer to the file object */
+	FSIZE_t ofs		/* File offset to be converted to cluster# */
+)
+{
+	DWORD cl, ncl, *tbl;
+	FATFS *fs = fp->obj.fs;
+
+
+	tbl = fp->cltbl + 1;	/* Top of CLMT */
+	cl = (DWORD)(ofs / SS(fs) / fs->csize);	/* Cluster order from top of the file */
+	for (;;) {
+		ncl = *tbl++;			/* Number of cluters in the fragment */
+		if (ncl == 0) return 0;	/* End of table? (error) */
+		if (cl < ncl) break;	/* In this fragment? */
+		cl -= ncl; tbl++;		/* Next fragment */
+	}
+	return cl + *tbl;	/* Return the cluster number */
+}
+
+#endif	/* FF_USE_FASTSEEK */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Fill a cluster with zeros                        */
+/*-----------------------------------------------------------------------*/
+
+#if !FF_FS_READONLY
+static FRESULT dir_clear (	/* Returns FR_OK or FR_DISK_ERR */
+	FATFS *fs,		/* Filesystem object */
+	DWORD clst		/* Directory table to clear */
+)
+{
+	DWORD sect;
+	UINT n, szb;
+	BYTE *ibuf;
+
+
+	if (sync_window(fs) != FR_OK) return FR_DISK_ERR;	/* Flush disk access window */
+	sect = clst2sect(fs, clst);		/* Top of the cluster */
+	fs->winsect = sect;				/* Set window to top of the cluster */
+	mem_set(fs->win, 0, sizeof fs->win);	/* Clear window buffer */
+#if FF_USE_LFN == 3		/* Quick table clear by using multi-secter write */
+	/* Allocate a temporary buffer */
+	for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
+	if (szb > SS(fs)) {		/* Buffer allocated? */
+		mem_set(ibuf, 0, szb);
+		szb /= SS(fs);		/* Bytes -> Sectors */
+		for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ;	/* Fill the cluster with 0 */
+		ff_memfree(ibuf);
+	} else
+#endif
+	{
+		ibuf = fs->win; szb = 1;	/* Use window buffer (many single-sector writes may take a time) */
+		for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ;	/* Fill the cluster with 0 */
+	}
+	return (n == fs->csize) ? FR_OK : FR_DISK_ERR;
+}
+#endif	/* !FF_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Set directory index                              */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT dir_sdi (	/* FR_OK(0):succeeded, !=0:error */
+	DIR* dp,		/* Pointer to directory object */
+	DWORD ofs		/* Offset of directory table */
+)
+{
+	DWORD csz, clst;
+	FATFS *fs = dp->obj.fs;
+
+
+	if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) {	/* Check range of offset and alignment */
+		return FR_INT_ERR;
+	}
+	dp->dptr = ofs;				/* Set current offset */
+	clst = dp->obj.sclust;		/* Table start cluster (0:root) */
+	if (clst == 0 && fs->fs_type >= FS_FAT32) {	/* Replace cluster# 0 with root cluster# */
+		clst = fs->dirbase;
+		if (FF_FS_EXFAT) dp->obj.stat = 0;	/* exFAT: Root dir has an FAT chain */
+	}
+
+	if (clst == 0) {	/* Static table (root-directory on the FAT volume) */
+		if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR;	/* Is index out of range? */
+		dp->sect = fs->dirbase;
+
+	} else {			/* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */
+		csz = (DWORD)fs->csize * SS(fs);	/* Bytes per cluster */
+		while (ofs >= csz) {				/* Follow cluster chain */
+			clst = get_fat(&dp->obj, clst);				/* Get next cluster */
+			if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
+			if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR;	/* Reached to end of table or internal error */
+			ofs -= csz;
+		}
+		dp->sect = clst2sect(fs, clst);
+	}
+	dp->clust = clst;					/* Current cluster# */
+	if (dp->sect == 0) return FR_INT_ERR;
+	dp->sect += ofs / SS(fs);			/* Sector# of the directory entry */
+	dp->dir = fs->win + (ofs % SS(fs));	/* Pointer to the entry in the win[] */
+
+	return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Move directory table index next                  */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT dir_next (	/* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */
+	DIR* dp,				/* Pointer to the directory object */
+	int stretch				/* 0: Do not stretch table, 1: Stretch table if needed */
+)
+{
+	DWORD ofs, clst;
+	FATFS *fs = dp->obj.fs;
+
+
+	ofs = dp->dptr + SZDIRE;	/* Next entry */
+	if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0;	/* Disable it if the offset reached the max value */
+	if (dp->sect == 0) return FR_NO_FILE;	/* Report EOT if it has been disabled */
+
+	if (ofs % SS(fs) == 0) {	/* Sector changed? */
+		dp->sect++;				/* Next sector */
+
+		if (dp->clust == 0) {	/* Static table */
+			if (ofs / SZDIRE >= fs->n_rootdir) {	/* Report EOT if it reached end of static table */
+				dp->sect = 0; return FR_NO_FILE;
+			}
+		}
+		else {					/* Dynamic table */
+			if ((ofs / SS(fs) & (fs->csize - 1)) == 0) {	/* Cluster changed? */
+				clst = get_fat(&dp->obj, dp->clust);		/* Get next cluster */
+				if (clst <= 1) return FR_INT_ERR;			/* Internal error */
+				if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
+				if (clst >= fs->n_fatent) {					/* It reached end of dynamic table */
+#if !FF_FS_READONLY
+					if (!stretch) {								/* If no stretch, report EOT */
+						dp->sect = 0; return FR_NO_FILE;
+					}
+					clst = create_chain(&dp->obj, dp->clust);	/* Allocate a cluster */
+					if (clst == 0) return FR_DENIED;			/* No free cluster */
+					if (clst == 1) return FR_INT_ERR;			/* Internal error */
+					if (clst == 0xFFFFFFFF) return FR_DISK_ERR;	/* Disk error */
+					if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR;	/* Clean up the stretched table */
+					if (FF_FS_EXFAT) dp->obj.stat |= 4;			/* exFAT: The directory has been stretched */
+#else
+					if (!stretch) dp->sect = 0;					/* (this line is to suppress compiler warning) */
+					dp->sect = 0; return FR_NO_FILE;			/* Report EOT */
+#endif
+				}
+				dp->clust = clst;		/* Initialize data for new cluster */
+				dp->sect = clst2sect(fs, clst);
+			}
+		}
+	}
+	dp->dptr = ofs;						/* Current entry */
+	dp->dir = fs->win + ofs % SS(fs);	/* Pointer to the entry in the win[] */
+
+	return FR_OK;
+}
+
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Reserve a block of directory entries             */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT dir_alloc (	/* FR_OK(0):succeeded, !=0:error */
+	DIR* dp,				/* Pointer to the directory object */
+	UINT nent				/* Number of contiguous entries to allocate */
+)
+{
+	FRESULT res;
+	UINT n;
+	FATFS *fs = dp->obj.fs;
+
+
+	res = dir_sdi(dp, 0);
+	if (res == FR_OK) {
+		n = 0;
+		do {
+			res = move_window(fs, dp->sect);
+			if (res != FR_OK) break;
+#if FF_FS_EXFAT
+			if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) {
+#else
+			if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) {
+#endif
+				if (++n == nent) break;	/* A block of contiguous free entries is found */
+			} else {
+				n = 0;					/* Not a blank entry. Restart to search */
+			}
+			res = dir_next(dp, 1);
+		} while (res == FR_OK);	/* Next entry with table stretch enabled */
+	}
+
+	if (res == FR_NO_FILE) res = FR_DENIED;	/* No directory entry to allocate */
+	return res;
+}
+
+#endif	/* !FF_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT: Directory handling - Load/Store start cluster number             */
+/*-----------------------------------------------------------------------*/
+
+static DWORD ld_clust (	/* Returns the top cluster value of the SFN entry */
+	FATFS* fs,			/* Pointer to the fs object */
+	const BYTE* dir		/* Pointer to the key entry */
+)
+{
+	DWORD cl;
+
+	cl = ld_word(dir + DIR_FstClusLO);
+	if (fs->fs_type == FS_FAT32) {
+		cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16;
+	}
+
+	return cl;
+}
+
+
+#if !FF_FS_READONLY
+static void st_clust (
+	FATFS* fs,	/* Pointer to the fs object */
+	BYTE* dir,	/* Pointer to the key entry */
+	DWORD cl	/* Value to be set */
+)
+{
+	st_word(dir + DIR_FstClusLO, (WORD)cl);
+	if (fs->fs_type == FS_FAT32) {
+		st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16));
+	}
+}
+#endif
+
+
+
+#if FF_USE_LFN
+/*--------------------------------------------------------*/
+/* FAT-LFN: Compare a part of file name with an LFN entry */
+/*--------------------------------------------------------*/
+
+static int cmp_lfn (		/* 1:matched, 0:not matched */
+	const WCHAR* lfnbuf,	/* Pointer to the LFN working buffer to be compared */
+	BYTE* dir				/* Pointer to the directory entry containing the part of LFN */
+)
+{
+	UINT i, s;
+	WCHAR wc, uc;
+
+
+	if (ld_word(dir + LDIR_FstClusLO) != 0) return 0;	/* Check LDIR_FstClusLO */
+
+	i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13;	/* Offset in the LFN buffer */
+
+	for (wc = 1, s = 0; s < 13; s++) {		/* Process all characters in the entry */
+		uc = ld_word(dir + LfnOfs[s]);		/* Pick an LFN character */
+		if (wc != 0) {
+			if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) {	/* Compare it */
+				return 0;					/* Not matched */
+			}
+			wc = uc;
+		} else {
+			if (uc != 0xFFFF) return 0;		/* Check filler */
+		}
+	}
+
+	if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0;	/* Last segment matched but different length */
+
+	return 1;		/* The part of LFN matched */
+}
+
+
+#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT
+/*-----------------------------------------------------*/
+/* FAT-LFN: Pick a part of file name from an LFN entry */
+/*-----------------------------------------------------*/
+
+static int pick_lfn (	/* 1:succeeded, 0:buffer overflow or invalid LFN entry */
+	WCHAR* lfnbuf,		/* Pointer to the LFN working buffer */
+	BYTE* dir			/* Pointer to the LFN entry */
+)
+{
+	UINT i, s;
+	WCHAR wc, uc;
+
+
+	if (ld_word(dir + LDIR_FstClusLO) != 0) return 0;	/* Check LDIR_FstClusLO is 0 */
+
+	i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13;	/* Offset in the LFN buffer */
+
+	for (wc = 1, s = 0; s < 13; s++) {		/* Process all characters in the entry */
+		uc = ld_word(dir + LfnOfs[s]);		/* Pick an LFN character */
+		if (wc != 0) {
+			if (i >= FF_MAX_LFN) return 0;	/* Buffer overflow? */
+			lfnbuf[i++] = wc = uc;			/* Store it */
+		} else {
+			if (uc != 0xFFFF) return 0;		/* Check filler */
+		}
+	}
+
+	if (dir[LDIR_Ord] & LLEF) {				/* Put terminator if it is the last LFN part */
+		if (i >= FF_MAX_LFN) return 0;		/* Buffer overflow? */
+		lfnbuf[i] = 0;
+	}
+
+	return 1;		/* The part of LFN is valid */
+}
+#endif
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------*/
+/* FAT-LFN: Create an entry of LFN entries */
+/*-----------------------------------------*/
+
+static void put_lfn (
+	const WCHAR* lfn,	/* Pointer to the LFN */
+	BYTE* dir,			/* Pointer to the LFN entry to be created */
+	BYTE ord,			/* LFN order (1-20) */
+	BYTE sum			/* Checksum of the corresponding SFN */
+)
+{
+	UINT i, s;
+	WCHAR wc;
+
+
+	dir[LDIR_Chksum] = sum;			/* Set checksum */
+	dir[LDIR_Attr] = AM_LFN;		/* Set attribute. LFN entry */
+	dir[LDIR_Type] = 0;
+	st_word(dir + LDIR_FstClusLO, 0);
+
+	i = (ord - 1) * 13;				/* Get offset in the LFN working buffer */
+	s = wc = 0;
+	do {
+		if (wc != 0xFFFF) wc = lfn[i++];	/* Get an effective character */
+		st_word(dir + LfnOfs[s], wc);		/* Put it */
+		if (wc == 0) wc = 0xFFFF;		/* Padding characters for left locations */
+	} while (++s < 13);
+	if (wc == 0xFFFF || !lfn[i]) ord |= LLEF;	/* Last LFN part is the start of LFN sequence */
+	dir[LDIR_Ord] = ord;			/* Set the LFN order */
+}
+
+#endif	/* !FF_FS_READONLY */
+#endif	/* FF_USE_LFN */
+
+
+
+#if FF_USE_LFN && !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* FAT-LFN: Create a Numbered SFN                                        */
+/*-----------------------------------------------------------------------*/
+
+static void gen_numname (
+	BYTE* dst,			/* Pointer to the buffer to store numbered SFN */
+	const BYTE* src,	/* Pointer to SFN */
+	const WCHAR* lfn,	/* Pointer to LFN */
+	UINT seq			/* Sequence number */
+)
+{
+	BYTE ns[8], c;
+	UINT i, j;
+	WCHAR wc;
+	DWORD sr;
+
+
+	mem_cpy(dst, src, 11);
+
+	if (seq > 5) {	/* In case of many collisions, generate a hash number instead of sequential number */
+		sr = seq;
+		while (*lfn) {	/* Create a CRC as hash value */
+			wc = *lfn++;
+			for (i = 0; i < 16; i++) {
+				sr = (sr << 1) + (wc & 1);
+				wc >>= 1;
+				if (sr & 0x10000) sr ^= 0x11021;
+			}
+		}
+		seq = (UINT)sr;
+	}
+
+	/* itoa (hexdecimal) */
+	i = 7;
+	do {
+		c = (BYTE)((seq % 16) + '0');
+		if (c > '9') c += 7;
+		ns[i--] = c;
+		seq /= 16;
+	} while (seq);
+	ns[i] = '~';
+
+	/* Append the number to the SFN body */
+	for (j = 0; j < i && dst[j] != ' '; j++) {
+		if (dbc_1st(dst[j])) {
+			if (j == i - 1) break;
+			j++;
+		}
+	}
+	do {
+		dst[j++] = (i < 8) ? ns[i++] : ' ';
+	} while (j < 8);
+}
+#endif	/* FF_USE_LFN && !FF_FS_READONLY */
+
+
+
+#if FF_USE_LFN
+/*-----------------------------------------------------------------------*/
+/* FAT-LFN: Calculate checksum of an SFN entry                           */
+/*-----------------------------------------------------------------------*/
+
+static BYTE sum_sfn (
+	const BYTE* dir		/* Pointer to the SFN entry */
+)
+{
+	BYTE sum = 0;
+	UINT n = 11;
+
+	do {
+		sum = (sum >> 1) + (sum << 7) + *dir++;
+	} while (--n);
+	return sum;
+}
+
+#endif	/* FF_USE_LFN */
+
+
+
+#if FF_FS_EXFAT
+/*-----------------------------------------------------------------------*/
+/* exFAT: Checksum                                                       */
+/*-----------------------------------------------------------------------*/
+
+static WORD xdir_sum (	/* Get checksum of the directoly entry block */
+	const BYTE* dir		/* Directory entry block to be calculated */
+)
+{
+	UINT i, szblk;
+	WORD sum;
+
+
+	szblk = (dir[XDIR_NumSec] + 1) * SZDIRE;	/* Number of bytes of the entry block */
+	for (i = sum = 0; i < szblk; i++) {
+		if (i == XDIR_SetSum) {	/* Skip 2-byte sum field */
+			i++;
+		} else {
+			sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i];
+		}
+	}
+	return sum;
+}
+
+
+
+static WORD xname_sum (	/* Get check sum (to be used as hash) of the file name */
+	const WCHAR* name	/* File name to be calculated */
+)
+{
+	WCHAR chr;
+	WORD sum = 0;
+
+
+	while ((chr = *name++) != 0) {
+		chr = (WCHAR)ff_wtoupper(chr);		/* File name needs to be up-case converted */
+		sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF);
+		sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8);
+	}
+	return sum;
+}
+
+
+#if !FF_FS_READONLY && FF_USE_MKFS
+static DWORD xsum32 (	/* Returns 32-bit checksum */
+	BYTE  dat,			/* Byte to be calculated (byte-by-byte processing) */
+	DWORD sum			/* Previous sum value */
+)
+{
+	sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat;
+	return sum;
+}
+#endif
+
+
+#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2
+/*------------------------------------------------------*/
+/* exFAT: Get object information from a directory block */
+/*------------------------------------------------------*/
+
+static void get_xfileinfo (
+	BYTE* dirb,			/* Pointer to the direcotry entry block 85+C0+C1s */
+	FILINFO* fno		/* Buffer to store the extracted file information */
+)
+{
+	WCHAR wc, hs;
+	UINT di, si, nc;
+
+	/* Get file name from the entry block */
+	si = SZDIRE * 2;	/* 1st C1 entry */
+	nc = 0; hs = 0; di = 0;
+	while (nc < dirb[XDIR_NumName]) {
+		if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; }	/* Truncated directory block? */
+		if ((si % SZDIRE) == 0) si += 2;		/* Skip entry type field */
+		wc = ld_word(dirb + si); si += 2; nc++;	/* Get a character */
+		if (hs == 0 && IsSurrogate(wc)) {	/* Is it a surrogate? */
+			hs = wc; continue;	/* Get low surrogate */
+		}
+		wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di);	/* Store it in API encoding */
+		if (wc == 0) { di = 0; break; }	/* Buffer overflow or wrong encoding? */
+		di += wc;
+		hs = 0;
+	}
+	if (hs != 0) di = 0;					/* Broken surrogate pair? */
+	if (di == 0) fno->fname[di++] = '?';	/* Inaccessible object name? */
+	fno->fname[di] = 0;						/* Terminate the name */
+	fno->altname[0] = 0;					/* exFAT does not support SFN */
+
+	fno->fattrib = dirb[XDIR_Attr];			/* Attribute */
+	fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize);	/* Size */
+	fno->ftime = ld_word(dirb + XDIR_ModTime + 0);	/* Time */
+	fno->fdate = ld_word(dirb + XDIR_ModTime + 2);	/* Date */
+}
+
+#endif	/* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */
+
+
+/*-----------------------------------*/
+/* exFAT: Get a directry entry block */
+/*-----------------------------------*/
+
+static FRESULT load_xdir (	/* FR_INT_ERR: invalid entry block */
+	DIR* dp					/* Reading direcotry object pointing top of the entry block to load */
+)
+{
+	FRESULT res;
+	UINT i, sz_ent;
+	BYTE* dirb = dp->obj.fs->dirbuf;	/* Pointer to the on-memory direcotry entry block 85+C0+C1s */
+
+
+	/* Load file-directory entry */
+	res = move_window(dp->obj.fs, dp->sect);
+	if (res != FR_OK) return res;
+	if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR;	/* Invalid order */
+	mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
+	sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
+	if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
+
+	/* Load stream-extension entry */
+	res = dir_next(dp, 0);
+	if (res == FR_NO_FILE) res = FR_INT_ERR;	/* It cannot be */
+	if (res != FR_OK) return res;
+	res = move_window(dp->obj.fs, dp->sect);
+	if (res != FR_OK) return res;
+	if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR;	/* Invalid order */
+	mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
+	if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
+
+	/* Load file-name entries */
+	i = 2 * SZDIRE;	/* Name offset to load */
+	do {
+		res = dir_next(dp, 0);
+		if (res == FR_NO_FILE) res = FR_INT_ERR;	/* It cannot be */
+		if (res != FR_OK) return res;
+		res = move_window(dp->obj.fs, dp->sect);
+		if (res != FR_OK) return res;
+		if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR;	/* Invalid order */
+		if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
+	} while ((i += SZDIRE) < sz_ent);
+
+	/* Sanity check (do it for only accessible object) */
+	if (i <= MAXDIRB(FF_MAX_LFN)) {
+		if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR;
+	}
+	return FR_OK;
+}
+
+
+/*------------------------------------------------------------------*/
+/* exFAT: Initialize object allocation info with loaded entry block */
+/*------------------------------------------------------------------*/
+
+static void init_alloc_info (
+	FATFS* fs,		/* Filesystem object */
+	FFOBJID* obj	/* Object allocation information to be initialized */
+)
+{
+	obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus);		/* Start cluster */
+	obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize);	/* Size */
+	obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;				/* Allocation status */
+	obj->n_frag = 0;										/* No last fragment info */
+}
+
+
+
+#if !FF_FS_READONLY || FF_FS_RPATH != 0
+/*------------------------------------------------*/
+/* exFAT: Load the object's directory entry block */
+/*------------------------------------------------*/
+
+static FRESULT load_obj_xdir (
+	DIR* dp,			/* Blank directory object to be used to access containing direcotry */
+	const FFOBJID* obj	/* Object with its containing directory information */
+)
+{
+	FRESULT res;
+
+	/* Open object containing directory */
+	dp->obj.fs = obj->fs;
+	dp->obj.sclust = obj->c_scl;
+	dp->obj.stat = (BYTE)obj->c_size;
+	dp->obj.objsize = obj->c_size & 0xFFFFFF00;
+	dp->obj.n_frag = 0;
+	dp->blk_ofs = obj->c_ofs;
+
+	res = dir_sdi(dp, dp->blk_ofs);	/* Goto object's entry block */
+	if (res == FR_OK) {
+		res = load_xdir(dp);		/* Load the object's entry block */
+	}
+	return res;
+}
+#endif
+
+
+#if !FF_FS_READONLY
+/*----------------------------------------*/
+/* exFAT: Store the directory entry block */
+/*----------------------------------------*/
+
+static FRESULT store_xdir (
+	DIR* dp				/* Pointer to the direcotry object */
+)
+{
+	FRESULT res;
+	UINT nent;
+	BYTE* dirb = dp->obj.fs->dirbuf;	/* Pointer to the direcotry entry block 85+C0+C1s */
+
+	/* Create set sum */
+	st_word(dirb + XDIR_SetSum, xdir_sum(dirb));
+	nent = dirb[XDIR_NumSec] + 1;
+
+	/* Store the direcotry entry block to the directory */
+	res = dir_sdi(dp, dp->blk_ofs);
+	while (res == FR_OK) {
+		res = move_window(dp->obj.fs, dp->sect);
+		if (res != FR_OK) break;
+		mem_cpy(dp->dir, dirb, SZDIRE);
+		dp->obj.fs->wflag = 1;
+		if (--nent == 0) break;
+		dirb += SZDIRE;
+		res = dir_next(dp, 0);
+	}
+	return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR;
+}
+
+
+
+/*-------------------------------------------*/
+/* exFAT: Create a new directory enrty block */
+/*-------------------------------------------*/
+
+static void create_xdir (
+	BYTE* dirb,			/* Pointer to the direcotry entry block buffer */
+	const WCHAR* lfn	/* Pointer to the object name */
+)
+{
+	UINT i;
+	BYTE nc1, nlen;
+	WCHAR wc;
+
+
+	/* Create file-directory and stream-extension entry */
+	mem_set(dirb, 0, 2 * SZDIRE);
+	dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
+	dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
+
+	/* Create file-name entries */
+	i = SZDIRE * 2;	/* Top of file_name entries */
+	nlen = nc1 = 0; wc = 1;
+	do {
+		dirb[i++] = ET_FILENAME; dirb[i++] = 0;
+		do {	/* Fill name field */
+			if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++;	/* Get a character if exist */
+			st_word(dirb + i, wc); 		/* Store it */
+			i += 2;
+		} while (i % SZDIRE != 0);
+		nc1++;
+	} while (lfn[nlen]);	/* Fill next entry if any char follows */
+
+	dirb[XDIR_NumName] = nlen;		/* Set name length */
+	dirb[XDIR_NumSec] = 1 + nc1;	/* Set secondary count (C0 + C1s) */
+	st_word(dirb + XDIR_NameHash, xname_sum(lfn));	/* Set name hash */
+}
+
+#endif	/* !FF_FS_READONLY */
+#endif	/* FF_FS_EXFAT */
+
+
+
+#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT
+/*-----------------------------------------------------------------------*/
+/* Read an object from the directory                                     */
+/*-----------------------------------------------------------------------*/
+
+#define DIR_READ_FILE(dp) dir_read(dp, 0)
+#define DIR_READ_LABEL(dp) dir_read(dp, 1)
+
+static FRESULT dir_read (
+	DIR* dp,		/* Pointer to the directory object */
+	int vol			/* Filtered by 0:file/directory or 1:volume label */
+)
+{
+	FRESULT res = FR_NO_FILE;
+	FATFS *fs = dp->obj.fs;
+	BYTE attr, b;
+#if FF_USE_LFN
+	BYTE ord = 0xFF, sum = 0xFF;
+#endif
+
+	while (dp->sect) {
+		res = move_window(fs, dp->sect);
+		if (res != FR_OK) break;
+		b = dp->dir[DIR_Name];	/* Test for the entry type */
+		if (b == 0) {
+			res = FR_NO_FILE; break; /* Reached to end of the directory */
+		}
+#if FF_FS_EXFAT
+		if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
+			if (FF_USE_LABEL && vol) {
+				if (b == ET_VLABEL) break;	/* Volume label entry? */
+			} else {
+				if (b == ET_FILEDIR) {		/* Start of the file entry block? */
+					dp->blk_ofs = dp->dptr;	/* Get location of the block */
+					res = load_xdir(dp);	/* Load the entry block */
+					if (res == FR_OK) {
+						dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK;	/* Get attribute */
+					}
+					break;
+				}
+			}
+		} else
+#endif
+		{	/* On the FAT/FAT32 volume */
+			dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK;	/* Get attribute */
+#if FF_USE_LFN		/* LFN configuration */
+			if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) {	/* An entry without valid data */
+				ord = 0xFF;
+			} else {
+				if (attr == AM_LFN) {			/* An LFN entry is found */
+					if (b & LLEF) {			/* Is it start of an LFN sequence? */
+						sum = dp->dir[LDIR_Chksum];
+						b &= (BYTE)~LLEF; ord = b;
+						dp->blk_ofs = dp->dptr;
+					}
+					/* Check LFN validity and capture it */
+					ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
+				} else {					/* An SFN entry is found */
+					if (ord != 0 || sum != sum_sfn(dp->dir)) {	/* Is there a valid LFN? */
+						dp->blk_ofs = 0xFFFFFFFF;			/* It has no LFN. */
+					}
+					break;
+				}
+			}
+#else		/* Non LFN configuration */
+			if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) {	/* Is it a valid entry? */
+				break;
+			}
+#endif
+		}
+		res = dir_next(dp, 0);		/* Next entry */
+		if (res != FR_OK) break;
+	}
+
+	if (res != FR_OK) dp->sect = 0;		/* Terminate the read operation on error or EOT */
+	return res;
+}
+
+#endif	/* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Find an object in the directory                  */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT dir_find (	/* FR_OK(0):succeeded, !=0:error */
+	DIR* dp					/* Pointer to the directory object with the file name */
+)
+{
+	FRESULT res;
+	FATFS *fs = dp->obj.fs;
+	BYTE c;
+#if FF_USE_LFN
+	BYTE a, ord, sum;
+#endif
+
+	res = dir_sdi(dp, 0);			/* Rewind directory object */
+	if (res != FR_OK) return res;
+#if FF_FS_EXFAT
+	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
+		BYTE nc;
+		UINT di, ni;
+		WORD hash = xname_sum(fs->lfnbuf);		/* Hash value of the name to find */
+
+		while ((res = DIR_READ_FILE(dp)) == FR_OK) {	/* Read an item */
+#if FF_MAX_LFN < 255
+			if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue;			/* Skip comparison if inaccessible object name */
+#endif
+			if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue;	/* Skip comparison if hash mismatched */
+			for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) {	/* Compare the name */
+				if ((di % SZDIRE) == 0) di += 2;
+				if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break;
+			}
+			if (nc == 0 && !fs->lfnbuf[ni]) break;	/* Name matched? */
+		}
+		return res;
+	}
+#endif
+	/* On the FAT/FAT32 volume */
+#if FF_USE_LFN
+	ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF;	/* Reset LFN sequence */
+#endif
+	do {
+		res = move_window(fs, dp->sect);
+		if (res != FR_OK) break;
+		c = dp->dir[DIR_Name];
+		if (c == 0) { res = FR_NO_FILE; break; }	/* Reached to end of table */
+#if FF_USE_LFN		/* LFN configuration */
+		dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK;
+		if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) {	/* An entry without valid data */
+			ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF;	/* Reset LFN sequence */
+		} else {
+			if (a == AM_LFN) {			/* An LFN entry is found */
+				if (!(dp->fn[NSFLAG] & NS_NOLFN)) {
+					if (c & LLEF) {		/* Is it start of LFN sequence? */
+						sum = dp->dir[LDIR_Chksum];
+						c &= (BYTE)~LLEF; ord = c;	/* LFN start order */
+						dp->blk_ofs = dp->dptr;	/* Start offset of LFN */
+					}
+					/* Check validity of the LFN entry and compare it with given name */
+					ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
+				}
+			} else {					/* An SFN entry is found */
+				if (ord == 0 && sum == sum_sfn(dp->dir)) break;	/* LFN matched? */
+				if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break;	/* SFN matched? */
+				ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF;	/* Reset LFN sequence */
+			}
+		}
+#else		/* Non LFN configuration */
+		dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK;
+		if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break;	/* Is it a valid entry? */
+#endif
+		res = dir_next(dp, 0);	/* Next entry */
+	} while (res == FR_OK);
+
+	return res;
+}
+
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Register an object to the directory                                   */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT dir_register (	/* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */
+	DIR* dp						/* Target directory with object name to be created */
+)
+{
+	FRESULT res;
+	FATFS *fs = dp->obj.fs;
+#if FF_USE_LFN		/* LFN configuration */
+	UINT n, nlen, nent;
+	BYTE sn[12], sum;
+
+
+	if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME;	/* Check name validity */
+	for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ;	/* Get lfn length */
+
+#if FF_FS_EXFAT
+	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
+		nent = (nlen + 14) / 15 + 2;	/* Number of entries to allocate (85+C0+C1s) */
+		res = dir_alloc(dp, nent);		/* Allocate directory entries */
+		if (res != FR_OK) return res;
+		dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1);	/* Set the allocated entry block offset */
+
+		if (dp->obj.stat & 4) {			/* Has the directory been stretched by new allocation? */
+			dp->obj.stat &= ~4;
+			res = fill_first_frag(&dp->obj);	/* Fill the first fragment on the FAT if needed */
+			if (res != FR_OK) return res;
+			res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF);	/* Fill the last fragment on the FAT if needed */
+			if (res != FR_OK) return res;
+			if (dp->obj.sclust != 0) {		/* Is it a sub-directory? */
+				DIR dj;
+
+				res = load_obj_xdir(&dj, &dp->obj);	/* Load the object status */
+				if (res != FR_OK) return res;
+				dp->obj.objsize += (DWORD)fs->csize * SS(fs);			/* Increase the directory size by cluster size */
+				st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize);	/* Update the allocation status */
+				st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
+				fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
+				res = store_xdir(&dj);				/* Store the object status */
+				if (res != FR_OK) return res;
+			}
+		}
+
+		create_xdir(fs->dirbuf, fs->lfnbuf);	/* Create on-memory directory block to be written later */
+		return FR_OK;
+	}
+#endif
+	/* On the FAT/FAT32 volume */
+	mem_cpy(sn, dp->fn, 12);
+	if (sn[NSFLAG] & NS_LOSS) {			/* When LFN is out of 8.3 format, generate a numbered name */
+		dp->fn[NSFLAG] = NS_NOLFN;		/* Find only SFN */
+		for (n = 1; n < 100; n++) {
+			gen_numname(dp->fn, sn, fs->lfnbuf, n);	/* Generate a numbered name */
+			res = dir_find(dp);				/* Check if the name collides with existing SFN */
+			if (res != FR_OK) break;
+		}
+		if (n == 100) return FR_DENIED;		/* Abort if too many collisions */
+		if (res != FR_NO_FILE) return res;	/* Abort if the result is other than 'not collided' */
+		dp->fn[NSFLAG] = sn[NSFLAG];
+	}
+
+	/* Create an SFN with/without LFNs. */
+	nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1;	/* Number of entries to allocate */
+	res = dir_alloc(dp, nent);		/* Allocate entries */
+	if (res == FR_OK && --nent) {	/* Set LFN entry if needed */
+		res = dir_sdi(dp, dp->dptr - nent * SZDIRE);
+		if (res == FR_OK) {
+			sum = sum_sfn(dp->fn);	/* Checksum value of the SFN tied to the LFN */
+			do {					/* Store LFN entries in bottom first */
+				res = move_window(fs, dp->sect);
+				if (res != FR_OK) break;
+				put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum);
+				fs->wflag = 1;
+				res = dir_next(dp, 0);	/* Next entry */
+			} while (res == FR_OK && --nent);
+		}
+	}
+
+#else	/* Non LFN configuration */
+	res = dir_alloc(dp, 1);		/* Allocate an entry for SFN */
+
+#endif
+
+	/* Set SFN entry */
+	if (res == FR_OK) {
+		res = move_window(fs, dp->sect);
+		if (res == FR_OK) {
+			mem_set(dp->dir, 0, SZDIRE);	/* Clean the entry */
+			mem_cpy(dp->dir + DIR_Name, dp->fn, 11);	/* Put SFN */
+#if FF_USE_LFN
+			dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT);	/* Put NT flag */
+#endif
+			fs->wflag = 1;
+		}
+	}
+
+	return res;
+}
+
+#endif /* !FF_FS_READONLY */
+
+
+
+#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0
+/*-----------------------------------------------------------------------*/
+/* Remove an object from the directory                                   */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT dir_remove (	/* FR_OK:Succeeded, FR_DISK_ERR:A disk error */
+	DIR* dp					/* Directory object pointing the entry to be removed */
+)
+{
+	FRESULT res;
+	FATFS *fs = dp->obj.fs;
+#if FF_USE_LFN		/* LFN configuration */
+	DWORD last = dp->dptr;
+
+	res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs);	/* Goto top of the entry block if LFN is exist */
+	if (res == FR_OK) {
+		do {
+			res = move_window(fs, dp->sect);
+			if (res != FR_OK) break;
+			if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
+				dp->dir[XDIR_Type] &= 0x7F;	/* Clear the entry InUse flag. */
+			} else {									/* On the FAT/FAT32 volume */
+				dp->dir[DIR_Name] = DDEM;	/* Mark the entry 'deleted'. */
+			}
+			fs->wflag = 1;
+			if (dp->dptr >= last) break;	/* If reached last entry then all entries of the object has been deleted. */
+			res = dir_next(dp, 0);	/* Next entry */
+		} while (res == FR_OK);
+		if (res == FR_NO_FILE) res = FR_INT_ERR;
+	}
+#else			/* Non LFN configuration */
+
+	res = move_window(fs, dp->sect);
+	if (res == FR_OK) {
+		dp->dir[DIR_Name] = DDEM;	/* Mark the entry 'deleted'.*/
+		fs->wflag = 1;
+	}
+#endif
+
+	return res;
+}
+
+#endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */
+
+
+
+#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2
+/*-----------------------------------------------------------------------*/
+/* Get file information from directory entry                             */
+/*-----------------------------------------------------------------------*/
+
+static void get_fileinfo (
+	DIR* dp,			/* Pointer to the directory object */
+	FILINFO* fno		/* Pointer to the file information to be filled */
+)
+{
+	UINT si, di;
+#if FF_USE_LFN
+	WCHAR wc, hs;
+	FATFS *fs = dp->obj.fs;
+#else
+	TCHAR c;
+#endif
+
+
+	fno->fname[0] = 0;			/* Invaidate file info */
+	if (dp->sect == 0) return;	/* Exit if read pointer has reached end of directory */
+
+#if FF_USE_LFN		/* LFN configuration */
+#if FF_FS_EXFAT
+	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
+		get_xfileinfo(fs->dirbuf, fno);
+		return;
+	} else
+#endif
+	{	/* On the FAT/FAT32 volume */
+		if (dp->blk_ofs != 0xFFFFFFFF) {	/* Get LFN if available */
+			si = di = hs = 0;
+			while (fs->lfnbuf[si] != 0) {
+				wc = fs->lfnbuf[si++];		/* Get an LFN character (UTF-16) */
+				if (hs == 0 && IsSurrogate(wc)) {	/* Is it a surrogate? */
+					hs = wc; continue;		/* Get low surrogate */
+				}
+				wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di);	/* Store it in UTF-16 or UTF-8 encoding */
+				if (wc == 0) { di = 0; break; }	/* Invalid char or buffer overflow? */
+				di += wc;
+				hs = 0;
+			}
+			if (hs != 0) di = 0;	/* Broken surrogate pair? */
+			fno->fname[di] = 0;		/* Terminate the LFN (null string means LFN is invalid) */
+		}
+	}
+
+	si = di = 0;
+	while (si < 11) {		/* Get SFN from SFN entry */
+		wc = dp->dir[si++];			/* Get a char */
+		if (wc == ' ') continue;	/* Skip padding spaces */
+		if (wc == RDDEM) wc = DDEM;	/* Restore replaced DDEM character */
+		if (si == 9 && di < FF_SFN_BUF) fno->altname[di++] = '.';	/* Insert a . if extension is exist */
+#if FF_LFN_UNICODE >= 1	/* Unicode output */
+		if (dbc_1st((BYTE)wc) && si != 8 && si != 11 && dbc_2nd(dp->dir[si])) {	/* Make a DBC if needed */
+			wc = wc << 8 | dp->dir[si++];
+		}
+		wc = ff_oem2uni(wc, CODEPAGE);		/* ANSI/OEM -> Unicode */
+		if (wc == 0) { di = 0; break; }		/* Wrong char in the current code page? */
+		wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di);	/* Store it in Unicode */
+		if (wc == 0) { di = 0; break; }		/* Buffer overflow? */
+		di += wc;
+#else					/* ANSI/OEM output */
+		fno->altname[di++] = (TCHAR)wc;	/* Store it without any conversion */
+#endif
+	}
+	fno->altname[di] = 0;	/* Terminate the SFN  (null string means SFN is invalid) */
+
+	if (fno->fname[0] == 0) {	/* If LFN is invalid, altname[] needs to be copied to fname[] */
+		if (di == 0) {	/* If LFN and SFN both are invalid, this object is inaccesible */
+			fno->fname[di++] = '?';
+		} else {
+			for (si = di = 0; fno->altname[si]; si++, di++) {	/* Copy altname[] to fname[] with case information */
+				wc = (WCHAR)fno->altname[si];
+				if (IsUpper(wc) && (dp->dir[DIR_NTres] & ((si >= 9) ? NS_EXT : NS_BODY))) wc += 0x20;
+				fno->fname[di] = (TCHAR)wc;
+			}
+		}
+		fno->fname[di] = 0;	/* Terminate the LFN */
+		if (!dp->dir[DIR_NTres]) fno->altname[0] = 0;	/* Altname is not needed if neither LFN nor case info is exist. */
+	}
+
+#else	/* Non-LFN configuration */
+	si = di = 0;
+	while (si < 11) {		/* Copy name body and extension */
+		c = (TCHAR)dp->dir[si++];
+		if (c == ' ') continue;		/* Skip padding spaces */
+		if (c == RDDEM) c = DDEM;	/* Restore replaced DDEM character */
+		if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */
+		fno->fname[di++] = c;
+	}
+	fno->fname[di] = 0;
+#endif
+
+	fno->fattrib = dp->dir[DIR_Attr];					/* Attribute */
+	fno->fsize = ld_dword(dp->dir + DIR_FileSize);		/* Size */
+	fno->ftime = ld_word(dp->dir + DIR_ModTime + 0);	/* Time */
+	fno->fdate = ld_word(dp->dir + DIR_ModTime + 2);	/* Date */
+}
+
+#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */
+
+
+
+#if FF_USE_FIND && FF_FS_MINIMIZE <= 1
+/*-----------------------------------------------------------------------*/
+/* Pattern matching                                                      */
+/*-----------------------------------------------------------------------*/
+
+static DWORD get_achar (	/* Get a character and advances ptr */
+	const TCHAR** ptr		/* Pointer to pointer to the ANSI/OEM or Unicode string */
+)
+{
+	DWORD chr;
+
+
+#if FF_USE_LFN && FF_LFN_UNICODE >= 1	/* Unicode input */
+	chr = tchar2uni(ptr);
+	if (chr == 0xFFFFFFFF) chr = 0;		/* Wrong UTF encoding is recognized as end of the string */
+	chr = ff_wtoupper(chr);
+
+#else									/* ANSI/OEM input */
+	chr = (BYTE)*(*ptr)++;				/* Get a byte */
+	if (IsLower(chr)) chr -= 0x20;		/* To upper ASCII char */
+#if FF_CODE_PAGE == 0
+	if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80];	/* To upper SBCS extended char */
+#elif FF_CODE_PAGE < 900
+	if (chr >= 0x80) chr = ExCvt[chr - 0x80];	/* To upper SBCS extended char */
+#endif
+#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900
+	if (dbc_1st((BYTE)chr)) {	/* Get DBC 2nd byte if needed */
+		chr = dbc_2nd((BYTE)**ptr) ? chr << 8 | (BYTE)*(*ptr)++ : 0;
+	}
+#endif
+
+#endif
+	return chr;
+}
+
+
+static int pattern_matching (	/* 0:not matched, 1:matched */
+	const TCHAR* pat,	/* Matching pattern */
+	const TCHAR* nam,	/* String to be tested */
+	int skip,			/* Number of pre-skip chars (number of ?s) */
+	int inf				/* Infinite search (* specified) */
+)
+{
+	const TCHAR *pp, *np;
+	DWORD pc, nc;
+	int nm, nx;
+
+
+	while (skip--) {				/* Pre-skip name chars */
+		if (!get_achar(&nam)) return 0;	/* Branch mismatched if less name chars */
+	}
+	if (*pat == 0 && inf) return 1;	/* (short circuit) */
+
+	do {
+		pp = pat; np = nam;			/* Top of pattern and name to match */
+		for (;;) {
+			if (*pp == '?' || *pp == '*') {	/* Wildcard? */
+				nm = nx = 0;
+				do {				/* Analyze the wildcard block */
+					if (*pp++ == '?') nm++; else nx = 1;
+				} while (*pp == '?' || *pp == '*');
+				if (pattern_matching(pp, np, nm, nx)) return 1;	/* Test new branch (recurs upto number of wildcard blocks in the pattern) */
+				nc = *np; break;	/* Branch mismatched */
+			}
+			pc = get_achar(&pp);	/* Get a pattern char */
+			nc = get_achar(&np);	/* Get a name char */
+			if (pc != nc) break;	/* Branch mismatched? */
+			if (pc == 0) return 1;	/* Branch matched? (matched at end of both strings) */
+		}
+		get_achar(&nam);			/* nam++ */
+	} while (inf && nc);			/* Retry until end of name if infinite search is specified */
+
+	return 0;
+}
+
+#endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Pick a top segment and create the object name in directory form       */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT create_name (	/* FR_OK: successful, FR_INVALID_NAME: could not create */
+	DIR* dp,					/* Pointer to the directory object */
+	const TCHAR** path			/* Pointer to pointer to the segment in the path string */
+)
+{
+#if FF_USE_LFN		/* LFN configuration */
+	BYTE b, cf;
+	WCHAR wc, *lfn;
+	DWORD uc;
+	UINT i, ni, si, di;
+	const TCHAR *p;
+
+
+	/* Create LFN into LFN working buffer */
+	p = *path; lfn = dp->obj.fs->lfnbuf; di = 0;
+	for (;;) {
+		uc = tchar2uni(&p);			/* Get a character */
+		if (uc == 0xFFFFFFFF) return FR_INVALID_NAME;		/* Invalid code or UTF decode error */
+		if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16);	/* Store high surrogate if needed */
+		wc = (WCHAR)uc;
+		if (wc < ' ' || wc == '/' || wc == '\\') break;	/* Break if end of the path or a separator is found */
+		if (wc < 0x80 && chk_chr("\"*:<>\?|\x7F", wc)) return FR_INVALID_NAME;	/* Reject illegal characters for LFN */
+		if (di >= FF_MAX_LFN) return FR_INVALID_NAME;	/* Reject too long name */
+		lfn[di++] = wc;					/* Store the Unicode character */
+	}
+	while (*p == '/' || *p == '\\') p++;	/* Skip duplicated separators if exist */
+	*path = p;							/* Return pointer to the next segment */
+	cf = (wc < ' ') ? NS_LAST : 0;		/* Set last segment flag if end of the path */
+
+#if FF_FS_RPATH != 0
+	if ((di == 1 && lfn[di - 1] == '.') ||
+		(di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) {	/* Is this segment a dot name? */
+		lfn[di] = 0;
+		for (i = 0; i < 11; i++) {		/* Create dot name for SFN entry */
+			dp->fn[i] = (i < di) ? '.' : ' ';
+		}
+		dp->fn[i] = cf | NS_DOT;		/* This is a dot entry */
+		return FR_OK;
+	}
+#endif
+	while (di) {						/* Snip off trailing spaces and dots if exist */
+		wc = lfn[di - 1];
+		if (wc != ' ' && wc != '.') break;
+		di--;
+	}
+	lfn[di] = 0;							/* LFN is created into the working buffer */
+	if (di == 0) return FR_INVALID_NAME;	/* Reject null name */
+
+	/* Create SFN in directory form */
+	for (si = 0; lfn[si] == ' '; si++) ;	/* Remove leading spaces */
+	if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN;	/* Is there any leading space or dot? */
+	while (di > 0 && lfn[di - 1] != '.') di--;	/* Find last dot (di<=si: no extension) */
+
+	mem_set(dp->fn, ' ', 11);
+	i = b = 0; ni = 8;
+	for (;;) {
+		wc = lfn[si++];					/* Get an LFN character */
+		if (wc == 0) break;				/* Break on end of the LFN */
+		if (wc == ' ' || (wc == '.' && si != di)) {	/* Remove embedded spaces and dots */
+			cf |= NS_LOSS | NS_LFN;
+			continue;
+		}
+
+		if (i >= ni || si == di) {		/* End of field? */
+			if (ni == 11) {				/* Name extension overflow? */
+				cf |= NS_LOSS | NS_LFN;
+				break;
+			}
+			if (si != di) cf |= NS_LOSS | NS_LFN;	/* Name body overflow? */
+			if (si > di) break;						/* No name extension? */
+			si = di; i = 8; ni = 11; b <<= 2;		/* Enter name extension */
+			continue;
+		}
+
+		if (wc >= 0x80) {	/* Is this a non-ASCII character? */
+			cf |= NS_LFN;	/* LFN entry needs to be created */
+#if FF_CODE_PAGE == 0
+			if (ExCvt) {	/* At SBCS */
+				wc = ff_uni2oem(wc, CODEPAGE);			/* Unicode ==> ANSI/OEM code */
+				if (wc & 0x80) wc = ExCvt[wc & 0x7F];	/* Convert extended character to upper (SBCS) */
+			} else {		/* At DBCS */
+				wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE);	/* Unicode ==> Upper convert ==> ANSI/OEM code */
+			}
+#elif FF_CODE_PAGE < 900	/* SBCS cfg */
+			wc = ff_uni2oem(wc, CODEPAGE);			/* Unicode ==> ANSI/OEM code */
+			if (wc & 0x80) wc = ExCvt[wc & 0x7F];	/* Convert extended character to upper (SBCS) */
+#else						/* DBCS cfg */
+			wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE);	/* Unicode ==> Upper convert ==> ANSI/OEM code */
+#endif
+		}
+
+		if (wc >= 0x100) {				/* Is this a DBC? */
+			if (i >= ni - 1) {			/* Field overflow? */
+				cf |= NS_LOSS | NS_LFN;
+				i = ni; continue;		/* Next field */
+			}
+			dp->fn[i++] = (BYTE)(wc >> 8);	/* Put 1st byte */
+		} else {						/* SBC */
+			if (wc == 0 || chk_chr("+,;=[]", wc)) {	/* Replace illegal characters for SFN if needed */
+				wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
+			} else {
+				if (IsUpper(wc)) {		/* ASCII upper case? */
+					b |= 2;
+				}
+				if (IsLower(wc)) {		/* ASCII lower case? */
+					b |= 1; wc -= 0x20;
+				}
+			}
+		}
+		dp->fn[i++] = (BYTE)wc;
+	}
+
+	if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM;	/* If the first character collides with DDEM, replace it with RDDEM */
+
+	if (ni == 8) b <<= 2;				/* Shift capital flags if no extension */
+	if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN;	/* LFN entry needs to be created if composite capitals */
+	if (!(cf & NS_LFN)) {				/* When LFN is in 8.3 format without extended character, NT flags are created */
+		if (b & 0x01) cf |= NS_EXT;		/* NT flag (Extension has small capital letters only) */
+		if (b & 0x04) cf |= NS_BODY;	/* NT flag (Body has small capital letters only) */
+	}
+
+	dp->fn[NSFLAG] = cf;	/* SFN is created into dp->fn[] */
+
+	return FR_OK;
+
+
+#else	/* FF_USE_LFN : Non-LFN configuration */
+	BYTE c, d, *sfn;
+	UINT ni, si, i;
+	const char *p;
+
+	/* Create file name in directory form */
+	p = *path; sfn = dp->fn;
+	mem_set(sfn, ' ', 11);
+	si = i = 0; ni = 8;
+#if FF_FS_RPATH != 0
+	if (p[si] == '.') { /* Is this a dot entry? */
+		for (;;) {
+			c = (BYTE)p[si++];
+			if (c != '.' || si >= 3) break;
+			sfn[i++] = c;
+		}
+		if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
+		*path = p + si;								/* Return pointer to the next segment */
+		sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT;	/* Set last segment flag if end of the path */
+		return FR_OK;
+	}
+#endif
+	for (;;) {
+		c = (BYTE)p[si++];				/* Get a byte */
+		if (c <= ' ') break; 			/* Break if end of the path name */
+		if (c == '/' || c == '\\') {	/* Break if a separator is found */
+			while (p[si] == '/' || p[si] == '\\') si++;	/* Skip duplicated separator if exist */
+			break;
+		}
+		if (c == '.' || i >= ni) {		/* End of body or field overflow? */
+			if (ni == 11 || c != '.') return FR_INVALID_NAME;	/* Field overflow or invalid dot? */
+			i = 8; ni = 11;				/* Enter file extension field */
+			continue;
+		}
+#if FF_CODE_PAGE == 0
+		if (ExCvt && c >= 0x80) {		/* Is SBC extended character? */
+			c = ExCvt[c & 0x7F];		/* To upper SBC extended character */
+		}
+#elif FF_CODE_PAGE < 900
+		if (c >= 0x80) {				/* Is SBC extended character? */
+			c = ExCvt[c & 0x7F];		/* To upper SBC extended character */
+		}
+#endif
+		if (dbc_1st(c)) {				/* Check if it is a DBC 1st byte */
+			d = (BYTE)p[si++];			/* Get 2nd byte */
+			if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME;	/* Reject invalid DBC */
+			sfn[i++] = c;
+			sfn[i++] = d;
+		} else {						/* SBC */
+			if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME;	/* Reject illegal chrs for SFN */
+			if (IsLower(c)) c -= 0x20;	/* To upper */
+			sfn[i++] = c;
+		}
+	}
+	*path = p + si;						/* Return pointer to the next segment */
+	if (i == 0) return FR_INVALID_NAME;	/* Reject nul string */
+
+	if (sfn[0] == DDEM) sfn[0] = RDDEM;	/* If the first character collides with DDEM, replace it with RDDEM */
+	sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0;		/* Set last segment flag if end of the path */
+
+	return FR_OK;
+#endif /* FF_USE_LFN */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Follow a file path                                                    */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
+	DIR* dp,					/* Directory object to return last directory and found object */
+	const TCHAR* path			/* Full-path string to find a file or directory */
+)
+{
+	FRESULT res;
+	BYTE ns;
+	FATFS *fs = dp->obj.fs;
+
+
+#if FF_FS_RPATH != 0
+	if (*path != '/' && *path != '\\') {	/* Without heading separator */
+		dp->obj.sclust = fs->cdir;				/* Start from current directory */
+	} else
+#endif
+	{										/* With heading separator */
+		while (*path == '/' || *path == '\\') path++;	/* Strip heading separator */
+		dp->obj.sclust = 0;					/* Start from root directory */
+	}
+#if FF_FS_EXFAT
+	dp->obj.n_frag = 0;	/* Invalidate last fragment counter of the object */
+#if FF_FS_RPATH != 0
+	if (fs->fs_type == FS_EXFAT && dp->obj.sclust) {	/* exFAT: Retrieve the sub-directory's status */
+		DIR dj;
+
+		dp->obj.c_scl = fs->cdc_scl;
+		dp->obj.c_size = fs->cdc_size;
+		dp->obj.c_ofs = fs->cdc_ofs;
+		res = load_obj_xdir(&dj, &dp->obj);
+		if (res != FR_OK) return res;
+		dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize);
+		dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
+	}
+#endif
+#endif
+
+	if ((UINT)*path < ' ') {				/* Null path name is the origin directory itself */
+		dp->fn[NSFLAG] = NS_NONAME;
+		res = dir_sdi(dp, 0);
+
+	} else {								/* Follow path */
+		for (;;) {
+			res = create_name(dp, &path);	/* Get a segment name of the path */
+			if (res != FR_OK) break;
+			res = dir_find(dp);				/* Find an object with the segment name */
+			ns = dp->fn[NSFLAG];
+			if (res != FR_OK) {				/* Failed to find the object */
+				if (res == FR_NO_FILE) {	/* Object is not found */
+					if (FF_FS_RPATH && (ns & NS_DOT)) {	/* If dot entry is not exist, stay there */
+						if (!(ns & NS_LAST)) continue;	/* Continue to follow if not last segment */
+						dp->fn[NSFLAG] = NS_NONAME;
+						res = FR_OK;
+					} else {							/* Could not find the object */
+						if (!(ns & NS_LAST)) res = FR_NO_PATH;	/* Adjust error code if not last segment */
+					}
+				}
+				break;
+			}
+			if (ns & NS_LAST) break;			/* Last segment matched. Function completed. */
+			/* Get into the sub-directory */
+			if (!(dp->obj.attr & AM_DIR)) {		/* It is not a sub-directory and cannot follow */
+				res = FR_NO_PATH; break;
+			}
+#if FF_FS_EXFAT
+			if (fs->fs_type == FS_EXFAT) {		/* Save containing directory information for next dir */
+				dp->obj.c_scl = dp->obj.sclust;
+				dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
+				dp->obj.c_ofs = dp->blk_ofs;
+				init_alloc_info(fs, &dp->obj);	/* Open next directory */
+			} else
+#endif
+			{
+				dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs));	/* Open next directory */
+			}
+		}
+	}
+
+	return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get logical drive number from path name                               */
+/*-----------------------------------------------------------------------*/
+
+static int get_ldnumber (	/* Returns logical drive number (-1:invalid drive number or null pointer) */
+	const TCHAR** path		/* Pointer to pointer to the path name */
+)
+{
+	const TCHAR *tp, *tt;
+	TCHAR tc;
+	int i, vol = -1;
+#if FF_STR_VOLUME_ID		/* Find string volume ID */
+	const char *sp;
+	char c;
+#endif
+
+	tt = tp = *path;
+	if (!tp) return vol;	/* Invalid path name? */
+	do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':');	/* Find a colon in the path */
+
+	if (tc == ':') {	/* DOS/Windows style volume ID? */
+		i = FF_VOLUMES;
+		if (IsDigit(*tp) && tp + 2 == tt) {	/* Is there a numeric volume ID + colon? */
+			i = (int)*tp - '0';	/* Get the LD number */
+		}
+#if FF_STR_VOLUME_ID == 1	/* Arbitrary string is enabled */
+		else {
+			i = 0;
+			do {
+				sp = VolumeStr[i]; tp = *path;	/* This string volume ID and path name */
+				do {	/* Compare the volume ID with path name */
+					c = *sp++; tc = *tp++;
+					if (IsLower(c)) c -= 0x20;
+					if (IsLower(tc)) tc -= 0x20;
+				} while (c && (TCHAR)c == tc);
+			} while ((c || tp != tt) && ++i < FF_VOLUMES);	/* Repeat for each id until pattern match */
+		}
+#endif
+		if (i < FF_VOLUMES) {	/* If a volume ID is found, get the drive number and strip it */
+			vol = i;		/* Drive number */
+			*path = tt;		/* Snip the drive prefix off */
+		}
+		return vol;
+	}
+#if FF_STR_VOLUME_ID == 2		/* Unix style volume ID is enabled */
+	if (*tp == '/') {
+		i = 0;
+		do {
+			sp = VolumeStr[i]; tp = *path;	/* This string volume ID and path name */
+			do {	/* Compare the volume ID with path name */
+				c = *sp++; tc = *(++tp);
+				if (IsLower(c)) c -= 0x20;
+				if (IsLower(tc)) tc -= 0x20;
+			} while (c && (TCHAR)c == tc);
+		} while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES);	/* Repeat for each ID until pattern match */
+		if (i < FF_VOLUMES) {	/* If a volume ID is found, get the drive number and strip it */
+			vol = i;		/* Drive number */
+			*path = tp;		/* Snip the drive prefix off */
+			return vol;
+		}
+	}
+#endif
+	/* No drive prefix is found */
+#if FF_FS_RPATH != 0
+	vol = CurrVol;	/* Default drive is current drive */
+#else
+	vol = 0;		/* Default drive is 0 */
+#endif
+	return vol;		/* Return the default drive */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Load a sector and check if it is an FAT VBR                           */
+/*-----------------------------------------------------------------------*/
+
+static BYTE check_fs (	/* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */
+	FATFS* fs,			/* Filesystem object */
+	DWORD sect			/* Sector# (lba) to load and check if it is an FAT-VBR or not */
+)
+{
+	fs->wflag = 0; fs->winsect = 0xFFFFFFFF;		/* Invaidate window */
+	if (move_window(fs, sect) != FR_OK) return 4;	/* Load boot record */
+
+	if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3;	/* Check boot record signature (always here regardless of the sector size) */
+
+#if FF_FS_EXFAT
+	if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT   ", 11)) return 1;	/* Check if exFAT VBR */
+#endif
+	if (fs->win[BS_JmpBoot] == 0xE9 || fs->win[BS_JmpBoot] == 0xEB || fs->win[BS_JmpBoot] == 0xE8) {	/* Valid JumpBoot code? */
+		if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0;		/* Is it an FAT VBR? */
+		if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0;	/* Is it an FAT32 VBR? */
+	}
+	return 2;	/* Valid BS but not FAT */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Determine logical drive number and mount the volume if needed         */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT find_volume (	/* FR_OK(0): successful, !=0: an error occurred */
+	const TCHAR** path,			/* Pointer to pointer to the path name (drive number) */
+	FATFS** rfs,				/* Pointer to pointer to the found filesystem object */
+	BYTE mode					/* !=0: Check write protection for write access */
+)
+{
+	BYTE fmt, *pt;
+	int vol;
+	DSTATUS stat;
+	DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
+	WORD nrsv;
+	FATFS *fs;
+	UINT i;
+
+
+	/* Get logical drive number */
+	*rfs = 0;
+	vol = get_ldnumber(path);
+	if (vol < 0) return FR_INVALID_DRIVE;
+
+	/* Check if the filesystem object is valid or not */
+	fs = FatFs[vol];					/* Get pointer to the filesystem object */
+	if (!fs) return FR_NOT_ENABLED;		/* Is the filesystem object available? */
+#if FF_FS_REENTRANT
+	if (!lock_fs(fs)) return FR_TIMEOUT;	/* Lock the volume */
+#endif
+	*rfs = fs;							/* Return pointer to the filesystem object */
+
+	mode &= (BYTE)~FA_READ;				/* Desired access mode, write access or not */
+	if (fs->fs_type != 0) {				/* If the volume has been mounted */
+		stat = disk_status(fs->pdrv);
+		if (!(stat & STA_NOINIT)) {		/* and the physical drive is kept initialized */
+			if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) {	/* Check write protection if needed */
+				return FR_WRITE_PROTECTED;
+			}
+			return FR_OK;				/* The filesystem object is valid */
+		}
+	}
+
+	/* The filesystem object is not valid. */
+	/* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */
+
+	fs->fs_type = 0;					/* Clear the filesystem object */
+	fs->pdrv = LD2PD(vol);				/* Bind the logical drive and a physical drive */
+	stat = disk_initialize(fs->pdrv);	/* Initialize the physical drive */
+	if (stat & STA_NOINIT) { 			/* Check if the initialization succeeded */
+		return FR_NOT_READY;			/* Failed to initialize due to no medium or hard error */
+	}
+	if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
+		return FR_WRITE_PROTECTED;
+	}
+#if FF_MAX_SS != FF_MIN_SS				/* Get sector size (multiple sector size cfg only) */
+	if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
+	if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
+#endif
+
+	/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */
+	bsect = 0;
+	fmt = check_fs(fs, bsect);			/* Load sector 0 and check if it is an FAT-VBR as SFD */
+	if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) {	/* Not an FAT-VBR or forced partition number */
+		for (i = 0; i < 4; i++) {		/* Get partition offset */
+			pt = fs->win + (MBR_Table + i * SZ_PTE);
+			br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0;
+		}
+		i = LD2PT(vol);					/* Partition number: 0:auto, 1-4:forced */
+		if (i != 0) i--;
+		do {							/* Find an FAT volume */
+			bsect = br[i];
+			fmt = bsect ? check_fs(fs, bsect) : 3;	/* Check the partition */
+		} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
+	}
+	if (fmt == 4) return FR_DISK_ERR;		/* An error occured in the disk I/O layer */
+	if (fmt >= 2) return FR_NO_FILESYSTEM;	/* No FAT volume is found */
+
+	/* An FAT volume is found (bsect). Following code initializes the filesystem object */
+
+#if FF_FS_EXFAT
+	if (fmt == 1) {
+		QWORD maxlba;
+		DWORD so, cv, bcl;
+
+		for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ;	/* Check zero filler */
+		if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
+
+		if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM;	/* Check exFAT version (must be version 1.0) */
+
+		if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) {	/* (BPB_BytsPerSecEx must be equal to the physical sector size) */
+			return FR_NO_FILESYSTEM;
+		}
+
+		maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect;	/* Last LBA + 1 of the volume */
+		if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM;	/* (It cannot be handled in 32-bit LBA) */
+
+		fs->fsize = ld_dword(fs->win + BPB_FatSzEx);	/* Number of sectors per FAT */
+
+		fs->n_fats = fs->win[BPB_NumFATsEx];			/* Number of FATs */
+		if (fs->n_fats != 1) return FR_NO_FILESYSTEM;	/* (Supports only 1 FAT) */
+
+		fs->csize = 1 << fs->win[BPB_SecPerClusEx];		/* Cluster size */
+		if (fs->csize == 0)	return FR_NO_FILESYSTEM;	/* (Must be 1..32768) */
+
+		nclst = ld_dword(fs->win + BPB_NumClusEx);		/* Number of clusters */
+		if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM;	/* (Too many clusters) */
+		fs->n_fatent = nclst + 2;
+
+		/* Boundaries and Limits */
+		fs->volbase = bsect;
+		fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
+		fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
+		if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM;	/* (Volume size must not be smaller than the size requiered) */
+		fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
+
+		/* Get bitmap location and check if it is contiguous (implementation assumption) */
+		so = i = 0;
+		for (;;) {	/* Find the bitmap entry in the root directory (in only first cluster) */
+			if (i == 0) {
+				if (so >= fs->csize) return FR_NO_FILESYSTEM;	/* Not found? */
+				if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) return FR_DISK_ERR;
+				so++;
+			}
+			if (fs->win[i] == ET_BITMAP) break;				/* Is it a bitmap entry? */
+			i = (i + SZDIRE) % SS(fs);	/* Next entry */
+		}
+		bcl = ld_dword(fs->win + i + 20);					/* Bitmap cluster */
+		if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM;
+		fs->bitbase = fs->database + fs->csize * (bcl - 2);	/* Bitmap sector */
+		for (;;) {	/* Check if bitmap is contiguous */
+			if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
+			cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
+			if (cv == 0xFFFFFFFF) break;				/* Last link? */
+			if (cv != ++bcl) return FR_NO_FILESYSTEM;	/* Fragmented? */
+		}
+
+#if !FF_FS_READONLY
+		fs->last_clst = fs->free_clst = 0xFFFFFFFF;		/* Initialize cluster allocation information */
+#endif
+		fmt = FS_EXFAT;			/* FAT sub-type */
+	} else
+#endif	/* FF_FS_EXFAT */
+	{
+		if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_BytsPerSec must be equal to the physical sector size) */
+
+		fasize = ld_word(fs->win + BPB_FATSz16);		/* Number of sectors per FAT */
+		if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
+		fs->fsize = fasize;
+
+		fs->n_fats = fs->win[BPB_NumFATs];				/* Number of FATs */
+		if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM;	/* (Must be 1 or 2) */
+		fasize *= fs->n_fats;							/* Number of sectors for FAT area */
+
+		fs->csize = fs->win[BPB_SecPerClus];			/* Cluster size */
+		if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM;	/* (Must be power of 2) */
+
+		fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt);	/* Number of root directory entries */
+		if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM;	/* (Must be sector aligned) */
+
+		tsect = ld_word(fs->win + BPB_TotSec16);		/* Number of sectors on the volume */
+		if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
+
+		nrsv = ld_word(fs->win + BPB_RsvdSecCnt);		/* Number of reserved sectors */
+		if (nrsv == 0) return FR_NO_FILESYSTEM;			/* (Must not be 0) */
+
+		/* Determine the FAT sub type */
+		sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE);	/* RSV + FAT + DIR */
+		if (tsect < sysect) return FR_NO_FILESYSTEM;	/* (Invalid volume size) */
+		nclst = (tsect - sysect) / fs->csize;			/* Number of clusters */
+		if (nclst == 0) return FR_NO_FILESYSTEM;		/* (Invalid volume size) */
+		fmt = 0;
+		if (nclst <= MAX_FAT32) fmt = FS_FAT32;
+		if (nclst <= MAX_FAT16) fmt = FS_FAT16;
+		if (nclst <= MAX_FAT12) fmt = FS_FAT12;
+		if (fmt == 0) return FR_NO_FILESYSTEM;
+
+		/* Boundaries and Limits */
+		fs->n_fatent = nclst + 2;						/* Number of FAT entries */
+		fs->volbase = bsect;							/* Volume start sector */
+		fs->fatbase = bsect + nrsv; 					/* FAT start sector */
+		fs->database = bsect + sysect;					/* Data start sector */
+		if (fmt == FS_FAT32) {
+			if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM;	/* (Must be FAT32 revision 0.0) */
+			if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must be 0) */
+			fs->dirbase = ld_dword(fs->win + BPB_RootClus32);	/* Root directory start cluster */
+			szbfat = fs->n_fatent * 4;					/* (Needed FAT size) */
+		} else {
+			if (fs->n_rootdir == 0)	return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must not be 0) */
+			fs->dirbase = fs->fatbase + fasize;			/* Root directory start sector */
+			szbfat = (fmt == FS_FAT16) ?				/* (Needed FAT size) */
+				fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
+		}
+		if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_FATSz must not be less than the size needed) */
+
+#if !FF_FS_READONLY
+		/* Get FSInfo if available */
+		fs->last_clst = fs->free_clst = 0xFFFFFFFF;		/* Initialize cluster allocation information */
+		fs->fsi_flag = 0x80;
+#if (FF_FS_NOFSINFO & 3) != 3
+		if (fmt == FS_FAT32				/* Allow to update FSInfo only if BPB_FSInfo32 == 1 */
+			&& ld_word(fs->win + BPB_FSInfo32) == 1
+			&& move_window(fs, bsect + 1) == FR_OK)
+		{
+			fs->fsi_flag = 0;
+			if (ld_word(fs->win + BS_55AA) == 0xAA55	/* Load FSInfo data if available */
+				&& ld_dword(fs->win + FSI_LeadSig) == 0x41615252
+				&& ld_dword(fs->win + FSI_StrucSig) == 0x61417272)
+			{
+#if (FF_FS_NOFSINFO & 1) == 0
+				fs->free_clst = ld_dword(fs->win + FSI_Free_Count);
+#endif
+#if (FF_FS_NOFSINFO & 2) == 0
+				fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free);
+#endif
+			}
+		}
+#endif	/* (FF_FS_NOFSINFO & 3) != 3 */
+#endif	/* !FF_FS_READONLY */
+	}
+
+	fs->fs_type = fmt;		/* FAT sub-type */
+	fs->id = ++Fsid;		/* Volume mount ID */
+#if FF_USE_LFN == 1
+	fs->lfnbuf = LfnBuf;	/* Static LFN working buffer */
+#if FF_FS_EXFAT
+	fs->dirbuf = DirBuf;	/* Static directory block scratchpad buuffer */
+#endif
+#endif
+#if FF_FS_RPATH != 0
+	fs->cdir = 0;			/* Initialize current directory */
+#endif
+#if FF_FS_LOCK != 0			/* Clear file lock semaphores */
+	clear_lock(fs);
+#endif
+	return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Check if the file/directory object is valid or not                    */
+/*-----------------------------------------------------------------------*/
+
+static FRESULT validate (	/* Returns FR_OK or FR_INVALID_OBJECT */
+	FFOBJID* obj,			/* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */
+	FATFS** rfs				/* Pointer to pointer to the owner filesystem object to return */
+)
+{
+	FRESULT res = FR_INVALID_OBJECT;
+
+
+	if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) {	/* Test if the object is valid */
+#if FF_FS_REENTRANT
+		if (lock_fs(obj->fs)) {	/* Obtain the filesystem object */
+			if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
+				res = FR_OK;
+			} else {
+				unlock_fs(obj->fs, FR_OK);
+			}
+		} else {
+			res = FR_TIMEOUT;
+		}
+#else
+		if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */
+			res = FR_OK;
+		}
+#endif
+	}
+	*rfs = (res == FR_OK) ? obj->fs : 0;	/* Corresponding filesystem object */
+	return res;
+}
+
+
+
+
+/*---------------------------------------------------------------------------
+
+   Public Functions (FatFs API)
+
+----------------------------------------------------------------------------*/
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Mount/Unmount a Logical Drive                                         */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_mount (
+	FATFS* fs,			/* Pointer to the filesystem object (NULL:unmount)*/
+	const TCHAR* path,	/* Logical drive number to be mounted/unmounted */
+	BYTE opt			/* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */
+)
+{
+	FATFS *cfs;
+	int vol;
+	FRESULT res;
+	const TCHAR *rp = path;
+
+
+	/* Get logical drive number */
+	vol = get_ldnumber(&rp);
+	if (vol < 0) return FR_INVALID_DRIVE;
+	cfs = FatFs[vol];					/* Pointer to fs object */
+
+	if (cfs) {
+#if FF_FS_LOCK != 0
+		clear_lock(cfs);
+#endif
+#if FF_FS_REENTRANT						/* Discard sync object of the current volume */
+		if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
+#endif
+		cfs->fs_type = 0;				/* Clear old fs object */
+	}
+
+	if (fs) {
+		fs->fs_type = 0;				/* Clear new fs object */
+#if FF_FS_REENTRANT						/* Create sync object for the new volume */
+		if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR;
+#endif
+	}
+	FatFs[vol] = fs;					/* Register new fs object */
+
+	if (opt == 0) return FR_OK;			/* Do not mount now, it will be mounted later */
+
+	res = find_volume(&path, &fs, 0);	/* Force mounted the volume */
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Open or Create a File                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_open (
+	FIL* fp,			/* Pointer to the blank file object */
+	const TCHAR* path,	/* Pointer to the file name */
+	BYTE mode			/* Access mode and file open mode flags */
+)
+{
+	FRESULT res;
+	DIR dj;
+	FATFS *fs;
+#if !FF_FS_READONLY
+	DWORD dw, cl, bcs, clst, sc;
+	FSIZE_t ofs;
+#endif
+	DEF_NAMBUF
+
+
+	if (!fp) return FR_INVALID_OBJECT;
+
+	/* Get logical drive number */
+	mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND;
+	res = find_volume(&path, &fs, mode);
+	if (res == FR_OK) {
+		dj.obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(&dj, path);	/* Follow the file path */
+#if !FF_FS_READONLY	/* Read/Write configuration */
+		if (res == FR_OK) {
+			if (dj.fn[NSFLAG] & NS_NONAME) {	/* Origin directory itself? */
+				res = FR_INVALID_NAME;
+			}
+#if FF_FS_LOCK != 0
+			else {
+				res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);		/* Check if the file can be used */
+			}
+#endif
+		}
+		/* Create or Open a file */
+		if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
+			if (res != FR_OK) {					/* No file, create new */
+				if (res == FR_NO_FILE) {		/* There is no file to open, create a new entry */
+#if FF_FS_LOCK != 0
+					res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
+#else
+					res = dir_register(&dj);
+#endif
+				}
+				mode |= FA_CREATE_ALWAYS;		/* File is created */
+			}
+			else {								/* Any object with the same name is already existing */
+				if (dj.obj.attr & (AM_RDO | AM_DIR)) {	/* Cannot overwrite it (R/O or DIR) */
+					res = FR_DENIED;
+				} else {
+					if (mode & FA_CREATE_NEW) res = FR_EXIST;	/* Cannot create as new file */
+				}
+			}
+			if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {	/* Truncate the file if overwrite mode */
+#if FF_FS_EXFAT
+				if (fs->fs_type == FS_EXFAT) {
+					/* Get current allocation info */
+					fp->obj.fs = fs;
+					init_alloc_info(fs, &fp->obj);
+					/* Set directory entry block initial state */
+					mem_set(fs->dirbuf + 2, 0, 30);		/* Clear 85 entry except for NumSec */
+					mem_set(fs->dirbuf + 38, 0, 26);	/* Clear C0 entry except for NumName and NameHash */
+					fs->dirbuf[XDIR_Attr] = AM_ARC;
+					st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME());
+					fs->dirbuf[XDIR_GenFlags] = 1;
+					res = store_xdir(&dj);
+					if (res == FR_OK && fp->obj.sclust != 0) {	/* Remove the cluster chain if exist */
+						res = remove_chain(&fp->obj, fp->obj.sclust, 0);
+						fs->last_clst = fp->obj.sclust - 1;		/* Reuse the cluster hole */
+					}
+				} else
+#endif
+				{
+					/* Set directory entry initial state */
+					cl = ld_clust(fs, dj.dir);			/* Get current cluster chain */
+					st_dword(dj.dir + DIR_CrtTime, GET_FATTIME());	/* Set created time */
+					dj.dir[DIR_Attr] = AM_ARC;			/* Reset attribute */
+					st_clust(fs, dj.dir, 0);			/* Reset file allocation info */
+					st_dword(dj.dir + DIR_FileSize, 0);
+					fs->wflag = 1;
+					if (cl != 0) {						/* Remove the cluster chain if exist */
+						dw = fs->winsect;
+						res = remove_chain(&dj.obj, cl, 0);
+						if (res == FR_OK) {
+							res = move_window(fs, dw);
+							fs->last_clst = cl - 1;		/* Reuse the cluster hole */
+						}
+					}
+				}
+			}
+		}
+		else {	/* Open an existing file */
+			if (res == FR_OK) {					/* Is the object exsiting? */
+				if (dj.obj.attr & AM_DIR) {		/* File open against a directory */
+					res = FR_NO_FILE;
+				} else {
+					if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */
+						res = FR_DENIED;
+					}
+				}
+			}
+		}
+		if (res == FR_OK) {
+			if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED;	/* Set file change flag if created or overwritten */
+			fp->dir_sect = fs->winsect;			/* Pointer to the directory entry */
+			fp->dir_ptr = dj.dir;
+#if FF_FS_LOCK != 0
+			fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);	/* Lock the file for this session */
+			if (fp->obj.lockid == 0) res = FR_INT_ERR;
+#endif
+		}
+#else		/* R/O configuration */
+		if (res == FR_OK) {
+			if (dj.fn[NSFLAG] & NS_NONAME) {	/* Is it origin directory itself? */
+				res = FR_INVALID_NAME;
+			} else {
+				if (dj.obj.attr & AM_DIR) {		/* Is it a directory? */
+					res = FR_NO_FILE;
+				}
+			}
+		}
+#endif
+
+		if (res == FR_OK) {
+#if FF_FS_EXFAT
+			if (fs->fs_type == FS_EXFAT) {
+				fp->obj.c_scl = dj.obj.sclust;							/* Get containing directory info */
+				fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
+				fp->obj.c_ofs = dj.blk_ofs;
+				init_alloc_info(fs, &fp->obj);
+			} else
+#endif
+			{
+				fp->obj.sclust = ld_clust(fs, dj.dir);					/* Get object allocation info */
+				fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize);
+			}
+#if FF_USE_FASTSEEK
+			fp->cltbl = 0;			/* Disable fast seek mode */
+#endif
+			fp->obj.fs = fs;	 	/* Validate the file object */
+			fp->obj.id = fs->id;
+			fp->flag = mode;		/* Set file access mode */
+			fp->err = 0;			/* Clear error flag */
+			fp->sect = 0;			/* Invalidate current data sector */
+			fp->fptr = 0;			/* Set file pointer top of the file */
+#if !FF_FS_READONLY
+#if !FF_FS_TINY
+			mem_set(fp->buf, 0, sizeof fp->buf);	/* Clear sector buffer */
+#endif
+			if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) {	/* Seek to end of file if FA_OPEN_APPEND is specified */
+				fp->fptr = fp->obj.objsize;			/* Offset to seek */
+				bcs = (DWORD)fs->csize * SS(fs);	/* Cluster size in byte */
+				clst = fp->obj.sclust;				/* Follow the cluster chain */
+				for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) {
+					clst = get_fat(&fp->obj, clst);
+					if (clst <= 1) res = FR_INT_ERR;
+					if (clst == 0xFFFFFFFF) res = FR_DISK_ERR;
+				}
+				fp->clust = clst;
+				if (res == FR_OK && ofs % SS(fs)) {	/* Fill sector buffer if not on the sector boundary */
+					if ((sc = clst2sect(fs, clst)) == 0) {
+						res = FR_INT_ERR;
+					} else {
+						fp->sect = sc + (DWORD)(ofs / SS(fs));
+#if !FF_FS_TINY
+						if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR;
+#endif
+					}
+				}
+			}
+#endif
+		}
+
+		FREE_NAMBUF();
+	}
+
+	if (res != FR_OK) fp->obj.fs = 0;	/* Invalidate file object on error */
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read File                                                             */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_read (
+	FIL* fp, 	/* Pointer to the file object */
+	void* buff,	/* Pointer to data buffer */
+	UINT btr,	/* Number of bytes to read */
+	UINT* br	/* Pointer to number of bytes read */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD clst, sect;
+	FSIZE_t remain;
+	UINT rcnt, cc, csect;
+	BYTE *rbuff = (BYTE*)buff;
+
+
+	*br = 0;	/* Clear read byte counter */
+	res = validate(&fp->obj, &fs);				/* Check validity of the file object */
+	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);	/* Check validity */
+	if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
+	remain = fp->obj.objsize - fp->fptr;
+	if (btr > remain) btr = (UINT)remain;		/* Truncate btr by remaining bytes */
+
+	for ( ;  btr;								/* Repeat until btr bytes read */
+		btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) {
+		if (fp->fptr % SS(fs) == 0) {			/* On the sector boundary? */
+			csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));	/* Sector offset in the cluster */
+			if (csect == 0) {					/* On the cluster boundary? */
+				if (fp->fptr == 0) {			/* On the top of the file? */
+					clst = fp->obj.sclust;		/* Follow cluster chain from the origin */
+				} else {						/* Middle or end of the file */
+#if FF_USE_FASTSEEK
+					if (fp->cltbl) {
+						clst = clmt_clust(fp, fp->fptr);	/* Get cluster# from the CLMT */
+					} else
+#endif
+					{
+						clst = get_fat(&fp->obj, fp->clust);	/* Follow cluster chain on the FAT */
+					}
+				}
+				if (clst < 2) ABORT(fs, FR_INT_ERR);
+				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
+				fp->clust = clst;				/* Update current cluster */
+			}
+			sect = clst2sect(fs, fp->clust);	/* Get current sector */
+			if (sect == 0) ABORT(fs, FR_INT_ERR);
+			sect += csect;
+			cc = btr / SS(fs);					/* When remaining bytes >= sector size, */
+			if (cc > 0) {						/* Read maximum contiguous sectors directly */
+				if (csect + cc > fs->csize) {	/* Clip at cluster boundary */
+					cc = fs->csize - csect;
+				}
+				if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
+#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2		/* Replace one of the read sectors with cached data if it contains a dirty sector */
+#if FF_FS_TINY
+				if (fs->wflag && fs->winsect - sect < cc) {
+					mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
+				}
+#else
+				if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) {
+					mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
+				}
+#endif
+#endif
+				rcnt = SS(fs) * cc;				/* Number of bytes transferred */
+				continue;
+			}
+#if !FF_FS_TINY
+			if (fp->sect != sect) {			/* Load data sector if not in cache */
+#if !FF_FS_READONLY
+				if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
+					if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
+					fp->flag &= (BYTE)~FA_DIRTY;
+				}
+#endif
+				if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK)	ABORT(fs, FR_DISK_ERR);	/* Fill sector cache */
+			}
+#endif
+			fp->sect = sect;
+		}
+		rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes left in the sector */
+		if (rcnt > btr) rcnt = btr;					/* Clip it by btr if needed */
+#if FF_FS_TINY
+		if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window */
+		mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt);	/* Extract partial sector */
+#else
+		mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt);	/* Extract partial sector */
+#endif
+	}
+
+	LEAVE_FF(fs, FR_OK);
+}
+
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Write File                                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_write (
+	FIL* fp,			/* Pointer to the file object */
+	const void* buff,	/* Pointer to the data to be written */
+	UINT btw,			/* Number of bytes to write */
+	UINT* bw			/* Pointer to number of bytes written */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD clst, sect;
+	UINT wcnt, cc, csect;
+	const BYTE *wbuff = (const BYTE*)buff;
+
+
+	*bw = 0;	/* Clear write byte counter */
+	res = validate(&fp->obj, &fs);			/* Check validity of the file object */
+	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);	/* Check validity */
+	if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */
+
+	/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
+	if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
+		btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
+	}
+
+	for ( ;  btw;							/* Repeat until all data written */
+		btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) {
+		if (fp->fptr % SS(fs) == 0) {		/* On the sector boundary? */
+			csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1);	/* Sector offset in the cluster */
+			if (csect == 0) {				/* On the cluster boundary? */
+				if (fp->fptr == 0) {		/* On the top of the file? */
+					clst = fp->obj.sclust;	/* Follow from the origin */
+					if (clst == 0) {		/* If no cluster is allocated, */
+						clst = create_chain(&fp->obj, 0);	/* create a new cluster chain */
+					}
+				} else {					/* On the middle or end of the file */
+#if FF_USE_FASTSEEK
+					if (fp->cltbl) {
+						clst = clmt_clust(fp, fp->fptr);	/* Get cluster# from the CLMT */
+					} else
+#endif
+					{
+						clst = create_chain(&fp->obj, fp->clust);	/* Follow or stretch cluster chain on the FAT */
+					}
+				}
+				if (clst == 0) break;		/* Could not allocate a new cluster (disk full) */
+				if (clst == 1) ABORT(fs, FR_INT_ERR);
+				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
+				fp->clust = clst;			/* Update current cluster */
+				if (fp->obj.sclust == 0) fp->obj.sclust = clst;	/* Set start cluster if the first write */
+			}
+#if FF_FS_TINY
+			if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Write-back sector cache */
+#else
+			if (fp->flag & FA_DIRTY) {		/* Write-back sector cache */
+				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
+				fp->flag &= (BYTE)~FA_DIRTY;
+			}
+#endif
+			sect = clst2sect(fs, fp->clust);	/* Get current sector */
+			if (sect == 0) ABORT(fs, FR_INT_ERR);
+			sect += csect;
+			cc = btw / SS(fs);				/* When remaining bytes >= sector size, */
+			if (cc > 0) {					/* Write maximum contiguous sectors directly */
+				if (csect + cc > fs->csize) {	/* Clip at cluster boundary */
+					cc = fs->csize - csect;
+				}
+				if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
+#if FF_FS_MINIMIZE <= 2
+#if FF_FS_TINY
+				if (fs->winsect - sect < cc) {	/* Refill sector cache if it gets invalidated by the direct write */
+					mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
+					fs->wflag = 0;
+				}
+#else
+				if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
+					mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
+					fp->flag &= (BYTE)~FA_DIRTY;
+				}
+#endif
+#endif
+				wcnt = SS(fs) * cc;		/* Number of bytes transferred */
+				continue;
+			}
+#if FF_FS_TINY
+			if (fp->fptr >= fp->obj.objsize) {	/* Avoid silly cache filling on the growing edge */
+				if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);
+				fs->winsect = sect;
+			}
+#else
+			if (fp->sect != sect && 		/* Fill sector cache with file data */
+				fp->fptr < fp->obj.objsize &&
+				disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
+					ABORT(fs, FR_DISK_ERR);
+			}
+#endif
+			fp->sect = sect;
+		}
+		wcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes left in the sector */
+		if (wcnt > btw) wcnt = btw;					/* Clip it by btw if needed */
+#if FF_FS_TINY
+		if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window */
+		mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt);	/* Fit data to the sector */
+		fs->wflag = 1;
+#else
+		mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt);	/* Fit data to the sector */
+		fp->flag |= FA_DIRTY;
+#endif
+	}
+
+	fp->flag |= FA_MODIFIED;				/* Set file change flag */
+
+	LEAVE_FF(fs, FR_OK);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Synchronize the File                                                  */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_sync (
+	FIL* fp		/* Pointer to the file object */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD tm;
+	BYTE *dir;
+
+
+	res = validate(&fp->obj, &fs);	/* Check validity of the file object */
+	if (res == FR_OK) {
+		if (fp->flag & FA_MODIFIED) {	/* Is there any change to the file? */
+#if !FF_FS_TINY
+			if (fp->flag & FA_DIRTY) {	/* Write-back cached data if needed */
+				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
+				fp->flag &= (BYTE)~FA_DIRTY;
+			}
+#endif
+			/* Update the directory entry */
+			tm = GET_FATTIME();				/* Modified time */
+#if FF_FS_EXFAT
+			if (fs->fs_type == FS_EXFAT) {
+				res = fill_first_frag(&fp->obj);	/* Fill first fragment on the FAT if needed */
+				if (res == FR_OK) {
+					res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
+				}
+				if (res == FR_OK) {
+					DIR dj;
+					DEF_NAMBUF
+
+					INIT_NAMBUF(fs);
+					res = load_obj_xdir(&dj, &fp->obj);	/* Load directory entry block */
+					if (res == FR_OK) {
+						fs->dirbuf[XDIR_Attr] |= AM_ARC;				/* Set archive attribute to indicate that the file has been changed */
+						fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1;	/* Update file allocation information */
+						st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust);
+						st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize);
+						st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize);
+						st_dword(fs->dirbuf + XDIR_ModTime, tm);		/* Update modified time */
+						fs->dirbuf[XDIR_ModTime10] = 0;
+						st_dword(fs->dirbuf + XDIR_AccTime, 0);
+						res = store_xdir(&dj);	/* Restore it to the directory */
+						if (res == FR_OK) {
+							res = sync_fs(fs);
+							fp->flag &= (BYTE)~FA_MODIFIED;
+						}
+					}
+					FREE_NAMBUF();
+				}
+			} else
+#endif
+			{
+				res = move_window(fs, fp->dir_sect);
+				if (res == FR_OK) {
+					dir = fp->dir_ptr;
+					dir[DIR_Attr] |= AM_ARC;						/* Set archive attribute to indicate that the file has been changed */
+					st_clust(fp->obj.fs, dir, fp->obj.sclust);		/* Update file allocation information  */
+					st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize);	/* Update file size */
+					st_dword(dir + DIR_ModTime, tm);				/* Update modified time */
+					st_word(dir + DIR_LstAccDate, 0);
+					fs->wflag = 1;
+					res = sync_fs(fs);					/* Restore it to the directory */
+					fp->flag &= (BYTE)~FA_MODIFIED;
+				}
+			}
+		}
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+#endif /* !FF_FS_READONLY */
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Close File                                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_close (
+	FIL* fp		/* Pointer to the file object to be closed */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+
+#if !FF_FS_READONLY
+	res = f_sync(fp);					/* Flush cached data */
+	if (res == FR_OK)
+#endif
+	{
+		res = validate(&fp->obj, &fs);	/* Lock volume */
+		if (res == FR_OK) {
+#if FF_FS_LOCK != 0
+			res = dec_lock(fp->obj.lockid);		/* Decrement file open counter */
+			if (res == FR_OK) fp->obj.fs = 0;	/* Invalidate file object */
+#else
+			fp->obj.fs = 0;	/* Invalidate file object */
+#endif
+#if FF_FS_REENTRANT
+			unlock_fs(fs, FR_OK);		/* Unlock volume */
+#endif
+		}
+	}
+	return res;
+}
+
+
+
+
+#if FF_FS_RPATH >= 1
+/*-----------------------------------------------------------------------*/
+/* Change Current Directory or Current Drive, Get Current Directory      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_chdrive (
+	const TCHAR* path		/* Drive number to set */
+)
+{
+	int vol;
+
+
+	/* Get logical drive number */
+	vol = get_ldnumber(&path);
+	if (vol < 0) return FR_INVALID_DRIVE;
+	CurrVol = (BYTE)vol;	/* Set it as current volume */
+
+	return FR_OK;
+}
+
+
+
+FRESULT f_chdir (
+	const TCHAR* path	/* Pointer to the directory path */
+)
+{
+#if FF_STR_VOLUME_ID == 2
+	UINT i;
+#endif
+	FRESULT res;
+	DIR dj;
+	FATFS *fs;
+	DEF_NAMBUF
+
+
+	/* Get logical drive */
+	res = find_volume(&path, &fs, 0);
+	if (res == FR_OK) {
+		dj.obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(&dj, path);		/* Follow the path */
+		if (res == FR_OK) {					/* Follow completed */
+			if (dj.fn[NSFLAG] & NS_NONAME) {	/* Is it the start directory itself? */
+				fs->cdir = dj.obj.sclust;
+#if FF_FS_EXFAT
+				if (fs->fs_type == FS_EXFAT) {
+					fs->cdc_scl = dj.obj.c_scl;
+					fs->cdc_size = dj.obj.c_size;
+					fs->cdc_ofs = dj.obj.c_ofs;
+				}
+#endif
+			} else {
+				if (dj.obj.attr & AM_DIR) {	/* It is a sub-directory */
+#if FF_FS_EXFAT
+					if (fs->fs_type == FS_EXFAT) {
+						fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus);		/* Sub-directory cluster */
+						fs->cdc_scl = dj.obj.sclust;						/* Save containing directory information */
+						fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
+						fs->cdc_ofs = dj.blk_ofs;
+					} else
+#endif
+					{
+						fs->cdir = ld_clust(fs, dj.dir);					/* Sub-directory cluster */
+					}
+				} else {
+					res = FR_NO_PATH;		/* Reached but a file */
+				}
+			}
+		}
+		FREE_NAMBUF();
+		if (res == FR_NO_FILE) res = FR_NO_PATH;
+#if FF_STR_VOLUME_ID == 2	/* Also current drive is changed at Unix style volume ID */
+		if (res == FR_OK) {
+			for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ;	/* Set current drive */
+			CurrVol = (BYTE)i;
+		}
+#endif
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+#if FF_FS_RPATH >= 2
+FRESULT f_getcwd (
+	TCHAR* buff,	/* Pointer to the directory path */
+	UINT len		/* Size of buff in unit of TCHAR */
+)
+{
+	FRESULT res;
+	DIR dj;
+	FATFS *fs;
+	UINT i, n;
+	DWORD ccl;
+	TCHAR *tp = buff;
+#if FF_VOLUMES >= 2
+	UINT vl;
+#endif
+#if FF_STR_VOLUME_ID
+	const char *vp;
+#endif
+	FILINFO fno;
+	DEF_NAMBUF
+
+
+	/* Get logical drive */
+	buff[0] = 0;	/* Set null string to get current volume */
+	res = find_volume((const TCHAR**)&buff, &fs, 0);	/* Get current volume */
+	if (res == FR_OK) {
+		dj.obj.fs = fs;
+		INIT_NAMBUF(fs);
+
+		/* Follow parent directories and create the path */
+		i = len;			/* Bottom of buffer (directory stack base) */
+		if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {	/* (Cannot do getcwd on exFAT and returns root path) */
+			dj.obj.sclust = fs->cdir;				/* Start to follow upper directory from current directory */
+			while ((ccl = dj.obj.sclust) != 0) {	/* Repeat while current directory is a sub-directory */
+				res = dir_sdi(&dj, 1 * SZDIRE);	/* Get parent directory */
+				if (res != FR_OK) break;
+				res = move_window(fs, dj.sect);
+				if (res != FR_OK) break;
+				dj.obj.sclust = ld_clust(fs, dj.dir);	/* Goto parent directory */
+				res = dir_sdi(&dj, 0);
+				if (res != FR_OK) break;
+				do {							/* Find the entry links to the child directory */
+					res = DIR_READ_FILE(&dj);
+					if (res != FR_OK) break;
+					if (ccl == ld_clust(fs, dj.dir)) break;	/* Found the entry */
+					res = dir_next(&dj, 0);
+				} while (res == FR_OK);
+				if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
+				if (res != FR_OK) break;
+				get_fileinfo(&dj, &fno);		/* Get the directory name and push it to the buffer */
+				for (n = 0; fno.fname[n]; n++) ;	/* Name length */
+				if (i < n + 1) {	/* Insufficient space to store the path name? */
+					res = FR_NOT_ENOUGH_CORE; break;
+				}
+				while (n) buff[--i] = fno.fname[--n];	/* Stack the name */
+				buff[--i] = '/';
+			}
+		}
+		if (res == FR_OK) {
+			if (i == len) buff[--i] = '/';	/* Is it the root-directory? */
+#if FF_VOLUMES >= 2			/* Put drive prefix */
+			vl = 0;
+#if FF_STR_VOLUME_ID >= 1	/* String volume ID */
+			for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ;
+			if (i >= n + 2) {
+				if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/';
+				for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ;
+				if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':';
+				vl++;
+			}
+#else						/* Numeric volume ID */
+			if (i >= 3) {
+				*tp++ = (TCHAR)'0' + CurrVol;
+				*tp++ = (TCHAR)':';
+				vl = 2;
+			}
+#endif
+			if (vl == 0) res = FR_NOT_ENOUGH_CORE;
+#endif
+			/* Add current directory path */
+			if (res == FR_OK) {
+				do *tp++ = buff[i++]; while (i < len);	/* Copy stacked path string */
+			}
+		}
+		FREE_NAMBUF();
+	}
+
+	*tp = 0;
+	LEAVE_FF(fs, res);
+}
+
+#endif /* FF_FS_RPATH >= 2 */
+#endif /* FF_FS_RPATH >= 1 */
+
+
+
+#if FF_FS_MINIMIZE <= 2
+/*-----------------------------------------------------------------------*/
+/* Seek File Read/Write Pointer                                          */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_lseek (
+	FIL* fp,		/* Pointer to the file object */
+	FSIZE_t ofs		/* File pointer from top of file */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD clst, bcs, nsect;
+	FSIZE_t ifptr;
+#if FF_USE_FASTSEEK
+	DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
+#endif
+
+	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
+	if (res == FR_OK) res = (FRESULT)fp->err;
+#if FF_FS_EXFAT && !FF_FS_READONLY
+	if (res == FR_OK && fs->fs_type == FS_EXFAT) {
+		res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
+	}
+#endif
+	if (res != FR_OK) LEAVE_FF(fs, res);
+
+#if FF_USE_FASTSEEK
+	if (fp->cltbl) {	/* Fast seek */
+		if (ofs == CREATE_LINKMAP) {	/* Create CLMT */
+			tbl = fp->cltbl;
+			tlen = *tbl++; ulen = 2;	/* Given table size and required table size */
+			cl = fp->obj.sclust;		/* Origin of the chain */
+			if (cl != 0) {
+				do {
+					/* Get a fragment */
+					tcl = cl; ncl = 0; ulen += 2;	/* Top, length and used items */
+					do {
+						pcl = cl; ncl++;
+						cl = get_fat(&fp->obj, cl);
+						if (cl <= 1) ABORT(fs, FR_INT_ERR);
+						if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
+					} while (cl == pcl + 1);
+					if (ulen <= tlen) {		/* Store the length and top of the fragment */
+						*tbl++ = ncl; *tbl++ = tcl;
+					}
+				} while (cl < fs->n_fatent);	/* Repeat until end of chain */
+			}
+			*fp->cltbl = ulen;	/* Number of items used */
+			if (ulen <= tlen) {
+				*tbl = 0;		/* Terminate table */
+			} else {
+				res = FR_NOT_ENOUGH_CORE;	/* Given table size is smaller than required */
+			}
+		} else {						/* Fast seek */
+			if (ofs > fp->obj.objsize) ofs = fp->obj.objsize;	/* Clip offset at the file size */
+			fp->fptr = ofs;				/* Set file pointer */
+			if (ofs > 0) {
+				fp->clust = clmt_clust(fp, ofs - 1);
+				dsc = clst2sect(fs, fp->clust);
+				if (dsc == 0) ABORT(fs, FR_INT_ERR);
+				dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1);
+				if (fp->fptr % SS(fs) && dsc != fp->sect) {	/* Refill sector cache if needed */
+#if !FF_FS_TINY
+#if !FF_FS_READONLY
+					if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
+						if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
+						fp->flag &= (BYTE)~FA_DIRTY;
+					}
+#endif
+					if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);	/* Load current sector */
+#endif
+					fp->sect = dsc;
+				}
+			}
+		}
+	} else
+#endif
+
+	/* Normal Seek */
+	{
+#if FF_FS_EXFAT
+		if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF;	/* Clip at 4 GiB - 1 if at FATxx */
+#endif
+		if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) {	/* In read-only mode, clip offset with the file size */
+			ofs = fp->obj.objsize;
+		}
+		ifptr = fp->fptr;
+		fp->fptr = nsect = 0;
+		if (ofs > 0) {
+			bcs = (DWORD)fs->csize * SS(fs);	/* Cluster size (byte) */
+			if (ifptr > 0 &&
+				(ofs - 1) / bcs >= (ifptr - 1) / bcs) {	/* When seek to same or following cluster, */
+				fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1);	/* start from the current cluster */
+				ofs -= fp->fptr;
+				clst = fp->clust;
+			} else {									/* When seek to back cluster, */
+				clst = fp->obj.sclust;					/* start from the first cluster */
+#if !FF_FS_READONLY
+				if (clst == 0) {						/* If no cluster chain, create a new chain */
+					clst = create_chain(&fp->obj, 0);
+					if (clst == 1) ABORT(fs, FR_INT_ERR);
+					if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
+					fp->obj.sclust = clst;
+				}
+#endif
+				fp->clust = clst;
+			}
+			if (clst != 0) {
+				while (ofs > bcs) {						/* Cluster following loop */
+					ofs -= bcs; fp->fptr += bcs;
+#if !FF_FS_READONLY
+					if (fp->flag & FA_WRITE) {			/* Check if in write mode or not */
+						if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) {	/* No FAT chain object needs correct objsize to generate FAT value */
+							fp->obj.objsize = fp->fptr;
+							fp->flag |= FA_MODIFIED;
+						}
+						clst = create_chain(&fp->obj, clst);	/* Follow chain with forceed stretch */
+						if (clst == 0) {				/* Clip file size in case of disk full */
+							ofs = 0; break;
+						}
+					} else
+#endif
+					{
+						clst = get_fat(&fp->obj, clst);	/* Follow cluster chain if not in write mode */
+					}
+					if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
+					if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR);
+					fp->clust = clst;
+				}
+				fp->fptr += ofs;
+				if (ofs % SS(fs)) {
+					nsect = clst2sect(fs, clst);	/* Current sector */
+					if (nsect == 0) ABORT(fs, FR_INT_ERR);
+					nsect += (DWORD)(ofs / SS(fs));
+				}
+			}
+		}
+		if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) {	/* Set file change flag if the file size is extended */
+			fp->obj.objsize = fp->fptr;
+			fp->flag |= FA_MODIFIED;
+		}
+		if (fp->fptr % SS(fs) && nsect != fp->sect) {	/* Fill sector cache if needed */
+#if !FF_FS_TINY
+#if !FF_FS_READONLY
+			if (fp->flag & FA_DIRTY) {			/* Write-back dirty sector cache */
+				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
+				fp->flag &= (BYTE)~FA_DIRTY;
+			}
+#endif
+			if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);	/* Fill sector cache */
+#endif
+			fp->sect = nsect;
+		}
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+#if FF_FS_MINIMIZE <= 1
+/*-----------------------------------------------------------------------*/
+/* Create a Directory Object                                             */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_opendir (
+	DIR* dp,			/* Pointer to directory object to create */
+	const TCHAR* path	/* Pointer to the directory path */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DEF_NAMBUF
+
+
+	if (!dp) return FR_INVALID_OBJECT;
+
+	/* Get logical drive */
+	res = find_volume(&path, &fs, 0);
+	if (res == FR_OK) {
+		dp->obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(dp, path);			/* Follow the path to the directory */
+		if (res == FR_OK) {						/* Follow completed */
+			if (!(dp->fn[NSFLAG] & NS_NONAME)) {	/* It is not the origin directory itself */
+				if (dp->obj.attr & AM_DIR) {		/* This object is a sub-directory */
+#if FF_FS_EXFAT
+					if (fs->fs_type == FS_EXFAT) {
+						dp->obj.c_scl = dp->obj.sclust;							/* Get containing directory inforamation */
+						dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
+						dp->obj.c_ofs = dp->blk_ofs;
+						init_alloc_info(fs, &dp->obj);	/* Get object allocation info */
+					} else
+#endif
+					{
+						dp->obj.sclust = ld_clust(fs, dp->dir);	/* Get object allocation info */
+					}
+				} else {						/* This object is a file */
+					res = FR_NO_PATH;
+				}
+			}
+			if (res == FR_OK) {
+				dp->obj.id = fs->id;
+				res = dir_sdi(dp, 0);			/* Rewind directory */
+#if FF_FS_LOCK != 0
+				if (res == FR_OK) {
+					if (dp->obj.sclust != 0) {
+						dp->obj.lockid = inc_lock(dp, 0);	/* Lock the sub directory */
+						if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES;
+					} else {
+						dp->obj.lockid = 0;	/* Root directory need not to be locked */
+					}
+				}
+#endif
+			}
+		}
+		FREE_NAMBUF();
+		if (res == FR_NO_FILE) res = FR_NO_PATH;
+	}
+	if (res != FR_OK) dp->obj.fs = 0;		/* Invalidate the directory object if function faild */
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Close Directory                                                       */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_closedir (
+	DIR *dp		/* Pointer to the directory object to be closed */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+
+
+	res = validate(&dp->obj, &fs);	/* Check validity of the file object */
+	if (res == FR_OK) {
+#if FF_FS_LOCK != 0
+		if (dp->obj.lockid) res = dec_lock(dp->obj.lockid);	/* Decrement sub-directory open counter */
+		if (res == FR_OK) dp->obj.fs = 0;	/* Invalidate directory object */
+#else
+		dp->obj.fs = 0;	/* Invalidate directory object */
+#endif
+#if FF_FS_REENTRANT
+		unlock_fs(fs, FR_OK);		/* Unlock volume */
+#endif
+	}
+	return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Directory Entries in Sequence                                    */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_readdir (
+	DIR* dp,			/* Pointer to the open directory object */
+	FILINFO* fno		/* Pointer to file information to return */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DEF_NAMBUF
+
+
+	res = validate(&dp->obj, &fs);	/* Check validity of the directory object */
+	if (res == FR_OK) {
+		if (!fno) {
+			res = dir_sdi(dp, 0);			/* Rewind the directory object */
+		} else {
+			INIT_NAMBUF(fs);
+			res = DIR_READ_FILE(dp);		/* Read an item */
+			if (res == FR_NO_FILE) res = FR_OK;	/* Ignore end of directory */
+			if (res == FR_OK) {				/* A valid entry is found */
+				get_fileinfo(dp, fno);		/* Get the object information */
+				res = dir_next(dp, 0);		/* Increment index for next */
+				if (res == FR_NO_FILE) res = FR_OK;	/* Ignore end of directory now */
+			}
+			FREE_NAMBUF();
+		}
+	}
+	LEAVE_FF(fs, res);
+}
+
+
+
+#if FF_USE_FIND
+/*-----------------------------------------------------------------------*/
+/* Find Next File                                                        */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_findnext (
+	DIR* dp,		/* Pointer to the open directory object */
+	FILINFO* fno	/* Pointer to the file information structure */
+)
+{
+	FRESULT res;
+
+
+	for (;;) {
+		res = f_readdir(dp, fno);		/* Get a directory item */
+		if (res != FR_OK || !fno || !fno->fname[0]) break;	/* Terminate if any error or end of directory */
+		if (pattern_matching(dp->pat, fno->fname, 0, 0)) break;		/* Test for the file name */
+#if FF_USE_LFN && FF_USE_FIND == 2
+		if (pattern_matching(dp->pat, fno->altname, 0, 0)) break;	/* Test for alternative name if exist */
+#endif
+	}
+	return res;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Find First File                                                       */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_findfirst (
+	DIR* dp,				/* Pointer to the blank directory object */
+	FILINFO* fno,			/* Pointer to the file information structure */
+	const TCHAR* path,		/* Pointer to the directory to open */
+	const TCHAR* pattern	/* Pointer to the matching pattern */
+)
+{
+	FRESULT res;
+
+
+	dp->pat = pattern;		/* Save pointer to pattern string */
+	res = f_opendir(dp, path);		/* Open the target directory */
+	if (res == FR_OK) {
+		res = f_findnext(dp, fno);	/* Find the first item */
+	}
+	return res;
+}
+
+#endif	/* FF_USE_FIND */
+
+
+
+#if FF_FS_MINIMIZE == 0
+/*-----------------------------------------------------------------------*/
+/* Get File Status                                                       */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_stat (
+	const TCHAR* path,	/* Pointer to the file path */
+	FILINFO* fno		/* Pointer to file information to return */
+)
+{
+	FRESULT res;
+	DIR dj;
+	DEF_NAMBUF
+
+
+	/* Get logical drive */
+	res = find_volume(&path, &dj.obj.fs, 0);
+	if (res == FR_OK) {
+		INIT_NAMBUF(dj.obj.fs);
+		res = follow_path(&dj, path);	/* Follow the file path */
+		if (res == FR_OK) {				/* Follow completed */
+			if (dj.fn[NSFLAG] & NS_NONAME) {	/* It is origin directory */
+				res = FR_INVALID_NAME;
+			} else {							/* Found an object */
+				if (fno) get_fileinfo(&dj, fno);
+			}
+		}
+		FREE_NAMBUF();
+	}
+
+	LEAVE_FF(dj.obj.fs, res);
+}
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Get Number of Free Clusters                                           */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_getfree (
+	const TCHAR* path,	/* Logical drive number */
+	DWORD* nclst,		/* Pointer to a variable to return number of free clusters */
+	FATFS** fatfs		/* Pointer to return pointer to corresponding filesystem object */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD nfree, clst, sect, stat;
+	UINT i;
+	FFOBJID obj;
+
+
+	/* Get logical drive */
+	res = find_volume(&path, &fs, 0);
+	if (res == FR_OK) {
+		*fatfs = fs;				/* Return ptr to the fs object */
+		/* If free_clst is valid, return it without full FAT scan */
+		if (fs->free_clst <= fs->n_fatent - 2) {
+			*nclst = fs->free_clst;
+		} else {
+			/* Scan FAT to obtain number of free clusters */
+			nfree = 0;
+			if (fs->fs_type == FS_FAT12) {	/* FAT12: Scan bit field FAT entries */
+				clst = 2; obj.fs = fs;
+				do {
+					stat = get_fat(&obj, clst);
+					if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
+					if (stat == 1) { res = FR_INT_ERR; break; }
+					if (stat == 0) nfree++;
+				} while (++clst < fs->n_fatent);
+			} else {
+#if FF_FS_EXFAT
+				if (fs->fs_type == FS_EXFAT) {	/* exFAT: Scan allocation bitmap */
+					BYTE bm;
+					UINT b;
+
+					clst = fs->n_fatent - 2;	/* Number of clusters */
+					sect = fs->bitbase;			/* Bitmap sector */
+					i = 0;						/* Offset in the sector */
+					do {	/* Counts numbuer of bits with zero in the bitmap */
+						if (i == 0) {
+							res = move_window(fs, sect++);
+							if (res != FR_OK) break;
+						}
+						for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) {
+							if (!(bm & 1)) nfree++;
+							bm >>= 1;
+						}
+						i = (i + 1) % SS(fs);
+					} while (clst);
+				} else
+#endif
+				{	/* FAT16/32: Scan WORD/DWORD FAT entries */
+					clst = fs->n_fatent;	/* Number of entries */
+					sect = fs->fatbase;		/* Top of the FAT */
+					i = 0;					/* Offset in the sector */
+					do {	/* Counts numbuer of entries with zero in the FAT */
+						if (i == 0) {
+							res = move_window(fs, sect++);
+							if (res != FR_OK) break;
+						}
+						if (fs->fs_type == FS_FAT16) {
+							if (ld_word(fs->win + i) == 0) nfree++;
+							i += 2;
+						} else {
+							if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++;
+							i += 4;
+						}
+						i %= SS(fs);
+					} while (--clst);
+				}
+			}
+			*nclst = nfree;			/* Return the free clusters */
+			fs->free_clst = nfree;	/* Now free_clst is valid */
+			fs->fsi_flag |= 1;		/* FAT32: FSInfo is to be updated */
+		}
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Truncate File                                                         */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_truncate (
+	FIL* fp		/* Pointer to the file object */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD ncl;
+
+
+	res = validate(&fp->obj, &fs);	/* Check validity of the file object */
+	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
+	if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */
+
+	if (fp->fptr < fp->obj.objsize) {	/* Process when fptr is not on the eof */
+		if (fp->fptr == 0) {	/* When set file size to zero, remove entire cluster chain */
+			res = remove_chain(&fp->obj, fp->obj.sclust, 0);
+			fp->obj.sclust = 0;
+		} else {				/* When truncate a part of the file, remove remaining clusters */
+			ncl = get_fat(&fp->obj, fp->clust);
+			res = FR_OK;
+			if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
+			if (ncl == 1) res = FR_INT_ERR;
+			if (res == FR_OK && ncl < fs->n_fatent) {
+				res = remove_chain(&fp->obj, ncl, fp->clust);
+			}
+		}
+		fp->obj.objsize = fp->fptr;	/* Set file size to current read/write point */
+		fp->flag |= FA_MODIFIED;
+#if !FF_FS_TINY
+		if (res == FR_OK && (fp->flag & FA_DIRTY)) {
+			if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
+				res = FR_DISK_ERR;
+			} else {
+				fp->flag &= (BYTE)~FA_DIRTY;
+			}
+		}
+#endif
+		if (res != FR_OK) ABORT(fs, res);
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Delete a File/Directory                                               */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_unlink (
+	const TCHAR* path		/* Pointer to the file or directory path */
+)
+{
+	FRESULT res;
+	DIR dj, sdj;
+	DWORD dclst = 0;
+	FATFS *fs;
+#if FF_FS_EXFAT
+	FFOBJID obj;
+#endif
+	DEF_NAMBUF
+
+
+	/* Get logical drive */
+	res = find_volume(&path, &fs, FA_WRITE);
+	if (res == FR_OK) {
+		dj.obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(&dj, path);		/* Follow the file path */
+		if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) {
+			res = FR_INVALID_NAME;			/* Cannot remove dot entry */
+		}
+#if FF_FS_LOCK != 0
+		if (res == FR_OK) res = chk_lock(&dj, 2);	/* Check if it is an open object */
+#endif
+		if (res == FR_OK) {					/* The object is accessible */
+			if (dj.fn[NSFLAG] & NS_NONAME) {
+				res = FR_INVALID_NAME;		/* Cannot remove the origin directory */
+			} else {
+				if (dj.obj.attr & AM_RDO) {
+					res = FR_DENIED;		/* Cannot remove R/O object */
+				}
+			}
+			if (res == FR_OK) {
+#if FF_FS_EXFAT
+				obj.fs = fs;
+				if (fs->fs_type == FS_EXFAT) {
+					init_alloc_info(fs, &obj);
+					dclst = obj.sclust;
+				} else
+#endif
+				{
+					dclst = ld_clust(fs, dj.dir);
+				}
+				if (dj.obj.attr & AM_DIR) {			/* Is it a sub-directory? */
+#if FF_FS_RPATH != 0
+					if (dclst == fs->cdir) {		 	/* Is it the current directory? */
+						res = FR_DENIED;
+					} else
+#endif
+					{
+						sdj.obj.fs = fs;				/* Open the sub-directory */
+						sdj.obj.sclust = dclst;
+#if FF_FS_EXFAT
+						if (fs->fs_type == FS_EXFAT) {
+							sdj.obj.objsize = obj.objsize;
+							sdj.obj.stat = obj.stat;
+						}
+#endif
+						res = dir_sdi(&sdj, 0);
+						if (res == FR_OK) {
+							res = DIR_READ_FILE(&sdj);			/* Test if the directory is empty */
+							if (res == FR_OK) res = FR_DENIED;	/* Not empty? */
+							if (res == FR_NO_FILE) res = FR_OK;	/* Empty? */
+						}
+					}
+				}
+			}
+			if (res == FR_OK) {
+				res = dir_remove(&dj);			/* Remove the directory entry */
+				if (res == FR_OK && dclst != 0) {	/* Remove the cluster chain if exist */
+#if FF_FS_EXFAT
+					res = remove_chain(&obj, dclst, 0);
+#else
+					res = remove_chain(&dj.obj, dclst, 0);
+#endif
+				}
+				if (res == FR_OK) res = sync_fs(fs);
+			}
+		}
+		FREE_NAMBUF();
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Create a Directory                                                    */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_mkdir (
+	const TCHAR* path		/* Pointer to the directory path */
+)
+{
+	FRESULT res;
+	DIR dj;
+	FFOBJID sobj;
+	FATFS *fs;
+	DWORD dcl, pcl, tm;
+	DEF_NAMBUF
+
+
+	res = find_volume(&path, &fs, FA_WRITE);	/* Get logical drive */
+	if (res == FR_OK) {
+		dj.obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(&dj, path);			/* Follow the file path */
+		if (res == FR_OK) res = FR_EXIST;		/* Name collision? */
+		if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {	/* Invalid name? */
+			res = FR_INVALID_NAME;
+		}
+		if (res == FR_NO_FILE) {				/* It is clear to create a new directory */
+			sobj.fs = fs;						/* New object id to create a new chain */
+			dcl = create_chain(&sobj, 0);		/* Allocate a cluster for the new directory */
+			res = FR_OK;
+			if (dcl == 0) res = FR_DENIED;		/* No space to allocate a new cluster? */
+			if (dcl == 1) res = FR_INT_ERR;		/* Any insanity? */
+			if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;	/* Disk error? */
+			tm = GET_FATTIME();
+			if (res == FR_OK) {
+				res = dir_clear(fs, dcl);		/* Clean up the new table */
+				if (res == FR_OK) {
+					if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) {	/* Create dot entries (FAT only) */
+						mem_set(fs->win + DIR_Name, ' ', 11);	/* Create "." entry */
+						fs->win[DIR_Name] = '.';
+						fs->win[DIR_Attr] = AM_DIR;
+						st_dword(fs->win + DIR_ModTime, tm);
+						st_clust(fs, fs->win, dcl);
+						mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
+						fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
+						st_clust(fs, fs->win + SZDIRE, pcl);
+						fs->wflag = 1;
+					}
+					res = dir_register(&dj);	/* Register the object to the parent directoy */
+				}
+			}
+			if (res == FR_OK) {
+#if FF_FS_EXFAT
+				if (fs->fs_type == FS_EXFAT) {	/* Initialize directory entry block */
+					st_dword(fs->dirbuf + XDIR_ModTime, tm);	/* Created time */
+					st_dword(fs->dirbuf + XDIR_FstClus, dcl);	/* Table start cluster */
+					st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs));	/* File size needs to be valid */
+					st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
+					fs->dirbuf[XDIR_GenFlags] = 3;				/* Initialize the object flag */
+					fs->dirbuf[XDIR_Attr] = AM_DIR;				/* Attribute */
+					res = store_xdir(&dj);
+				} else
+#endif
+				{
+					st_dword(dj.dir + DIR_ModTime, tm);	/* Created time */
+					st_clust(fs, dj.dir, dcl);			/* Table start cluster */
+					dj.dir[DIR_Attr] = AM_DIR;			/* Attribute */
+					fs->wflag = 1;
+				}
+				if (res == FR_OK) {
+					res = sync_fs(fs);
+				}
+			} else {
+				remove_chain(&sobj, dcl, 0);		/* Could not register, remove the allocated cluster */
+			}
+		}
+		FREE_NAMBUF();
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Rename a File/Directory                                               */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_rename (
+	const TCHAR* path_old,	/* Pointer to the object name to be renamed */
+	const TCHAR* path_new	/* Pointer to the new name */
+)
+{
+	FRESULT res;
+	DIR djo, djn;
+	FATFS *fs;
+	BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir;
+	DWORD dw;
+	DEF_NAMBUF
+
+
+	get_ldnumber(&path_new);						/* Snip the drive number of new name off */
+	res = find_volume(&path_old, &fs, FA_WRITE);	/* Get logical drive of the old object */
+	if (res == FR_OK) {
+		djo.obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(&djo, path_old);		/* Check old object */
+		if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check validity of name */
+#if FF_FS_LOCK != 0
+		if (res == FR_OK) {
+			res = chk_lock(&djo, 2);
+		}
+#endif
+		if (res == FR_OK) {						/* Object to be renamed is found */
+#if FF_FS_EXFAT
+			if (fs->fs_type == FS_EXFAT) {	/* At exFAT volume */
+				BYTE nf, nn;
+				WORD nh;
+
+				mem_cpy(buf, fs->dirbuf, SZDIRE * 2);	/* Save 85+C0 entry of old object */
+				mem_cpy(&djn, &djo, sizeof djo);
+				res = follow_path(&djn, path_new);		/* Make sure if new object name is not in use */
+				if (res == FR_OK) {						/* Is new name already in use by any other object? */
+					res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
+				}
+				if (res == FR_NO_FILE) { 				/* It is a valid path and no name collision */
+					res = dir_register(&djn);			/* Register the new entry */
+					if (res == FR_OK) {
+						nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName];
+						nh = ld_word(fs->dirbuf + XDIR_NameHash);
+						mem_cpy(fs->dirbuf, buf, SZDIRE * 2);	/* Restore 85+C0 entry */
+						fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
+						st_word(fs->dirbuf + XDIR_NameHash, nh);
+						if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC;	/* Set archive attribute if it is a file */
+/* Start of critical section where an interruption can cause a cross-link */
+						res = store_xdir(&djn);
+					}
+				}
+			} else
+#endif
+			{	/* At FAT/FAT32 volume */
+				mem_cpy(buf, djo.dir, SZDIRE);			/* Save directory entry of the object */
+				mem_cpy(&djn, &djo, sizeof (DIR));		/* Duplicate the directory object */
+				res = follow_path(&djn, path_new);		/* Make sure if new object name is not in use */
+				if (res == FR_OK) {						/* Is new name already in use by any other object? */
+					res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
+				}
+				if (res == FR_NO_FILE) { 				/* It is a valid path and no name collision */
+					res = dir_register(&djn);			/* Register the new entry */
+					if (res == FR_OK) {
+						dir = djn.dir;					/* Copy directory entry of the object except name */
+						mem_cpy(dir + 13, buf + 13, SZDIRE - 13);
+						dir[DIR_Attr] = buf[DIR_Attr];
+						if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC;	/* Set archive attribute if it is a file */
+						fs->wflag = 1;
+						if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) {	/* Update .. entry in the sub-directory if needed */
+							dw = clst2sect(fs, ld_clust(fs, dir));
+							if (dw == 0) {
+								res = FR_INT_ERR;
+							} else {
+/* Start of critical section where an interruption can cause a cross-link */
+								res = move_window(fs, dw);
+								dir = fs->win + SZDIRE * 1;	/* Ptr to .. entry */
+								if (res == FR_OK && dir[1] == '.') {
+									st_clust(fs, dir, djn.obj.sclust);
+									fs->wflag = 1;
+								}
+							}
+						}
+					}
+				}
+			}
+			if (res == FR_OK) {
+				res = dir_remove(&djo);		/* Remove old entry */
+				if (res == FR_OK) {
+					res = sync_fs(fs);
+				}
+			}
+/* End of the critical section */
+		}
+		FREE_NAMBUF();
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+#endif /* !FF_FS_READONLY */
+#endif /* FF_FS_MINIMIZE == 0 */
+#endif /* FF_FS_MINIMIZE <= 1 */
+#endif /* FF_FS_MINIMIZE <= 2 */
+
+
+
+#if FF_USE_CHMOD && !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Change Attribute                                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_chmod (
+	const TCHAR* path,	/* Pointer to the file path */
+	BYTE attr,			/* Attribute bits */
+	BYTE mask			/* Attribute mask to change */
+)
+{
+	FRESULT res;
+	DIR dj;
+	FATFS *fs;
+	DEF_NAMBUF
+
+
+	res = find_volume(&path, &fs, FA_WRITE);	/* Get logical drive */
+	if (res == FR_OK) {
+		dj.obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(&dj, path);	/* Follow the file path */
+		if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check object validity */
+		if (res == FR_OK) {
+			mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC;	/* Valid attribute mask */
+#if FF_FS_EXFAT
+			if (fs->fs_type == FS_EXFAT) {
+				fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask);	/* Apply attribute change */
+				res = store_xdir(&dj);
+			} else
+#endif
+			{
+				dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask);	/* Apply attribute change */
+				fs->wflag = 1;
+			}
+			if (res == FR_OK) {
+				res = sync_fs(fs);
+			}
+		}
+		FREE_NAMBUF();
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Change Timestamp                                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_utime (
+	const TCHAR* path,	/* Pointer to the file/directory name */
+	const FILINFO* fno	/* Pointer to the timestamp to be set */
+)
+{
+	FRESULT res;
+	DIR dj;
+	FATFS *fs;
+	DEF_NAMBUF
+
+
+	res = find_volume(&path, &fs, FA_WRITE);	/* Get logical drive */
+	if (res == FR_OK) {
+		dj.obj.fs = fs;
+		INIT_NAMBUF(fs);
+		res = follow_path(&dj, path);	/* Follow the file path */
+		if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check object validity */
+		if (res == FR_OK) {
+#if FF_FS_EXFAT
+			if (fs->fs_type == FS_EXFAT) {
+				st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
+				res = store_xdir(&dj);
+			} else
+#endif
+			{
+				st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
+				fs->wflag = 1;
+			}
+			if (res == FR_OK) {
+				res = sync_fs(fs);
+			}
+		}
+		FREE_NAMBUF();
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+#endif	/* FF_USE_CHMOD && !FF_FS_READONLY */
+
+
+
+#if FF_USE_LABEL
+/*-----------------------------------------------------------------------*/
+/* Get Volume Label                                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_getlabel (
+	const TCHAR* path,	/* Logical drive number */
+	TCHAR* label,		/* Buffer to store the volume label */
+	DWORD* vsn			/* Variable to store the volume serial number */
+)
+{
+	FRESULT res;
+	DIR dj;
+	FATFS *fs;
+	UINT si, di;
+	WCHAR wc;
+
+	/* Get logical drive */
+	res = find_volume(&path, &fs, 0);
+
+	/* Get volume label */
+	if (res == FR_OK && label) {
+		dj.obj.fs = fs; dj.obj.sclust = 0;	/* Open root directory */
+		res = dir_sdi(&dj, 0);
+		if (res == FR_OK) {
+		 	res = DIR_READ_LABEL(&dj);		/* Find a volume label entry */
+		 	if (res == FR_OK) {
+#if FF_FS_EXFAT
+				if (fs->fs_type == FS_EXFAT) {
+					WCHAR hs;
+
+					for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) {	/* Extract volume label from 83 entry */
+						wc = ld_word(dj.dir + XDIR_Label + si * 2);
+						if (hs == 0 && IsSurrogate(wc)) {	/* Is the code a surrogate? */
+							hs = wc; continue;
+						}
+						wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4);
+						if (wc == 0) { di = 0; break; }
+						di += wc;
+						hs = 0;
+					}
+					if (hs != 0) di = 0;	/* Broken surrogate pair? */
+					label[di] = 0;
+				} else
+#endif
+				{
+					si = di = 0;		/* Extract volume label from AM_VOL entry */
+					while (si < 11) {
+						wc = dj.dir[si++];
+#if FF_USE_LFN && FF_LFN_UNICODE >= 1 	/* Unicode output */
+						if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++];	/* Is it a DBC? */
+						wc = ff_oem2uni(wc, CODEPAGE);					/* Convert it into Unicode */
+						if (wc != 0) wc = put_utf(wc, &label[di], 4);	/* Put it in Unicode */
+						if (wc == 0) { di = 0; break; }
+						di += wc;
+#else									/* ANSI/OEM output */
+						label[di++] = (TCHAR)wc;
+#endif
+					}
+					do {				/* Truncate trailing spaces */
+						label[di] = 0;
+						if (di == 0) break;
+					} while (label[--di] == ' ');
+				}
+			}
+		}
+		if (res == FR_NO_FILE) {	/* No label entry and return nul string */
+			label[0] = 0;
+			res = FR_OK;
+		}
+	}
+
+	/* Get volume serial number */
+	if (res == FR_OK && vsn) {
+		res = move_window(fs, fs->volbase);
+		if (res == FR_OK) {
+			switch (fs->fs_type) {
+			case FS_EXFAT:
+				di = BPB_VolIDEx; break;
+
+			case FS_FAT32:
+				di = BS_VolID32; break;
+
+			default:
+				di = BS_VolID;
+			}
+			*vsn = ld_dword(fs->win + di);
+		}
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+
+
+#if !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Set Volume Label                                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_setlabel (
+	const TCHAR* label	/* Volume label to set with heading logical drive number */
+)
+{
+	FRESULT res;
+	DIR dj;
+	FATFS *fs;
+	BYTE dirvn[22];
+	UINT di;
+	WCHAR wc;
+	static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F";	/* [0..] for FAT, [7..] for exFAT */
+#if FF_USE_LFN
+	DWORD dc;
+#endif
+
+	/* Get logical drive */
+	res = find_volume(&label, &fs, FA_WRITE);
+	if (res != FR_OK) LEAVE_FF(fs, res);
+
+#if FF_FS_EXFAT
+	if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
+		mem_set(dirvn, 0, 22);
+		di = 0;
+		while ((UINT)*label >= ' ') {	/* Create volume label */
+			dc = tchar2uni(&label);	/* Get a Unicode character */
+			if (dc >= 0x10000) {
+				if (dc == 0xFFFFFFFF || di >= 10) {	/* Wrong surrogate or buffer overflow */
+					dc = 0;
+				} else {
+					st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++;
+				}
+			}
+			if (dc == 0 || chk_chr(badchr + 7, (int)dc) || di >= 11) {	/* Check validity of the volume label */
+				LEAVE_FF(fs, FR_INVALID_NAME);
+			}
+			st_word(dirvn + di * 2, (WCHAR)dc); di++;
+		}
+	} else
+#endif
+	{	/* On the FAT/FAT32 volume */
+		mem_set(dirvn, ' ', 11);
+		di = 0;
+		while ((UINT)*label >= ' ') {	/* Create volume label */
+#if FF_USE_LFN
+			dc = tchar2uni(&label);
+			wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0;
+#else									/* ANSI/OEM input */
+			wc = (BYTE)*label++;
+			if (dbc_1st((BYTE)wc)) wc = dbc_2nd((BYTE)*label) ? wc << 8 | (BYTE)*label++ : 0;
+			if (IsLower(wc)) wc -= 0x20;		/* To upper ASCII characters */
+#if FF_CODE_PAGE == 0
+			if (ExCvt && wc >= 0x80) wc = ExCvt[wc - 0x80];	/* To upper extended characters (SBCS cfg) */
+#elif FF_CODE_PAGE < 900
+			if (wc >= 0x80) wc = ExCvt[wc - 0x80];	/* To upper extended characters (SBCS cfg) */
+#endif
+#endif
+			if (wc == 0 || chk_chr(badchr + 0, (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) {	/* Reject invalid characters for volume label */
+				LEAVE_FF(fs, FR_INVALID_NAME);
+			}
+			if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8);
+			dirvn[di++] = (BYTE)wc;
+		}
+		if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME);	/* Reject illegal name (heading DDEM) */
+		while (di && dirvn[di - 1] == ' ') di--;				/* Snip trailing spaces */
+	}
+
+	/* Set volume label */
+	dj.obj.fs = fs; dj.obj.sclust = 0;	/* Open root directory */
+	res = dir_sdi(&dj, 0);
+	if (res == FR_OK) {
+		res = DIR_READ_LABEL(&dj);	/* Get volume label entry */
+		if (res == FR_OK) {
+			if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
+				dj.dir[XDIR_NumLabel] = (BYTE)di;	/* Change the volume label */
+				mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
+			} else {
+				if (di != 0) {
+					mem_cpy(dj.dir, dirvn, 11);	/* Change the volume label */
+				} else {
+					dj.dir[DIR_Name] = DDEM;	/* Remove the volume label */
+				}
+			}
+			fs->wflag = 1;
+			res = sync_fs(fs);
+		} else {			/* No volume label entry or an error */
+			if (res == FR_NO_FILE) {
+				res = FR_OK;
+				if (di != 0) {	/* Create a volume label entry */
+					res = dir_alloc(&dj, 1);	/* Allocate an entry */
+					if (res == FR_OK) {
+						mem_set(dj.dir, 0, SZDIRE);	/* Clean the entry */
+						if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
+							dj.dir[XDIR_Type] = ET_VLABEL;	/* Create volume label entry */
+							dj.dir[XDIR_NumLabel] = (BYTE)di;
+							mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
+						} else {
+							dj.dir[DIR_Attr] = AM_VOL;		/* Create volume label entry */
+							mem_cpy(dj.dir, dirvn, 11);
+						}
+						fs->wflag = 1;
+						res = sync_fs(fs);
+					}
+				}
+			}
+		}
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+#endif /* !FF_FS_READONLY */
+#endif /* FF_USE_LABEL */
+
+
+
+#if FF_USE_EXPAND && !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Allocate a Contiguous Blocks to the File                              */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_expand (
+	FIL* fp,		/* Pointer to the file object */
+	FSIZE_t fsz,	/* File size to be expanded to */
+	BYTE opt		/* Operation mode 0:Find and prepare or 1:Find and allocate */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD n, clst, stcl, scl, ncl, tcl, lclst;
+
+
+	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
+	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
+	if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);
+#if FF_FS_EXFAT
+	if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED);	/* Check if in size limit */
+#endif
+	n = (DWORD)fs->csize * SS(fs);	/* Cluster size */
+	tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0);	/* Number of clusters required */
+	stcl = fs->last_clst; lclst = 0;
+	if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2;
+
+#if FF_FS_EXFAT
+	if (fs->fs_type == FS_EXFAT) {
+		scl = find_bitmap(fs, stcl, tcl);			/* Find a contiguous cluster block */
+		if (scl == 0) res = FR_DENIED;				/* No contiguous cluster block was found */
+		if (scl == 0xFFFFFFFF) res = FR_DISK_ERR;
+		if (res == FR_OK) {	/* A contiguous free area is found */
+			if (opt) {		/* Allocate it now */
+				res = change_bitmap(fs, scl, tcl, 1);	/* Mark the cluster block 'in use' */
+				lclst = scl + tcl - 1;
+			} else {		/* Set it as suggested point for next allocation */
+				lclst = scl - 1;
+			}
+		}
+	} else
+#endif
+	{
+		scl = clst = stcl; ncl = 0;
+		for (;;) {	/* Find a contiguous cluster block */
+			n = get_fat(&fp->obj, clst);
+			if (++clst >= fs->n_fatent) clst = 2;
+			if (n == 1) { res = FR_INT_ERR; break; }
+			if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
+			if (n == 0) {	/* Is it a free cluster? */
+				if (++ncl == tcl) break;	/* Break if a contiguous cluster block is found */
+			} else {
+				scl = clst; ncl = 0;		/* Not a free cluster */
+			}
+			if (clst == stcl) { res = FR_DENIED; break; }	/* No contiguous cluster? */
+		}
+		if (res == FR_OK) {	/* A contiguous free area is found */
+			if (opt) {		/* Allocate it now */
+				for (clst = scl, n = tcl; n; clst++, n--) {	/* Create a cluster chain on the FAT */
+					res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1);
+					if (res != FR_OK) break;
+					lclst = clst;
+				}
+			} else {		/* Set it as suggested point for next allocation */
+				lclst = scl - 1;
+			}
+		}
+	}
+
+	if (res == FR_OK) {
+		fs->last_clst = lclst;		/* Set suggested start cluster to start next */
+		if (opt) {	/* Is it allocated now? */
+			fp->obj.sclust = scl;		/* Update object allocation information */
+			fp->obj.objsize = fsz;
+			if (FF_FS_EXFAT) fp->obj.stat = 2;	/* Set status 'contiguous chain' */
+			fp->flag |= FA_MODIFIED;
+			if (fs->free_clst <= fs->n_fatent - 2) {	/* Update FSINFO */
+				fs->free_clst -= tcl;
+				fs->fsi_flag |= 1;
+			}
+		}
+	}
+
+	LEAVE_FF(fs, res);
+}
+
+#endif /* FF_USE_EXPAND && !FF_FS_READONLY */
+
+
+
+#if FF_USE_FORWARD
+/*-----------------------------------------------------------------------*/
+/* Forward Data to the Stream Directly                                   */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_forward (
+	FIL* fp, 						/* Pointer to the file object */
+	UINT (*func)(const BYTE*,UINT),	/* Pointer to the streaming function */
+	UINT btf,						/* Number of bytes to forward */
+	UINT* bf						/* Pointer to number of bytes forwarded */
+)
+{
+	FRESULT res;
+	FATFS *fs;
+	DWORD clst, sect;
+	FSIZE_t remain;
+	UINT rcnt, csect;
+	BYTE *dbuf;
+
+
+	*bf = 0;	/* Clear transfer byte counter */
+	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
+	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
+	if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */
+
+	remain = fp->obj.objsize - fp->fptr;
+	if (btf > remain) btf = (UINT)remain;			/* Truncate btf by remaining bytes */
+
+	for ( ;  btf && (*func)(0, 0);					/* Repeat until all data transferred or stream goes busy */
+		fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
+		csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));	/* Sector offset in the cluster */
+		if (fp->fptr % SS(fs) == 0) {				/* On the sector boundary? */
+			if (csect == 0) {						/* On the cluster boundary? */
+				clst = (fp->fptr == 0) ?			/* On the top of the file? */
+					fp->obj.sclust : get_fat(&fp->obj, fp->clust);
+				if (clst <= 1) ABORT(fs, FR_INT_ERR);
+				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
+				fp->clust = clst;					/* Update current cluster */
+			}
+		}
+		sect = clst2sect(fs, fp->clust);			/* Get current data sector */
+		if (sect == 0) ABORT(fs, FR_INT_ERR);
+		sect += csect;
+#if FF_FS_TINY
+		if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window to the file data */
+		dbuf = fs->win;
+#else
+		if (fp->sect != sect) {		/* Fill sector cache with file data */
+#if !FF_FS_READONLY
+			if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
+				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
+				fp->flag &= (BYTE)~FA_DIRTY;
+			}
+#endif
+			if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
+		}
+		dbuf = fp->buf;
+#endif
+		fp->sect = sect;
+		rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes left in the sector */
+		if (rcnt > btf) rcnt = btf;					/* Clip it by btr if needed */
+		rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt);	/* Forward the file data */
+		if (rcnt == 0) ABORT(fs, FR_INT_ERR);
+	}
+
+	LEAVE_FF(fs, FR_OK);
+}
+#endif /* FF_USE_FORWARD */
+
+
+
+#if FF_USE_MKFS && !FF_FS_READONLY
+/*-----------------------------------------------------------------------*/
+/* Create an FAT/exFAT volume                                            */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_mkfs (
+	const TCHAR* path,	/* Logical drive number */
+	BYTE opt,			/* Format option */
+	DWORD au,			/* Size of allocation unit (cluster) [byte] */
+	void* work,			/* Pointer to working buffer (null: use heap memory) */
+	UINT len			/* Size of working buffer [byte] */
+)
+{
+	const UINT n_fats = 1;		/* Number of FATs for FAT/FAT32 volume (1 or 2) */
+	const UINT n_rootdir = 512;	/* Number of root directory entries for FAT volume */
+	static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0};	/* Cluster size boundary for FAT volume (4Ks unit) */
+	static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0};	/* Cluster size boundary for FAT32 volume (128Ks unit) */
+	BYTE fmt, sys, *buf, *pte, pdrv, part;
+	WORD ss;	/* Sector size */
+	DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n;
+	DWORD b_vol, b_fat, b_data;				/* Base LBA for volume, fat, data */
+	DWORD sz_vol, sz_rsv, sz_fat, sz_dir;	/* Size for volume, fat, dir, data */
+	UINT i;
+	int vol;
+	DSTATUS stat;
+#if FF_USE_TRIM || FF_FS_EXFAT
+	DWORD tbl[3];
+#endif
+
+
+	/* Check mounted drive and clear work area */
+	vol = get_ldnumber(&path);					/* Get target logical drive */
+	if (vol < 0) return FR_INVALID_DRIVE;
+	if (FatFs[vol]) FatFs[vol]->fs_type = 0;	/* Clear the volume if mounted */
+	pdrv = LD2PD(vol);	/* Physical drive */
+	part = LD2PT(vol);	/* Partition (0:create as new, 1-4:get from partition table) */
+
+	/* Check physical drive status */
+	stat = disk_initialize(pdrv);
+	if (stat & STA_NOINIT) return FR_NOT_READY;
+	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
+	if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1;	/* Erase block to align data area */
+#if FF_MAX_SS != FF_MIN_SS		/* Get sector size of the medium if variable sector size cfg. */
+	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
+	if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
+#else
+	ss = FF_MAX_SS;
+#endif
+	if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER;	/* Check if au is valid */
+	au /= ss;	/* Cluster size in unit of sector */
+
+	/* Get working buffer */
+#if FF_USE_LFN == 3
+	if (!work) {	/* Use heap memory for working buffer */
+		for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ;
+		sz_buf = szb_buf / ss;		/* Size of working buffer (sector) */
+	} else
+#endif
+	{
+		buf = (BYTE*)work;		/* Working buffer */
+		sz_buf = len / ss;		/* Size of working buffer (sector) */
+		szb_buf = sz_buf * ss;	/* Size of working buffer (byte) */
+	}
+	if (!buf || sz_buf == 0) return FR_NOT_ENOUGH_CORE;
+
+	/* Determine where the volume to be located (b_vol, sz_vol) */
+	if (FF_MULTI_PARTITION && part != 0) {
+		/* Get partition information from partition table in the MBR */
+		if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Load MBR */
+		if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if MBR is valid */
+		pte = buf + (MBR_Table + (part - 1) * SZ_PTE);
+		if (pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED);	/* No partition? */
+		b_vol = ld_dword(pte + PTE_StLba);		/* Get volume start sector */
+		sz_vol = ld_dword(pte + PTE_SizLba);	/* Get volume size */
+	} else {
+		/* Create a single-partition in this function */
+		if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+		b_vol = (opt & FM_SFD) ? 0 : 63;		/* Volume start sector */
+		if (sz_vol < b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);
+		sz_vol -= b_vol;						/* Volume size */
+	}
+	if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Check if volume size is >=128s */
+
+	/* Pre-determine the FAT type */
+	do {
+		if (FF_FS_EXFAT && (opt & FM_EXFAT)) {	/* exFAT possible? */
+			if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) {	/* exFAT only, vol >= 64Ms or au > 128s ? */
+				fmt = FS_EXFAT; break;
+			}
+		}
+		if (au > 128) LEAVE_MKFS(FR_INVALID_PARAMETER);	/* Too large au for FAT/FAT32 */
+		if (opt & FM_FAT32) {	/* FAT32 possible? */
+			if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) {	/* FAT32 only or no-FAT? */
+				fmt = FS_FAT32; break;
+			}
+		}
+		if (!(opt & FM_FAT)) LEAVE_MKFS(FR_INVALID_PARAMETER);	/* no-FAT? */
+		fmt = FS_FAT16;
+	} while (0);
+
+#if FF_FS_EXFAT
+	if (fmt == FS_EXFAT) {	/* Create an exFAT volume */
+		DWORD szb_bit, szb_case, sum, nb, cl;
+		WCHAR ch, si;
+		UINT j, st;
+		BYTE b;
+
+		if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume? */
+#if FF_USE_TRIM
+		tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1;	/* Inform the device the volume area may be erased */
+		disk_ioctl(pdrv, CTRL_TRIM, tbl);
+#endif
+		/* Determine FAT location, data location and number of clusters */
+		if (au == 0) {	/* au auto-selection */
+			au = 8;
+			if (sz_vol >= 0x80000) au = 64;		/* >= 512Ks */
+			if (sz_vol >= 0x4000000) au = 256;	/* >= 64Ms */
+		}
+		b_fat = b_vol + 32;										/* FAT start at offset 32 */
+		sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss;			/* Number of FAT sectors */
+		b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1);	/* Align data area to the erase block boundary */
+		if (b_data >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume? */
+		n_clst = (sz_vol - (b_data - b_vol)) / au;				/* Number of clusters */
+		if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED);			/* Too few clusters? */
+		if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too many clusters? */
+
+		szb_bit = (n_clst + 7) / 8;						/* Size of allocation bitmap */
+		tbl[0] = (szb_bit + au * ss - 1) / (au * ss);	/* Number of allocation bitmap clusters */
+
+		/* Create a compressed up-case table */
+		sect = b_data + au * tbl[0];	/* Table start sector */
+		sum = 0;						/* Table checksum to be stored in the 82 entry */
+		st = 0; si = 0; i = 0; j = 0; szb_case = 0;
+		do {
+			switch (st) {
+			case 0:
+				ch = (WCHAR)ff_wtoupper(si);	/* Get an up-case char */
+				if (ch != si) {
+					si++; break;		/* Store the up-case char if exist */
+				}
+				for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ;	/* Get run length of no-case block */
+				if (j >= 128) {
+					ch = 0xFFFF; st = 2; break;	/* Compress the no-case block if run is >= 128 */
+				}
+				st = 1;			/* Do not compress short run */
+				/* go to next case */
+			case 1:
+				ch = si++;		/* Fill the short run */
+				if (--j == 0) st = 0;
+				break;
+
+			default:
+				ch = (WCHAR)j; si += (WCHAR)j;	/* Number of chars to skip */
+				st = 0;
+			}
+			sum = xsum32(buf[i + 0] = (BYTE)ch, sum);		/* Put it into the write buffer */
+			sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum);
+			i += 2; szb_case += 2;
+			if (si == 0 || i == szb_buf) {		/* Write buffered data when buffer full or end of process */
+				n = (i + ss - 1) / ss;
+				if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+				sect += n; i = 0;
+			}
+		} while (si);
+		tbl[1] = (szb_case + au * ss - 1) / (au * ss);	/* Number of up-case table clusters */
+		tbl[2] = 1;										/* Number of root dir clusters */
+
+		/* Initialize the allocation bitmap */
+		sect = b_data; nsect = (szb_bit + ss - 1) / ss;	/* Start of bitmap and number of sectors */
+		nb = tbl[0] + tbl[1] + tbl[2];					/* Number of clusters in-use by system */
+		do {
+			mem_set(buf, 0, szb_buf);
+			for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ;
+			for (b = 1; nb != 0 && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ;
+			n = (nsect > sz_buf) ? sz_buf : nsect;		/* Write the buffered data */
+			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+			sect += n; nsect -= n;
+		} while (nsect);
+
+		/* Initialize the FAT */
+		sect = b_fat; nsect = sz_fat;	/* Start of FAT and number of FAT sectors */
+		j = nb = cl = 0;
+		do {
+			mem_set(buf, 0, szb_buf); i = 0;	/* Clear work area and reset write index */
+			if (cl == 0) {	/* Set entry 0 and 1 */
+				st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++;
+				st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++;
+			}
+			do {			/* Create chains of bitmap, up-case and root dir */
+				while (nb != 0 && i < szb_buf) {			/* Create a chain */
+					st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF);
+					i += 4; cl++; nb--;
+				}
+				if (nb == 0 && j < 3) nb = tbl[j++];	/* Next chain */
+			} while (nb != 0 && i < szb_buf);
+			n = (nsect > sz_buf) ? sz_buf : nsect;	/* Write the buffered data */
+			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+			sect += n; nsect -= n;
+		} while (nsect);
+
+		/* Initialize the root directory */
+		mem_set(buf, 0, szb_buf);
+		buf[SZDIRE * 0 + 0] = ET_VLABEL;		/* Volume label entry */
+		buf[SZDIRE * 1 + 0] = ET_BITMAP;		/* Bitmap entry */
+		st_dword(buf + SZDIRE * 1 + 20, 2);				/* cluster */
+		st_dword(buf + SZDIRE * 1 + 24, szb_bit);		/* size */
+		buf[SZDIRE * 2 + 0] = ET_UPCASE;		/* Up-case table entry */
+		st_dword(buf + SZDIRE * 2 + 4, sum);			/* sum */
+		st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]);	/* cluster */
+		st_dword(buf + SZDIRE * 2 + 24, szb_case);		/* size */
+		sect = b_data + au * (tbl[0] + tbl[1]);	nsect = au;	/* Start of the root directory and number of sectors */
+		do {	/* Fill root directory sectors */
+			n = (nsect > sz_buf) ? sz_buf : nsect;
+			if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+			mem_set(buf, 0, ss);
+			sect += n; nsect -= n;
+		} while (nsect);
+
+		/* Create two set of the exFAT VBR blocks */
+		sect = b_vol;
+		for (n = 0; n < 2; n++) {
+			/* Main record (+0) */
+			mem_set(buf, 0, ss);
+			mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT   ", 11);	/* Boot jump code (x86), OEM name */
+			st_dword(buf + BPB_VolOfsEx, b_vol);					/* Volume offset in the physical drive [sector] */
+			st_dword(buf + BPB_TotSecEx, sz_vol);					/* Volume size [sector] */
+			st_dword(buf + BPB_FatOfsEx, b_fat - b_vol);			/* FAT offset [sector] */
+			st_dword(buf + BPB_FatSzEx, sz_fat);					/* FAT size [sector] */
+			st_dword(buf + BPB_DataOfsEx, b_data - b_vol);			/* Data offset [sector] */
+			st_dword(buf + BPB_NumClusEx, n_clst);					/* Number of clusters */
+			st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]);	/* Root dir cluster # */
+			st_dword(buf + BPB_VolIDEx, GET_FATTIME());				/* VSN */
+			st_word(buf + BPB_FSVerEx, 0x100);						/* Filesystem version (1.00) */
+			for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ;	/* Log2 of sector size [byte] */
+			for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ;	/* Log2 of cluster size [sector] */
+			buf[BPB_NumFATsEx] = 1;					/* Number of FATs */
+			buf[BPB_DrvNumEx] = 0x80;				/* Drive number (for int13) */
+			st_word(buf + BS_BootCodeEx, 0xFEEB);	/* Boot code (x86) */
+			st_word(buf + BS_55AA, 0xAA55);			/* Signature (placed here regardless of sector size) */
+			for (i = sum = 0; i < ss; i++) {		/* VBR checksum */
+				if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum);
+			}
+			if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+			/* Extended bootstrap record (+1..+8) */
+			mem_set(buf, 0, ss);
+			st_word(buf + ss - 2, 0xAA55);	/* Signature (placed at end of sector) */
+			for (j = 1; j < 9; j++) {
+				for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;	/* VBR checksum */
+				if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+			}
+			/* OEM/Reserved record (+9..+10) */
+			mem_set(buf, 0, ss);
+			for ( ; j < 11; j++) {
+				for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ;	/* VBR checksum */
+				if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+			}
+			/* Sum record (+11) */
+			for (i = 0; i < ss; i += 4) st_dword(buf + i, sum);		/* Fill with checksum value */
+			if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+		}
+
+	} else
+#endif	/* FF_FS_EXFAT */
+	{	/* Create an FAT/FAT32 volume */
+		do {
+			pau = au;
+			/* Pre-determine number of clusters and FAT sub-type */
+			if (fmt == FS_FAT32) {	/* FAT32 volume */
+				if (pau == 0) {	/* au auto-selection */
+					n = sz_vol / 0x20000;	/* Volume size in unit of 128KS */
+					for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ;	/* Get from table */
+				}
+				n_clst = sz_vol / pau;	/* Number of clusters */
+				sz_fat = (n_clst * 4 + 8 + ss - 1) / ss;	/* FAT size [sector] */
+				sz_rsv = 32;	/* Number of reserved sectors */
+				sz_dir = 0;		/* No static directory */
+				if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) LEAVE_MKFS(FR_MKFS_ABORTED);
+			} else {				/* FAT volume */
+				if (pau == 0) {	/* au auto-selection */
+					n = sz_vol / 0x1000;	/* Volume size in unit of 4KS */
+					for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ;	/* Get from table */
+				}
+				n_clst = sz_vol / pau;
+				if (n_clst > MAX_FAT12) {
+					n = n_clst * 2 + 4;		/* FAT size [byte] */
+				} else {
+					fmt = FS_FAT12;
+					n = (n_clst * 3 + 1) / 2 + 3;	/* FAT size [byte] */
+				}
+				sz_fat = (n + ss - 1) / ss;		/* FAT size [sector] */
+				sz_rsv = 1;						/* Number of reserved sectors */
+				sz_dir = (DWORD)n_rootdir * SZDIRE / ss;	/* Rootdir size [sector] */
+			}
+			b_fat = b_vol + sz_rsv;						/* FAT base */
+			b_data = b_fat + sz_fat * n_fats + sz_dir;	/* Data base */
+
+			/* Align data base to erase block boundary (for flash memory media) */
+			n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data;	/* Next nearest erase block from current data base */
+			if (fmt == FS_FAT32) {		/* FAT32: Move FAT base */
+				sz_rsv += n; b_fat += n;
+			} else {					/* FAT: Expand FAT size */
+				sz_fat += n / n_fats;
+			}
+
+			/* Determine number of clusters and final check of validity of the FAT sub-type */
+			if (sz_vol < b_data + pau * 16 - b_vol) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too small volume */
+			n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau;
+			if (fmt == FS_FAT32) {
+				if (n_clst <= MAX_FAT16) {	/* Too few clusters for FAT32 */
+					if (au == 0 && (au = pau / 2) != 0) continue;	/* Adjust cluster size and retry */
+					LEAVE_MKFS(FR_MKFS_ABORTED);
+				}
+			}
+			if (fmt == FS_FAT16) {
+				if (n_clst > MAX_FAT16) {	/* Too many clusters for FAT16 */
+					if (au == 0 && (pau * 2) <= 64) {
+						au = pau * 2; continue;		/* Adjust cluster size and retry */
+					}
+					if ((opt & FM_FAT32)) {
+						fmt = FS_FAT32; continue;	/* Switch type to FAT32 and retry */
+					}
+					if (au == 0 && (au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
+					LEAVE_MKFS(FR_MKFS_ABORTED);
+				}
+				if  (n_clst <= MAX_FAT12) {	/* Too few clusters for FAT16 */
+					if (au == 0 && (au = pau * 2) <= 128) continue;	/* Adjust cluster size and retry */
+					LEAVE_MKFS(FR_MKFS_ABORTED);
+				}
+			}
+			if (fmt == FS_FAT12 && n_clst > MAX_FAT12) LEAVE_MKFS(FR_MKFS_ABORTED);	/* Too many clusters for FAT12 */
+
+			/* Ok, it is the valid cluster configuration */
+			break;
+		} while (1);
+
+#if FF_USE_TRIM
+		tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1;	/* Inform the device the volume area can be erased */
+		disk_ioctl(pdrv, CTRL_TRIM, tbl);
+#endif
+		/* Create FAT VBR */
+		mem_set(buf, 0, ss);
+		mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */
+		st_word(buf + BPB_BytsPerSec, ss);				/* Sector size [byte] */
+		buf[BPB_SecPerClus] = (BYTE)pau;				/* Cluster size [sector] */
+		st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv);	/* Size of reserved area */
+		buf[BPB_NumFATs] = (BYTE)n_fats;				/* Number of FATs */
+		st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir));	/* Number of root directory entries */
+		if (sz_vol < 0x10000) {
+			st_word(buf + BPB_TotSec16, (WORD)sz_vol);	/* Volume size in 16-bit LBA */
+		} else {
+			st_dword(buf + BPB_TotSec32, sz_vol);		/* Volume size in 32-bit LBA */
+		}
+		buf[BPB_Media] = 0xF8;							/* Media descriptor byte */
+		st_word(buf + BPB_SecPerTrk, 63);				/* Number of sectors per track (for int13) */
+		st_word(buf + BPB_NumHeads, 255);				/* Number of heads (for int13) */
+		st_dword(buf + BPB_HiddSec, b_vol);				/* Volume offset in the physical drive [sector] */
+		if (fmt == FS_FAT32) {
+			st_dword(buf + BS_VolID32, GET_FATTIME());	/* VSN */
+			st_dword(buf + BPB_FATSz32, sz_fat);		/* FAT size [sector] */
+			st_dword(buf + BPB_RootClus32, 2);			/* Root directory cluster # (2) */
+			st_word(buf + BPB_FSInfo32, 1);				/* Offset of FSINFO sector (VBR + 1) */
+			st_word(buf + BPB_BkBootSec32, 6);			/* Offset of backup VBR (VBR + 6) */
+			buf[BS_DrvNum32] = 0x80;					/* Drive number (for int13) */
+			buf[BS_BootSig32] = 0x29;					/* Extended boot signature */
+			mem_cpy(buf + BS_VolLab32, "NO NAME    " "FAT32   ", 19);	/* Volume label, FAT signature */
+		} else {
+			st_dword(buf + BS_VolID, GET_FATTIME());	/* VSN */
+			st_word(buf + BPB_FATSz16, (WORD)sz_fat);	/* FAT size [sector] */
+			buf[BS_DrvNum] = 0x80;						/* Drive number (for int13) */
+			buf[BS_BootSig] = 0x29;						/* Extended boot signature */
+			mem_cpy(buf + BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
+		}
+		st_word(buf + BS_55AA, 0xAA55);					/* Signature (offset is fixed here regardless of sector size) */
+		if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the VBR sector */
+
+		/* Create FSINFO record if needed */
+		if (fmt == FS_FAT32) {
+			disk_write(pdrv, buf, b_vol + 6, 1);		/* Write backup VBR (VBR + 6) */
+			mem_set(buf, 0, ss);
+			st_dword(buf + FSI_LeadSig, 0x41615252);
+			st_dword(buf + FSI_StrucSig, 0x61417272);
+			st_dword(buf + FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
+			st_dword(buf + FSI_Nxt_Free, 2);			/* Last allocated cluster# */
+			st_word(buf + BS_55AA, 0xAA55);
+			disk_write(pdrv, buf, b_vol + 7, 1);		/* Write backup FSINFO (VBR + 7) */
+			disk_write(pdrv, buf, b_vol + 1, 1);		/* Write original FSINFO (VBR + 1) */
+		}
+
+		/* Initialize FAT area */
+		mem_set(buf, 0, (UINT)szb_buf);
+		sect = b_fat;		/* FAT start sector */
+		for (i = 0; i < n_fats; i++) {			/* Initialize FATs each */
+			if (fmt == FS_FAT32) {
+				st_dword(buf + 0, 0xFFFFFFF8);	/* Entry 0 */
+				st_dword(buf + 4, 0xFFFFFFFF);	/* Entry 1 */
+				st_dword(buf + 8, 0x0FFFFFFF);	/* Entry 2 (root directory) */
+			} else {
+				st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8);	/* Entry 0 and 1 */
+			}
+			nsect = sz_fat;		/* Number of FAT sectors */
+			do {	/* Fill FAT sectors */
+				n = (nsect > sz_buf) ? sz_buf : nsect;
+				if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+				mem_set(buf, 0, ss);
+				sect += n; nsect -= n;
+			} while (nsect);
+		}
+
+		/* Initialize root directory (fill with zero) */
+		nsect = (fmt == FS_FAT32) ? pau : sz_dir;	/* Number of root directory sectors */
+		do {
+			n = (nsect > sz_buf) ? sz_buf : nsect;
+			if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+			sect += n; nsect -= n;
+		} while (nsect);
+	}
+
+	/* Determine system ID in the partition table */
+	if (FF_FS_EXFAT && fmt == FS_EXFAT) {
+		sys = 0x07;			/* HPFS/NTFS/exFAT */
+	} else {
+		if (fmt == FS_FAT32) {
+			sys = 0x0C;		/* FAT32X */
+		} else {
+			if (sz_vol >= 0x10000) {
+				sys = 0x06;	/* FAT12/16 (large) */
+			} else {
+				sys = (fmt == FS_FAT16) ? 0x04 : 0x01;	/* FAT16 : FAT12 */
+			}
+		}
+	}
+
+	/* Update partition information */
+	if (FF_MULTI_PARTITION && part != 0) {	/* Created in the existing partition */
+		/* Update system ID in the partition table */
+		if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Read the MBR */
+		buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys;		/* Set system ID */
+		if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it back to the MBR */
+	} else {								/* Created as a new single partition */
+		if (!(opt & FM_SFD)) {	/* Create partition table if in FDISK format */
+			mem_set(buf, 0, ss);
+			st_word(buf + BS_55AA, 0xAA55);		/* MBR signature */
+			pte = buf + MBR_Table;				/* Create partition table for single partition in the drive */
+			pte[PTE_Boot] = 0;					/* Boot indicator */
+			pte[PTE_StHead] = 1;				/* Start head */
+			pte[PTE_StSec] = 1;					/* Start sector */
+			pte[PTE_StCyl] = 0;					/* Start cylinder */
+			pte[PTE_System] = sys;				/* System type */
+			n = (b_vol + sz_vol) / (63 * 255);	/* (End CHS may be invalid) */
+			pte[PTE_EdHead] = 254;				/* End head */
+			pte[PTE_EdSec] = (BYTE)(((n >> 2) & 0xC0) | 63);	/* End sector */
+			pte[PTE_EdCyl] = (BYTE)n;			/* End cylinder */
+			st_dword(pte + PTE_StLba, b_vol);	/* Start offset in LBA */
+			st_dword(pte + PTE_SizLba, sz_vol);	/* Size in sectors */
+			if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);	/* Write it to the MBR */
+		}
+	}
+
+	if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
+
+	LEAVE_MKFS(FR_OK);
+}
+
+
+
+#if FF_MULTI_PARTITION
+/*-----------------------------------------------------------------------*/
+/* Create Partition Table on the Physical Drive                          */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_fdisk (
+	BYTE pdrv,			/* Physical drive number */
+	const DWORD* szt,	/* Pointer to the size table for each partitions */
+	void* work			/* Pointer to the working buffer (null: use heap memory) */
+)
+{
+	UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
+	BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
+	DSTATUS stat;
+	DWORD sz_disk, sz_part, s_part;
+	FRESULT res;
+
+
+	stat = disk_initialize(pdrv);
+	if (stat & STA_NOINIT) return FR_NOT_READY;
+	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
+	if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
+
+	buf = (BYTE*)work;
+#if FF_USE_LFN == 3
+	if (!buf) buf = ff_memalloc(FF_MAX_SS);	/* Use heap memory for working buffer */
+#endif
+	if (!buf) return FR_NOT_ENOUGH_CORE;
+
+	/* Determine the CHS without any consideration of the drive geometry */
+	for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
+	if (n == 256) n--;
+	e_hd = (BYTE)(n - 1);
+	sz_cyl = 63 * n;
+	tot_cyl = sz_disk / sz_cyl;
+
+	/* Create partition table */
+	mem_set(buf, 0, FF_MAX_SS);
+	p = buf + MBR_Table; b_cyl = 0;
+	for (i = 0; i < 4; i++, p += SZ_PTE) {
+		p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;	/* Number of cylinders */
+		if (p_cyl == 0) continue;
+		s_part = (DWORD)sz_cyl * b_cyl;
+		sz_part = (DWORD)sz_cyl * p_cyl;
+		if (i == 0) {	/* Exclude first track of cylinder 0 */
+			s_hd = 1;
+			s_part += 63; sz_part -= 63;
+		} else {
+			s_hd = 0;
+		}
+		e_cyl = b_cyl + p_cyl - 1;	/* End cylinder */
+		if (e_cyl >= tot_cyl) LEAVE_MKFS(FR_INVALID_PARAMETER);
+
+		/* Set partition table */
+		p[1] = s_hd;						/* Start head */
+		p[2] = (BYTE)(((b_cyl >> 2) & 0xC0) | 1);	/* Start sector */
+		p[3] = (BYTE)b_cyl;					/* Start cylinder */
+		p[4] = 0x07;						/* System type (temporary setting) */
+		p[5] = e_hd;						/* End head */
+		p[6] = (BYTE)(((e_cyl >> 2) & 0xC0) | 63);	/* End sector */
+		p[7] = (BYTE)e_cyl;					/* End cylinder */
+		st_dword(p + 8, s_part);			/* Start sector in LBA */
+		st_dword(p + 12, sz_part);			/* Number of sectors */
+
+		/* Next partition */
+		b_cyl += p_cyl;
+	}
+	st_word(p, 0xAA55);		/* MBR signature (always at offset 510) */
+
+	/* Write it to the MBR */
+	res = (disk_write(pdrv, buf, 0, 1) == RES_OK && disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
+	LEAVE_MKFS(res);
+}
+
+#endif /* FF_MULTI_PARTITION */
+#endif /* FF_USE_MKFS && !FF_FS_READONLY */
+
+
+
+
+#if FF_USE_STRFUNC
+#if FF_USE_LFN && FF_LFN_UNICODE && (FF_STRF_ENCODE < 0 || FF_STRF_ENCODE > 3)
+#error Wrong FF_STRF_ENCODE setting
+#endif
+/*-----------------------------------------------------------------------*/
+/* Get a String from the File                                            */
+/*-----------------------------------------------------------------------*/
+
+TCHAR* f_gets (
+	TCHAR* buff,	/* Pointer to the string buffer to read */
+	int len,		/* Size of string buffer (items) */
+	FIL* fp			/* Pointer to the file object */
+)
+{
+	int nc = 0;
+	TCHAR *p = buff;
+	BYTE s[4];
+	UINT rc;
+	DWORD dc;
+#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2
+	WCHAR wc;
+#endif
+#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3
+	UINT ct;
+#endif
+
+#if FF_USE_LFN && FF_LFN_UNICODE			/* With code conversion (Unicode API) */
+	/* Make a room for the character and terminator  */
+	if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2;
+	if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4;
+	if (FF_LFN_UNICODE == 3) len -= 1;
+	while (nc < len) {
+#if FF_STRF_ENCODE == 0		/* Read a character in ANSI/OEM */
+		f_read(fp, s, 1, &rc);
+		if (rc != 1) break;
+		wc = s[0];
+		if (dbc_1st((BYTE)wc)) {
+			f_read(fp, s, 1, &rc);
+			if (rc != 1 || !dbc_2nd(s[0])) continue;
+			wc = wc << 8 | s[0];
+		}
+		dc = ff_oem2uni(wc, CODEPAGE);
+		if (dc == 0) continue;
+#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 	/* Read a character in UTF-16LE/BE */
+		f_read(fp, s, 2, &rc);
+		if (rc != 2) break;
+		dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
+		if (IsSurrogateL(dc)) continue;
+		if (IsSurrogateH(dc)) {
+			f_read(fp, s, 2, &rc);
+			if (rc != 2) break;
+			wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
+			if (!IsSurrogateL(wc)) continue;
+			dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF);
+		}
+#else	/* Read a character in UTF-8 */
+		f_read(fp, s, 1, &rc);
+		if (rc != 1) break;
+		dc = s[0];
+		if (dc >= 0x80) {	/* Multi-byte character? */
+			ct = 0;
+			if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; }	/* 2-byte? */
+			if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; }	/* 3-byte? */
+			if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; }	/* 4-byte? */
+			if (ct == 0) continue;
+			f_read(fp, s, ct, &rc);		/* Get trailing bytes */
+			if (rc != ct) break;
+			rc = 0;
+			do {	/* Merge trailing bytes */
+				if ((s[rc] & 0xC0) != 0x80) break;
+				dc = dc << 6 | (s[rc] & 0x3F);
+			} while (++rc < ct);
+			if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue;	/* Wrong encoding? */
+		}
+#endif
+		if (FF_USE_STRFUNC == 2 && dc == '\r') continue;	/* Strip \r off if needed */
+#if FF_LFN_UNICODE == 1	|| FF_LFN_UNICODE == 3	/* Output it in UTF-16/32 encoding */
+		if (FF_LFN_UNICODE == 1 && dc >= 0x10000) {	/* Out of BMP at UTF-16? */
+			*p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++;	/* Make and output high surrogate */
+			dc = 0xDC00 | (dc & 0x3FF);		/* Make low surrogate */
+		}
+		*p++ = (TCHAR)dc; nc++;
+		if (dc == '\n') break;	/* End of line? */
+#elif FF_LFN_UNICODE == 2		/* Output it in UTF-8 encoding */
+		if (dc < 0x80) {	/* 1-byte */
+			*p++ = (TCHAR)dc;
+			nc++;
+			if (dc == '\n') break;	/* End of line? */
+		} else {
+			if (dc < 0x800) {		/* 2-byte */
+				*p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F));
+				*p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
+				nc += 2;
+			} else {
+				if (dc < 0x10000) {	/* 3-byte */
+					*p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F));
+					*p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
+					*p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
+					nc += 3;
+				} else {			/* 4-byte */
+					*p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07));
+					*p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F));
+					*p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
+					*p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
+					nc += 4;
+				}
+			}
+		}
+#endif
+	}
+
+#else			/* Byte-by-byte without any conversion (ANSI/OEM API) */
+	len -= 1;	/* Make a room for the terminator */
+	while (nc < len) {
+		f_read(fp, s, 1, &rc);
+		if (rc != 1) break;
+		dc = s[0];
+		if (FF_USE_STRFUNC == 2 && dc == '\r') continue;
+		*p++ = (TCHAR)dc; nc++;
+		if (dc == '\n') break;
+	}
+#endif
+
+	*p = 0;		/* Terminate the string */
+	return nc ? buff : 0;	/* When no data read due to EOF or error, return with error. */
+}
+
+
+
+
+#if !FF_FS_READONLY
+#include <stdarg.h>
+/*-----------------------------------------------------------------------*/
+/* Put a Character to the File                                           */
+/*-----------------------------------------------------------------------*/
+
+typedef struct {	/* Putchar output buffer and work area */
+	FIL *fp;		/* Ptr to the writing file */
+	int idx, nchr;	/* Write index of buf[] (-1:error), number of encoding units written */
+#if FF_USE_LFN && FF_LFN_UNICODE == 1
+	WCHAR hs;
+#elif FF_USE_LFN && FF_LFN_UNICODE == 2
+	BYTE bs[4];
+	UINT wi, ct;
+#endif
+	BYTE buf[64];	/* Write buffer */
+} putbuff;
+
+
+static void putc_bfd (		/* Buffered write with code conversion */
+	putbuff* pb,
+	TCHAR c
+)
+{
+	UINT n;
+	int i, nc;
+#if FF_USE_LFN && FF_LFN_UNICODE
+	WCHAR hs, wc;
+#if FF_LFN_UNICODE == 2
+	DWORD dc;
+	TCHAR *tp;
+#endif
+#endif
+
+	if (FF_USE_STRFUNC == 2 && c == '\n') {	 /* LF -> CRLF conversion */
+		putc_bfd(pb, '\r');
+	}
+
+	i = pb->idx;			/* Write index of pb->buf[] */
+	if (i < 0) return;
+	nc = pb->nchr;			/* Write unit counter */
+
+#if FF_USE_LFN && FF_LFN_UNICODE
+#if FF_LFN_UNICODE == 1		/* UTF-16 input */
+	if (IsSurrogateH(c)) {
+		pb->hs = c; return;
+	}
+	hs = pb->hs; pb->hs = 0;
+	if (hs != 0) {
+		if (!IsSurrogateL(c)) hs = 0;
+	} else {
+		if (IsSurrogateL(c)) return;
+	}
+	wc = c;
+#elif FF_LFN_UNICODE == 2	/* UTF-8 input */
+	for (;;) {
+		if (pb->ct == 0) {	/* Out of multi-byte sequence? */
+			pb->bs[pb->wi = 0] = (BYTE)c;	/* Save 1st byte */
+			if ((BYTE)c < 0x80) break;					/* 1-byte? */
+			if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1;	/* 2-byte? */
+			if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2;	/* 3-byte? */
+			if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3;	/* 4-byte? */
+			return;
+		} else {				/* In the multi-byte sequence */
+			if (((BYTE)c & 0xC0) != 0x80) {	/* Broken sequence? */
+				pb->ct = 0; continue;
+			}
+			pb->bs[++pb->wi] = (BYTE)c;	/* Save the trailing byte */
+			if (--pb->ct == 0) break;	/* End of multi-byte sequence? */
+			return;
+		}
+	}
+	tp = (TCHAR*)pb->bs;
+	dc = tchar2uni(&tp);	/* UTF-8 ==> UTF-16 */
+	if (dc == 0xFFFFFFFF) return;
+	wc = (WCHAR)dc;
+	hs = (WCHAR)(dc >> 16);
+#elif FF_LFN_UNICODE == 3	/* UTF-32 input */
+	if (IsSurrogate(c) || c >= 0x110000) return;
+	if (c >= 0x10000) {
+		hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); 	/* Make high surrogate */
+		wc = 0xDC00 | (c & 0x3FF);					/* Make low surrogate */
+	} else {
+		hs = 0;
+		wc = (WCHAR)c;
+	}
+#endif
+
+#if FF_STRF_ENCODE == 1		/* Write a character in UTF-16LE */
+	if (hs != 0) {
+		st_word(&pb->buf[i], hs);
+		i += 2;
+		nc++;
+	}
+	st_word(&pb->buf[i], wc);
+	i += 2;
+#elif FF_STRF_ENCODE == 2	/* Write a character in UTF-16BE */
+	if (hs != 0) {
+		pb->buf[i++] = (BYTE)(hs >> 8);
+		pb->buf[i++] = (BYTE)hs;
+		nc++;
+	}
+	pb->buf[i++] = (BYTE)(wc >> 8);
+	pb->buf[i++] = (BYTE)wc;
+#elif FF_STRF_ENCODE == 3	/* Write it in UTF-8 */
+	if (hs != 0) {				/* 4-byte */
+		nc += 3;
+		hs = (hs & 0x3FF) + 0x40;
+		pb->buf[i++] = (BYTE)(0xF0 | hs >> 8);
+		pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F));
+		pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F));
+		pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F));
+	} else {
+		if (wc < 0x80) {		/* 1-byte */
+			pb->buf[i++] = (BYTE)wc;
+		} else {
+			if (wc < 0x800) {	/* 2-byte */
+				nc += 1;
+				pb->buf[i++] = (BYTE)(0xC0 | wc >> 6);
+			} else {			/* 3-byte */
+				nc += 2;
+				pb->buf[i++] = (BYTE)(0xE0 | wc >> 12);
+				pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F));
+			}
+			pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F));
+		}
+	}
+#else						/* Write it in ANSI/OEM */
+	if (hs != 0) return;
+	wc = ff_uni2oem(wc, CODEPAGE);	/* UTF-16 ==> ANSI/OEM */
+	if (wc == 0) return;
+	if (wc >= 0x100) {
+		pb->buf[i++] = (BYTE)(wc >> 8); nc++;
+	}
+	pb->buf[i++] = (BYTE)wc;
+#endif
+
+#else									/* ANSI/OEM input (without re-encode) */
+	pb->buf[i++] = (BYTE)c;
+#endif
+
+	if (i >= (int)(sizeof pb->buf) - 4) {	/* Write buffered characters to the file */
+		f_write(pb->fp, pb->buf, (UINT)i, &n);
+		i = (n == (UINT)i) ? 0 : -1;
+	}
+	pb->idx = i;
+	pb->nchr = nc + 1;
+}
+
+
+static int putc_flush (		/* Flush left characters in the buffer */
+	putbuff* pb
+)
+{
+	UINT nw;
+
+	if (   pb->idx >= 0	/* Flush buffered characters to the file */
+		&& f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK
+		&& (UINT)pb->idx == nw) return pb->nchr;
+	return EOF;
+}
+
+
+static void putc_init (		/* Initialize write buffer */
+	putbuff* pb,
+	FIL* fp
+)
+{
+	mem_set(pb, 0, sizeof (putbuff));
+	pb->fp = fp;
+}
+
+
+
+int f_putc (
+	TCHAR c,	/* A character to be output */
+	FIL* fp		/* Pointer to the file object */
+)
+{
+	putbuff pb;
+
+
+	putc_init(&pb, fp);
+	putc_bfd(&pb, c);	/* Put the character */
+	return putc_flush(&pb);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Put a String to the File                                              */
+/*-----------------------------------------------------------------------*/
+
+int f_puts (
+	const TCHAR* str,	/* Pointer to the string to be output */
+	FIL* fp				/* Pointer to the file object */
+)
+{
+	putbuff pb;
+
+
+	putc_init(&pb, fp);
+	while (*str) putc_bfd(&pb, *str++);		/* Put the string */
+	return putc_flush(&pb);
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Put a Formatted String to the File                                    */
+/*-----------------------------------------------------------------------*/
+
+int f_printf (
+	FIL* fp,			/* Pointer to the file object */
+	const TCHAR* fmt,	/* Pointer to the format string */
+	...					/* Optional arguments... */
+)
+{
+	va_list arp;
+	putbuff pb;
+	BYTE f, r;
+	UINT i, j, w;
+	DWORD v;
+	TCHAR c, d, str[32], *p;
+
+
+	putc_init(&pb, fp);
+
+	va_start(arp, fmt);
+
+	for (;;) {
+		c = *fmt++;
+		if (c == 0) break;			/* End of string */
+		if (c != '%') {				/* Non escape character */
+			putc_bfd(&pb, c);
+			continue;
+		}
+		w = f = 0;
+		c = *fmt++;
+		if (c == '0') {				/* Flag: '0' padding */
+			f = 1; c = *fmt++;
+		} else {
+			if (c == '-') {			/* Flag: left justified */
+				f = 2; c = *fmt++;
+			}
+		}
+		if (c == '*') {				/* Minimum width by argument */
+			w = va_arg(arp, int);
+			c = *fmt++;
+		} else {
+			while (IsDigit(c)) {	/* Minimum width */
+				w = w * 10 + c - '0';
+				c = *fmt++;
+			}
+		}
+		if (c == 'l' || c == 'L') {	/* Type prefix: Size is long int */
+			f |= 4; c = *fmt++;
+		}
+		if (c == 0) break;
+		d = c;
+		if (IsLower(d)) d -= 0x20;
+		switch (d) {				/* Atgument type is... */
+		case 'S' :					/* String */
+			p = va_arg(arp, TCHAR*);
+			for (j = 0; p[j]; j++) ;
+			if (!(f & 2)) {						/* Right padded */
+				while (j++ < w) putc_bfd(&pb, ' ') ;
+			}
+			while (*p) putc_bfd(&pb, *p++) ;		/* String body */
+			while (j++ < w) putc_bfd(&pb, ' ') ;	/* Left padded */
+			continue;
+
+		case 'C' :					/* Character */
+			putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue;
+
+		case 'B' :					/* Unsigned binary */
+			r = 2; break;
+
+		case 'O' :					/* Unsigned octal */
+			r = 8; break;
+
+		case 'D' :					/* Signed decimal */
+		case 'U' :					/* Unsigned decimal */
+			r = 10; break;
+
+		case 'X' :					/* Unsigned hexdecimal */
+			r = 16; break;
+
+		default:					/* Unknown type (pass-through) */
+			putc_bfd(&pb, c); continue;
+		}
+
+		/* Get an argument and put it in numeral */
+		v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int));
+		if (d == 'D' && (v & 0x80000000)) {
+			v = 0 - v;
+			f |= 8;
+		}
+		i = 0;
+		do {
+			d = (TCHAR)(v % r); v /= r;
+			if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
+			str[i++] = d + '0';
+		} while (v && i < sizeof str / sizeof *str);
+		if (f & 8) str[i++] = '-';
+		j = i; d = (f & 1) ? '0' : ' ';
+		if (!(f & 2)) {
+			while (j++ < w) putc_bfd(&pb, d);	/* Right pad */
+		}
+		do {
+			putc_bfd(&pb, str[--i]);			/* Number body */
+		} while (i);
+		while (j++ < w) putc_bfd(&pb, d);		/* Left pad */
+	}
+
+	va_end(arp);
+
+	return putc_flush(&pb);
+}
+
+#endif /* !FF_FS_READONLY */
+#endif /* FF_USE_STRFUNC */
+
+
+
+#if FF_CODE_PAGE == 0
+/*-----------------------------------------------------------------------*/
+/* Set Active Codepage for the Path Name                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_setcp (
+	WORD cp		/* Value to be set as active code page */
+)
+{
+	static const WORD       validcp[] = {  437,   720,   737,   771,   775,   850,   852,   857,   860,   861,   862,   863,   864,   865,   866,   869,   932,   936,   949,   950, 0};
+	static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0};
+	UINT i;
+
+
+	for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ;	/* Find the code page */
+	if (validcp[i] != cp) return FR_INVALID_PARAMETER;	/* Not found? */
+
+	CodePage = cp;
+	if (cp >= 900) {	/* DBCS */
+		ExCvt = 0;
+		DbcTbl = tables[i];
+	} else {			/* SBCS */
+		ExCvt = tables[i];
+		DbcTbl = 0;
+	}
+	return FR_OK;
+}
+#endif	/* FF_CODE_PAGE == 0 */
+

+ 405 - 405
app/fatfs/ff.h

@@ -1,405 +1,405 @@
-/*----------------------------------------------------------------------------/
-/  FatFs - Generic FAT Filesystem module  R0.13c                              /
-/-----------------------------------------------------------------------------/
-/
-/ Copyright (C) 2018, ChaN, all right reserved.
-/
-/ FatFs module is an open source software. Redistribution and use of FatFs in
-/ source and binary forms, with or without modification, are permitted provided
-/ that the following condition is met:
-
-/ 1. Redistributions of source code must retain the above copyright notice,
-/    this condition and the following disclaimer.
-/
-/ This software is provided by the copyright holder and contributors "AS IS"
-/ and any warranties related to this software are DISCLAIMED.
-/ The copyright owner or contributors be NOT LIABLE for any damages caused
-/ by use of this software.
-/
-/----------------------------------------------------------------------------*/
-
-
-#ifndef FF_DEFINED
-#define FF_DEFINED	86604	/* Revision ID */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ffconf.h"		/* FatFs configuration options */
-
-#if FF_DEFINED != FFCONF_DEF
-#error Wrong configuration file (ffconf.h).
-#endif
-
-
-/* Integer types used for FatFs API */
-
-#if defined(_WIN32)	/* Main development platform */
-#define FF_INTDEF 2
-#include <windows.h>
-typedef unsigned __int64 QWORD;
-#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus)	/* C99 or later */
-#define FF_INTDEF 2
-#include <stdint.h>
-typedef unsigned int	UINT;	/* int must be 16-bit or 32-bit */
-typedef unsigned char	BYTE;	/* char must be 8-bit */
-typedef uint16_t		WORD;	/* 16-bit unsigned integer */
-typedef uint16_t		WCHAR;	/* 16-bit unsigned integer */
-typedef uint32_t		DWORD;	/* 32-bit unsigned integer */
-typedef uint64_t		QWORD;	/* 64-bit unsigned integer */
-#else  	/* Earlier than C99 */
-#define FF_INTDEF 1
-typedef unsigned int	UINT;	/* int must be 16-bit or 32-bit */
-typedef unsigned char	BYTE;	/* char must be 8-bit */
-typedef unsigned short	WORD;	/* 16-bit unsigned integer */
-typedef unsigned short	WCHAR;	/* 16-bit unsigned integer */
-typedef unsigned long	DWORD;	/* 32-bit unsigned integer */
-#endif
-
-
-/* Definitions of volume management */
-
-#if FF_MULTI_PARTITION		/* Multiple partition configuration */
-typedef struct {
-	BYTE pd;	/* Physical drive number */
-	BYTE pt;	/* Partition: 0:Auto detect, 1-4:Forced partition) */
-} PARTITION;
-extern PARTITION VolToPart[];	/* Volume - Partition resolution table */
-#endif
-
-#if FF_STR_VOLUME_ID
-#ifndef FF_VOLUME_STRS
-extern const char* VolumeStr[FF_VOLUMES];	/* User defied volume ID */
-#endif
-#endif
-
-
-
-/* Type of path name strings on FatFs API */
-
-#ifndef _INC_TCHAR
-#define _INC_TCHAR
-
-#if FF_USE_LFN && FF_LFN_UNICODE == 1 	/* Unicode in UTF-16 encoding */
-typedef WCHAR TCHAR;
-#define _T(x) L ## x
-#define _TEXT(x) L ## x
-#elif FF_USE_LFN && FF_LFN_UNICODE == 2	/* Unicode in UTF-8 encoding */
-typedef char TCHAR;
-#define _T(x) u8 ## x
-#define _TEXT(x) u8 ## x
-#elif FF_USE_LFN && FF_LFN_UNICODE == 3	/* Unicode in UTF-32 encoding */
-typedef DWORD TCHAR;
-#define _T(x) U ## x
-#define _TEXT(x) U ## x
-#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
-#error Wrong FF_LFN_UNICODE setting
-#else									/* ANSI/OEM code in SBCS/DBCS */
-typedef char TCHAR;
-#define _T(x) x
-#define _TEXT(x) x
-#endif
-
-#endif
-
-
-
-/* Type of file size variables */
-
-#if FF_FS_EXFAT
-#if FF_INTDEF != 2
-#error exFAT feature wants C99 or later
-#endif
-typedef QWORD FSIZE_t;
-#else
-typedef DWORD FSIZE_t;
-#endif
-
-
-
-/* Filesystem object structure (FATFS) */
-
-typedef struct {
-	BYTE	fs_type;		/* Filesystem type (0:not mounted) */
-	BYTE	pdrv;			/* Associated physical drive */
-	BYTE	n_fats;			/* Number of FATs (1 or 2) */
-	BYTE	wflag;			/* win[] flag (b0:dirty) */
-	BYTE	fsi_flag;		/* FSINFO flags (b7:disabled, b0:dirty) */
-	WORD	id;				/* Volume mount ID */
-	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */
-	WORD	csize;			/* Cluster size [sectors] */
-#if FF_MAX_SS != FF_MIN_SS
-	WORD	ssize;			/* Sector size (512, 1024, 2048 or 4096) */
-#endif
-#if FF_USE_LFN
-	WCHAR*	lfnbuf;			/* LFN working buffer */
-#endif
-#if FF_FS_EXFAT
-	BYTE*	dirbuf;			/* Directory entry block scratchpad buffer for exFAT */
-#endif
-#if FF_FS_REENTRANT
-	FF_SYNC_t	sobj;		/* Identifier of sync object */
-#endif
-#if !FF_FS_READONLY
-	DWORD	last_clst;		/* Last allocated cluster */
-	DWORD	free_clst;		/* Number of free clusters */
-#endif
-#if FF_FS_RPATH
-	DWORD	cdir;			/* Current directory start cluster (0:root) */
-#if FF_FS_EXFAT
-	DWORD	cdc_scl;		/* Containing directory start cluster (invalid when cdir is 0) */
-	DWORD	cdc_size;		/* b31-b8:Size of containing directory, b7-b0: Chain status */
-	DWORD	cdc_ofs;		/* Offset in the containing directory (invalid when cdir is 0) */
-#endif
-#endif
-	DWORD	n_fatent;		/* Number of FAT entries (number of clusters + 2) */
-	DWORD	fsize;			/* Size of an FAT [sectors] */
-	DWORD	volbase;		/* Volume base sector */
-	DWORD	fatbase;		/* FAT base sector */
-	DWORD	dirbase;		/* Root directory base sector/cluster */
-	DWORD	database;		/* Data base sector */
-#if FF_FS_EXFAT
-	DWORD	bitbase;		/* Allocation bitmap base sector */
-#endif
-	DWORD	winsect;		/* Current sector appearing in the win[] */
-	BYTE	win[FF_MAX_SS];	/* Disk access window for Directory, FAT (and file data at tiny cfg) */
-} FATFS;
-
-
-
-/* Object ID and allocation information (FFOBJID) */
-
-typedef struct {
-	FATFS*	fs;				/* Pointer to the hosting volume of this object */
-	WORD	id;				/* Hosting volume mount ID */
-	BYTE	attr;			/* Object attribute */
-	BYTE	stat;			/* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
-	DWORD	sclust;			/* Object data start cluster (0:no cluster or root directory) */
-	FSIZE_t	objsize;		/* Object size (valid when sclust != 0) */
-#if FF_FS_EXFAT
-	DWORD	n_cont;			/* Size of first fragment - 1 (valid when stat == 3) */
-	DWORD	n_frag;			/* Size of last fragment needs to be written to FAT (valid when not zero) */
-	DWORD	c_scl;			/* Containing directory start cluster (valid when sclust != 0) */
-	DWORD	c_size;			/* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
-	DWORD	c_ofs;			/* Offset in the containing directory (valid when file object and sclust != 0) */
-#endif
-#if FF_FS_LOCK
-	UINT	lockid;			/* File lock ID origin from 1 (index of file semaphore table Files[]) */
-#endif
-} FFOBJID;
-
-
-
-/* File object structure (FIL) */
-
-typedef struct {
-	FFOBJID	obj;			/* Object identifier (must be the 1st member to detect invalid object pointer) */
-	BYTE	flag;			/* File status flags */
-	BYTE	err;			/* Abort flag (error code) */
-	FSIZE_t	fptr;			/* File read/write pointer (Zeroed on file open) */
-	DWORD	clust;			/* Current cluster of fpter (invalid when fptr is 0) */
-	DWORD	sect;			/* Sector number appearing in buf[] (0:invalid) */
-#if !FF_FS_READONLY
-	DWORD	dir_sect;		/* Sector number containing the directory entry (not used at exFAT) */
-	BYTE*	dir_ptr;		/* Pointer to the directory entry in the win[] (not used at exFAT) */
-#endif
-#if FF_USE_FASTSEEK
-	DWORD*	cltbl;			/* Pointer to the cluster link map table (nulled on open, set by application) */
-#endif
-#if !FF_FS_TINY
-	BYTE	buf[FF_MAX_SS];	/* File private data read/write window */
-#endif
-} FIL;
-
-
-
-/* Directory object structure (DIR) */
-
-typedef struct {
-	FFOBJID	obj;			/* Object identifier */
-	DWORD	dptr;			/* Current read/write offset */
-	DWORD	clust;			/* Current cluster */
-	DWORD	sect;			/* Current sector (0:Read operation has terminated) */
-	BYTE*	dir;			/* Pointer to the directory item in the win[] */
-	BYTE	fn[12];			/* SFN (in/out) {body[8],ext[3],status[1]} */
-#if FF_USE_LFN
-	DWORD	blk_ofs;		/* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
-#endif
-#if FF_USE_FIND
-	const TCHAR* pat;		/* Pointer to the name matching pattern */
-#endif
-} DIR;
-
-
-
-/* File information structure (FILINFO) */
-
-typedef struct {
-	FSIZE_t	fsize;			/* File size */
-	WORD	fdate;			/* Modified date */
-	WORD	ftime;			/* Modified time */
-	BYTE	fattrib;		/* File attribute */
-#if FF_USE_LFN
-	TCHAR	altname[FF_SFN_BUF + 1];/* Altenative file name */
-	TCHAR	fname[FF_LFN_BUF + 1];	/* Primary file name */
-#else
-	TCHAR	fname[12 + 1];	/* File name */
-#endif
-} FILINFO;
-
-
-
-/* File function return code (FRESULT) */
-
-typedef enum {
-	FR_OK = 0,				/* (0) Succeeded */
-	FR_DISK_ERR,			/* (1) A hard error occurred in the low level disk I/O layer */
-	FR_INT_ERR,				/* (2) Assertion failed */
-	FR_NOT_READY,			/* (3) The physical drive cannot work */
-	FR_NO_FILE,				/* (4) Could not find the file */
-	FR_NO_PATH,				/* (5) Could not find the path */
-	FR_INVALID_NAME,		/* (6) The path name format is invalid */
-	FR_DENIED,				/* (7) Access denied due to prohibited access or directory full */
-	FR_EXIST,				/* (8) Access denied due to prohibited access */
-	FR_INVALID_OBJECT,		/* (9) The file/directory object is invalid */
-	FR_WRITE_PROTECTED,		/* (10) The physical drive is write protected */
-	FR_INVALID_DRIVE,		/* (11) The logical drive number is invalid */
-	FR_NOT_ENABLED,			/* (12) The volume has no work area */
-	FR_NO_FILESYSTEM,		/* (13) There is no valid FAT volume */
-	FR_MKFS_ABORTED,		/* (14) The f_mkfs() aborted due to any problem */
-	FR_TIMEOUT,				/* (15) Could not get a grant to access the volume within defined period */
-	FR_LOCKED,				/* (16) The operation is rejected according to the file sharing policy */
-	FR_NOT_ENOUGH_CORE,		/* (17) LFN working buffer could not be allocated */
-	FR_TOO_MANY_OPEN_FILES,	/* (18) Number of open files > FF_FS_LOCK */
-	FR_INVALID_PARAMETER	/* (19) Given parameter is invalid */
-} FRESULT;
-
-
-
-/*--------------------------------------------------------------*/
-/* FatFs module application interface                           */
-
-FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);				/* Open or create a file */
-FRESULT f_close (FIL* fp);											/* Close an open file object */
-FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);			/* Read data from the file */
-FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);	/* Write data to the file */
-FRESULT f_lseek (FIL* fp, FSIZE_t ofs);								/* Move file pointer of the file object */
-FRESULT f_truncate (FIL* fp);										/* Truncate the file */
-FRESULT f_sync (FIL* fp);											/* Flush cached data of the writing file */
-FRESULT f_opendir (DIR* dp, const TCHAR* path);						/* Open a directory */
-FRESULT f_closedir (DIR* dp);										/* Close an open directory */
-FRESULT f_readdir (DIR* dp, FILINFO* fno);							/* Read a directory item */
-FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);	/* Find first file */
-FRESULT f_findnext (DIR* dp, FILINFO* fno);							/* Find next file */
-FRESULT f_mkdir (const TCHAR* path);								/* Create a sub directory */
-FRESULT f_unlink (const TCHAR* path);								/* Delete an existing file or directory */
-FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new);	/* Rename/Move a file or directory */
-FRESULT f_stat (const TCHAR* path, FILINFO* fno);					/* Get file status */
-FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask);			/* Change attribute of a file/dir */
-FRESULT f_utime (const TCHAR* path, const FILINFO* fno);			/* Change timestamp of a file/dir */
-FRESULT f_chdir (const TCHAR* path);								/* Change current directory */
-FRESULT f_chdrive (const TCHAR* path);								/* Change current drive */
-FRESULT f_getcwd (TCHAR* buff, UINT len);							/* Get current directory */
-FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs);	/* Get number of free clusters on the drive */
-FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn);	/* Get volume label */
-FRESULT f_setlabel (const TCHAR* label);							/* Set volume label */
-FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf);	/* Forward data to the stream */
-FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt);					/* Allocate a contiguous block to the file */
-FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);			/* Mount/Unmount a logical drive */
-FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len);	/* Create a FAT volume */
-FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work);			/* Divide a physical drive into some partitions */
-FRESULT f_setcp (WORD cp);											/* Set current code page */
-int f_putc (TCHAR c, FIL* fp);										/* Put a character to the file */
-int f_puts (const TCHAR* str, FIL* cp);								/* Put a string to the file */
-int f_printf (FIL* fp, const TCHAR* str, ...);						/* Put a formatted string to the file */
-TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);						/* Get a string from the file */
-
-#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
-#define f_error(fp) ((fp)->err)
-#define f_tell(fp) ((fp)->fptr)
-#define f_size(fp) ((fp)->obj.objsize)
-#define f_rewind(fp) f_lseek((fp), 0)
-#define f_rewinddir(dp) f_readdir((dp), 0)
-#define f_rmdir(path) f_unlink(path)
-#define f_unmount(path) f_mount(0, path, 0)
-
-#ifndef EOF
-#define EOF (-1)
-#endif
-
-
-
-
-/*--------------------------------------------------------------*/
-/* Additional user defined functions                            */
-
-/* RTC function */
-#if !FF_FS_READONLY && !FF_FS_NORTC
-DWORD get_fattime (void);
-#endif
-
-/* LFN support functions */
-#if FF_USE_LFN >= 1						/* Code conversion (defined in unicode.c) */
-WCHAR ff_oem2uni (WCHAR oem, WORD cp);	/* OEM code to Unicode conversion */
-WCHAR ff_uni2oem (DWORD uni, WORD cp);	/* Unicode to OEM code conversion */
-DWORD ff_wtoupper (DWORD uni);			/* Unicode upper-case conversion */
-#endif
-#if FF_USE_LFN == 3						/* Dynamic memory allocation */
-void* ff_memalloc (UINT msize);			/* Allocate memory block */
-void ff_memfree (void* mblock);			/* Free memory block */
-#endif
-
-/* Sync functions */
-#if FF_FS_REENTRANT
-int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj);	/* Create a sync object */
-int ff_req_grant (FF_SYNC_t sobj);		/* Lock sync object */
-void ff_rel_grant (FF_SYNC_t sobj);		/* Unlock sync object */
-int ff_del_syncobj (FF_SYNC_t sobj);	/* Delete a sync object */
-#endif
-
-
-
-
-/*--------------------------------------------------------------*/
-/* Flags and offset address                                     */
-
-
-/* File access mode and open method flags (3rd argument of f_open) */
-#define	FA_READ				0x01
-#define	FA_WRITE			0x02
-#define	FA_OPEN_EXISTING	0x00
-#define	FA_CREATE_NEW		0x04
-#define	FA_CREATE_ALWAYS	0x08
-#define	FA_OPEN_ALWAYS		0x10
-#define	FA_OPEN_APPEND		0x30
-
-/* Fast seek controls (2nd argument of f_lseek) */
-#define CREATE_LINKMAP	((FSIZE_t)0 - 1)
-
-/* Format options (2nd argument of f_mkfs) */
-#define FM_FAT		0x01
-#define FM_FAT32	0x02
-#define FM_EXFAT	0x04
-#define FM_ANY		0x07
-#define FM_SFD		0x08
-
-/* Filesystem type (FATFS.fs_type) */
-#define FS_FAT12	1
-#define FS_FAT16	2
-#define FS_FAT32	3
-#define FS_EXFAT	4
-
-/* File attribute bits for directory entry (FILINFO.fattrib) */
-#define	AM_RDO	0x01	/* Read only */
-#define	AM_HID	0x02	/* Hidden */
-#define	AM_SYS	0x04	/* System */
-#define AM_DIR	0x10	/* Directory */
-#define AM_ARC	0x20	/* Archive */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* FF_DEFINED */
+/*----------------------------------------------------------------------------/
+/  FatFs - Generic FAT Filesystem module  R0.13c                              /
+/-----------------------------------------------------------------------------/
+/
+/ Copyright (C) 2018, ChaN, all right reserved.
+/
+/ FatFs module is an open source software. Redistribution and use of FatFs in
+/ source and binary forms, with or without modification, are permitted provided
+/ that the following condition is met:
+
+/ 1. Redistributions of source code must retain the above copyright notice,
+/    this condition and the following disclaimer.
+/
+/ This software is provided by the copyright holder and contributors "AS IS"
+/ and any warranties related to this software are DISCLAIMED.
+/ The copyright owner or contributors be NOT LIABLE for any damages caused
+/ by use of this software.
+/
+/----------------------------------------------------------------------------*/
+
+
+#ifndef FF_DEFINED
+#define FF_DEFINED	86604	/* Revision ID */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ffconf.h"		/* FatFs configuration options */
+
+#if FF_DEFINED != FFCONF_DEF
+#error Wrong configuration file (ffconf.h).
+#endif
+
+
+/* Integer types used for FatFs API */
+
+#if defined(_WIN32)	/* Main development platform */
+#define FF_INTDEF 2
+#include <windows.h>
+typedef unsigned __int64 QWORD;
+#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus)	/* C99 or later */
+#define FF_INTDEF 2
+#include <stdint.h>
+typedef unsigned int	UINT;	/* int must be 16-bit or 32-bit */
+typedef unsigned char	BYTE;	/* char must be 8-bit */
+typedef uint16_t		WORD;	/* 16-bit unsigned integer */
+typedef uint16_t		WCHAR;	/* 16-bit unsigned integer */
+typedef uint32_t		DWORD;	/* 32-bit unsigned integer */
+typedef uint64_t		QWORD;	/* 64-bit unsigned integer */
+#else  	/* Earlier than C99 */
+#define FF_INTDEF 1
+typedef unsigned int	UINT;	/* int must be 16-bit or 32-bit */
+typedef unsigned char	BYTE;	/* char must be 8-bit */
+typedef unsigned short	WORD;	/* 16-bit unsigned integer */
+typedef unsigned short	WCHAR;	/* 16-bit unsigned integer */
+typedef unsigned long	DWORD;	/* 32-bit unsigned integer */
+#endif
+
+
+/* Definitions of volume management */
+
+#if FF_MULTI_PARTITION		/* Multiple partition configuration */
+typedef struct {
+	BYTE pd;	/* Physical drive number */
+	BYTE pt;	/* Partition: 0:Auto detect, 1-4:Forced partition) */
+} PARTITION;
+extern PARTITION VolToPart[];	/* Volume - Partition resolution table */
+#endif
+
+#if FF_STR_VOLUME_ID
+#ifndef FF_VOLUME_STRS
+extern const char* VolumeStr[FF_VOLUMES];	/* User defied volume ID */
+#endif
+#endif
+
+
+
+/* Type of path name strings on FatFs API */
+
+#ifndef _INC_TCHAR
+#define _INC_TCHAR
+
+#if FF_USE_LFN && FF_LFN_UNICODE == 1 	/* Unicode in UTF-16 encoding */
+typedef WCHAR TCHAR;
+#define _T(x) L ## x
+#define _TEXT(x) L ## x
+#elif FF_USE_LFN && FF_LFN_UNICODE == 2	/* Unicode in UTF-8 encoding */
+typedef char TCHAR;
+#define _T(x) u8 ## x
+#define _TEXT(x) u8 ## x
+#elif FF_USE_LFN && FF_LFN_UNICODE == 3	/* Unicode in UTF-32 encoding */
+typedef DWORD TCHAR;
+#define _T(x) U ## x
+#define _TEXT(x) U ## x
+#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
+#error Wrong FF_LFN_UNICODE setting
+#else									/* ANSI/OEM code in SBCS/DBCS */
+typedef char TCHAR;
+#define _T(x) x
+#define _TEXT(x) x
+#endif
+
+#endif
+
+
+
+/* Type of file size variables */
+
+#if FF_FS_EXFAT
+#if FF_INTDEF != 2
+#error exFAT feature wants C99 or later
+#endif
+typedef QWORD FSIZE_t;
+#else
+typedef DWORD FSIZE_t;
+#endif
+
+
+
+/* Filesystem object structure (FATFS) */
+
+typedef struct {
+	BYTE	fs_type;		/* Filesystem type (0:not mounted) */
+	BYTE	pdrv;			/* Associated physical drive */
+	BYTE	n_fats;			/* Number of FATs (1 or 2) */
+	BYTE	wflag;			/* win[] flag (b0:dirty) */
+	BYTE	fsi_flag;		/* FSINFO flags (b7:disabled, b0:dirty) */
+	WORD	id;				/* Volume mount ID */
+	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */
+	WORD	csize;			/* Cluster size [sectors] */
+#if FF_MAX_SS != FF_MIN_SS
+	WORD	ssize;			/* Sector size (512, 1024, 2048 or 4096) */
+#endif
+#if FF_USE_LFN
+	WCHAR*	lfnbuf;			/* LFN working buffer */
+#endif
+#if FF_FS_EXFAT
+	BYTE*	dirbuf;			/* Directory entry block scratchpad buffer for exFAT */
+#endif
+#if FF_FS_REENTRANT
+	FF_SYNC_t	sobj;		/* Identifier of sync object */
+#endif
+#if !FF_FS_READONLY
+	DWORD	last_clst;		/* Last allocated cluster */
+	DWORD	free_clst;		/* Number of free clusters */
+#endif
+#if FF_FS_RPATH
+	DWORD	cdir;			/* Current directory start cluster (0:root) */
+#if FF_FS_EXFAT
+	DWORD	cdc_scl;		/* Containing directory start cluster (invalid when cdir is 0) */
+	DWORD	cdc_size;		/* b31-b8:Size of containing directory, b7-b0: Chain status */
+	DWORD	cdc_ofs;		/* Offset in the containing directory (invalid when cdir is 0) */
+#endif
+#endif
+	DWORD	n_fatent;		/* Number of FAT entries (number of clusters + 2) */
+	DWORD	fsize;			/* Size of an FAT [sectors] */
+	DWORD	volbase;		/* Volume base sector */
+	DWORD	fatbase;		/* FAT base sector */
+	DWORD	dirbase;		/* Root directory base sector/cluster */
+	DWORD	database;		/* Data base sector */
+#if FF_FS_EXFAT
+	DWORD	bitbase;		/* Allocation bitmap base sector */
+#endif
+	DWORD	winsect;		/* Current sector appearing in the win[] */
+	BYTE	win[FF_MAX_SS];	/* Disk access window for Directory, FAT (and file data at tiny cfg) */
+} FATFS;
+
+
+
+/* Object ID and allocation information (FFOBJID) */
+
+typedef struct {
+	FATFS*	fs;				/* Pointer to the hosting volume of this object */
+	WORD	id;				/* Hosting volume mount ID */
+	BYTE	attr;			/* Object attribute */
+	BYTE	stat;			/* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
+	DWORD	sclust;			/* Object data start cluster (0:no cluster or root directory) */
+	FSIZE_t	objsize;		/* Object size (valid when sclust != 0) */
+#if FF_FS_EXFAT
+	DWORD	n_cont;			/* Size of first fragment - 1 (valid when stat == 3) */
+	DWORD	n_frag;			/* Size of last fragment needs to be written to FAT (valid when not zero) */
+	DWORD	c_scl;			/* Containing directory start cluster (valid when sclust != 0) */
+	DWORD	c_size;			/* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
+	DWORD	c_ofs;			/* Offset in the containing directory (valid when file object and sclust != 0) */
+#endif
+#if FF_FS_LOCK
+	UINT	lockid;			/* File lock ID origin from 1 (index of file semaphore table Files[]) */
+#endif
+} FFOBJID;
+
+
+
+/* File object structure (FIL) */
+
+typedef struct {
+	FFOBJID	obj;			/* Object identifier (must be the 1st member to detect invalid object pointer) */
+	BYTE	flag;			/* File status flags */
+	BYTE	err;			/* Abort flag (error code) */
+	FSIZE_t	fptr;			/* File read/write pointer (Zeroed on file open) */
+	DWORD	clust;			/* Current cluster of fpter (invalid when fptr is 0) */
+	DWORD	sect;			/* Sector number appearing in buf[] (0:invalid) */
+#if !FF_FS_READONLY
+	DWORD	dir_sect;		/* Sector number containing the directory entry (not used at exFAT) */
+	BYTE*	dir_ptr;		/* Pointer to the directory entry in the win[] (not used at exFAT) */
+#endif
+#if FF_USE_FASTSEEK
+	DWORD*	cltbl;			/* Pointer to the cluster link map table (nulled on open, set by application) */
+#endif
+#if !FF_FS_TINY
+	BYTE	buf[FF_MAX_SS];	/* File private data read/write window */
+#endif
+} FIL;
+
+
+
+/* Directory object structure (DIR) */
+
+typedef struct {
+	FFOBJID	obj;			/* Object identifier */
+	DWORD	dptr;			/* Current read/write offset */
+	DWORD	clust;			/* Current cluster */
+	DWORD	sect;			/* Current sector (0:Read operation has terminated) */
+	BYTE*	dir;			/* Pointer to the directory item in the win[] */
+	BYTE	fn[12];			/* SFN (in/out) {body[8],ext[3],status[1]} */
+#if FF_USE_LFN
+	DWORD	blk_ofs;		/* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
+#endif
+#if FF_USE_FIND
+	const TCHAR* pat;		/* Pointer to the name matching pattern */
+#endif
+} DIR;
+
+
+
+/* File information structure (FILINFO) */
+
+typedef struct {
+	FSIZE_t	fsize;			/* File size */
+	WORD	fdate;			/* Modified date */
+	WORD	ftime;			/* Modified time */
+	BYTE	fattrib;		/* File attribute */
+#if FF_USE_LFN
+	TCHAR	altname[FF_SFN_BUF + 1];/* Altenative file name */
+	TCHAR	fname[FF_LFN_BUF + 1];	/* Primary file name */
+#else
+	TCHAR	fname[12 + 1];	/* File name */
+#endif
+} FILINFO;
+
+
+
+/* File function return code (FRESULT) */
+
+typedef enum {
+	FR_OK = 0,				/* (0) Succeeded */
+	FR_DISK_ERR,			/* (1) A hard error occurred in the low level disk I/O layer */
+	FR_INT_ERR,				/* (2) Assertion failed */
+	FR_NOT_READY,			/* (3) The physical drive cannot work */
+	FR_NO_FILE,				/* (4) Could not find the file */
+	FR_NO_PATH,				/* (5) Could not find the path */
+	FR_INVALID_NAME,		/* (6) The path name format is invalid */
+	FR_DENIED,				/* (7) Access denied due to prohibited access or directory full */
+	FR_EXIST,				/* (8) Access denied due to prohibited access */
+	FR_INVALID_OBJECT,		/* (9) The file/directory object is invalid */
+	FR_WRITE_PROTECTED,		/* (10) The physical drive is write protected */
+	FR_INVALID_DRIVE,		/* (11) The logical drive number is invalid */
+	FR_NOT_ENABLED,			/* (12) The volume has no work area */
+	FR_NO_FILESYSTEM,		/* (13) There is no valid FAT volume */
+	FR_MKFS_ABORTED,		/* (14) The f_mkfs() aborted due to any problem */
+	FR_TIMEOUT,				/* (15) Could not get a grant to access the volume within defined period */
+	FR_LOCKED,				/* (16) The operation is rejected according to the file sharing policy */
+	FR_NOT_ENOUGH_CORE,		/* (17) LFN working buffer could not be allocated */
+	FR_TOO_MANY_OPEN_FILES,	/* (18) Number of open files > FF_FS_LOCK */
+	FR_INVALID_PARAMETER	/* (19) Given parameter is invalid */
+} FRESULT;
+
+
+
+/*--------------------------------------------------------------*/
+/* FatFs module application interface                           */
+
+FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);				/* Open or create a file */
+FRESULT f_close (FIL* fp);											/* Close an open file object */
+FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);			/* Read data from the file */
+FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);	/* Write data to the file */
+FRESULT f_lseek (FIL* fp, FSIZE_t ofs);								/* Move file pointer of the file object */
+FRESULT f_truncate (FIL* fp);										/* Truncate the file */
+FRESULT f_sync (FIL* fp);											/* Flush cached data of the writing file */
+FRESULT f_opendir (DIR* dp, const TCHAR* path);						/* Open a directory */
+FRESULT f_closedir (DIR* dp);										/* Close an open directory */
+FRESULT f_readdir (DIR* dp, FILINFO* fno);							/* Read a directory item */
+FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);	/* Find first file */
+FRESULT f_findnext (DIR* dp, FILINFO* fno);							/* Find next file */
+FRESULT f_mkdir (const TCHAR* path);								/* Create a sub directory */
+FRESULT f_unlink (const TCHAR* path);								/* Delete an existing file or directory */
+FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new);	/* Rename/Move a file or directory */
+FRESULT f_stat (const TCHAR* path, FILINFO* fno);					/* Get file status */
+FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask);			/* Change attribute of a file/dir */
+FRESULT f_utime (const TCHAR* path, const FILINFO* fno);			/* Change timestamp of a file/dir */
+FRESULT f_chdir (const TCHAR* path);								/* Change current directory */
+FRESULT f_chdrive (const TCHAR* path);								/* Change current drive */
+FRESULT f_getcwd (TCHAR* buff, UINT len);							/* Get current directory */
+FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs);	/* Get number of free clusters on the drive */
+FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn);	/* Get volume label */
+FRESULT f_setlabel (const TCHAR* label);							/* Set volume label */
+FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf);	/* Forward data to the stream */
+FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt);					/* Allocate a contiguous block to the file */
+FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);			/* Mount/Unmount a logical drive */
+FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len);	/* Create a FAT volume */
+FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work);			/* Divide a physical drive into some partitions */
+FRESULT f_setcp (WORD cp);											/* Set current code page */
+int f_putc (TCHAR c, FIL* fp);										/* Put a character to the file */
+int f_puts (const TCHAR* str, FIL* cp);								/* Put a string to the file */
+int f_printf (FIL* fp, const TCHAR* str, ...);						/* Put a formatted string to the file */
+TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);						/* Get a string from the file */
+
+#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
+#define f_error(fp) ((fp)->err)
+#define f_tell(fp) ((fp)->fptr)
+#define f_size(fp) ((fp)->obj.objsize)
+#define f_rewind(fp) f_lseek((fp), 0)
+#define f_rewinddir(dp) f_readdir((dp), 0)
+#define f_rmdir(path) f_unlink(path)
+#define f_unmount(path) f_mount(0, path, 0)
+
+#ifndef EOF
+#define EOF (-1)
+#endif
+
+
+
+
+/*--------------------------------------------------------------*/
+/* Additional user defined functions                            */
+
+/* RTC function */
+#if !FF_FS_READONLY && !FF_FS_NORTC
+DWORD get_fattime (void);
+#endif
+
+/* LFN support functions */
+#if FF_USE_LFN >= 1						/* Code conversion (defined in unicode.c) */
+WCHAR ff_oem2uni (WCHAR oem, WORD cp);	/* OEM code to Unicode conversion */
+WCHAR ff_uni2oem (DWORD uni, WORD cp);	/* Unicode to OEM code conversion */
+DWORD ff_wtoupper (DWORD uni);			/* Unicode upper-case conversion */
+#endif
+#if FF_USE_LFN == 3						/* Dynamic memory allocation */
+void* ff_memalloc (UINT msize);			/* Allocate memory block */
+void ff_memfree (void* mblock);			/* Free memory block */
+#endif
+
+/* Sync functions */
+#if FF_FS_REENTRANT
+int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj);	/* Create a sync object */
+int ff_req_grant (FF_SYNC_t sobj);		/* Lock sync object */
+void ff_rel_grant (FF_SYNC_t sobj);		/* Unlock sync object */
+int ff_del_syncobj (FF_SYNC_t sobj);	/* Delete a sync object */
+#endif
+
+
+
+
+/*--------------------------------------------------------------*/
+/* Flags and offset address                                     */
+
+
+/* File access mode and open method flags (3rd argument of f_open) */
+#define	FA_READ				0x01
+#define	FA_WRITE			0x02
+#define	FA_OPEN_EXISTING	0x00
+#define	FA_CREATE_NEW		0x04
+#define	FA_CREATE_ALWAYS	0x08
+#define	FA_OPEN_ALWAYS		0x10
+#define	FA_OPEN_APPEND		0x30
+
+/* Fast seek controls (2nd argument of f_lseek) */
+#define CREATE_LINKMAP	((FSIZE_t)0 - 1)
+
+/* Format options (2nd argument of f_mkfs) */
+#define FM_FAT		0x01
+#define FM_FAT32	0x02
+#define FM_EXFAT	0x04
+#define FM_ANY		0x07
+#define FM_SFD		0x08
+
+/* Filesystem type (FATFS.fs_type) */
+#define FS_FAT12	1
+#define FS_FAT16	2
+#define FS_FAT32	3
+#define FS_EXFAT	4
+
+/* File attribute bits for directory entry (FILINFO.fattrib) */
+#define	AM_RDO	0x01	/* Read only */
+#define	AM_HID	0x02	/* Hidden */
+#define	AM_SYS	0x04	/* System */
+#define AM_DIR	0x10	/* Directory */
+#define AM_ARC	0x20	/* Archive */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FF_DEFINED */

+ 290 - 290
app/fatfs/ffconf.h

@@ -1,290 +1,290 @@
-/*---------------------------------------------------------------------------/
-/  FatFs Functional Configurations
-/---------------------------------------------------------------------------*/
-
-#define FFCONF_DEF	86604	/* Revision ID */
-
-#include "user_config.h"
-
-/*---------------------------------------------------------------------------/
-/ Function Configurations
-/---------------------------------------------------------------------------*/
-
-#define FF_FS_READONLY	0
-/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
-/  Read-only configuration removes writing API functions, f_write(), f_sync(),
-/  f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
-/  and optional writing functions as well. */
-
-
-#define FF_FS_MINIMIZE	0
-/* This option defines minimization level to remove some basic API functions.
-/
-/   0: Basic functions are fully enabled.
-/   1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
-/      are removed.
-/   2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
-/   3: f_lseek() function is removed in addition to 2. */
-
-
-#define FF_USE_STRFUNC	0
-/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
-/
-/  0: Disable string functions.
-/  1: Enable without LF-CRLF conversion.
-/  2: Enable with LF-CRLF conversion. */
-
-
-#define FF_USE_FIND		0
-/* This option switches filtered directory read functions, f_findfirst() and
-/  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
-
-
-#define FF_USE_MKFS		0
-/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
-
-
-#define FF_USE_FASTSEEK	0
-/* This option switches fast seek function. (0:Disable or 1:Enable) */
-
-
-#define FF_USE_EXPAND	0
-/* This option switches f_expand function. (0:Disable or 1:Enable) */
-
-
-#define FF_USE_CHMOD	1
-/* This option switches attribute manipulation functions, f_chmod() and f_utime().
-/  (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
-
-
-#define FF_USE_LABEL	1
-/* This option switches volume label functions, f_getlabel() and f_setlabel().
-/  (0:Disable or 1:Enable) */
-
-
-#define FF_USE_FORWARD	0
-/* This option switches f_forward() function. (0:Disable or 1:Enable) */
-
-
-/*---------------------------------------------------------------------------/
-/ Locale and Namespace Configurations
-/---------------------------------------------------------------------------*/
-
-#define FF_CODE_PAGE	932
-/* This option specifies the OEM code page to be used on the target system.
-/  Incorrect code page setting can cause a file open failure.
-/
-/   437 - U.S.
-/   720 - Arabic
-/   737 - Greek
-/   771 - KBL
-/   775 - Baltic
-/   850 - Latin 1
-/   852 - Latin 2
-/   855 - Cyrillic
-/   857 - Turkish
-/   860 - Portuguese
-/   861 - Icelandic
-/   862 - Hebrew
-/   863 - Canadian French
-/   864 - Arabic
-/   865 - Nordic
-/   866 - Russian
-/   869 - Greek 2
-/   932 - Japanese (DBCS)
-/   936 - Simplified Chinese (DBCS)
-/   949 - Korean (DBCS)
-/   950 - Traditional Chinese (DBCS)
-/     0 - Include all code pages above and configured by f_setcp()
-*/
-
-
-#define FF_USE_LFN		3
-#define FF_MAX_LFN		(FS_OBJ_NAME_LEN+1+1)
-/* The FF_USE_LFN switches the support for LFN (long file name).
-/
-/   0: Disable LFN. FF_MAX_LFN has no effect.
-/   1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
-/   2: Enable LFN with dynamic working buffer on the STACK.
-/   3: Enable LFN with dynamic working buffer on the HEAP.
-/
-/  To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
-/  requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
-/  additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
-/  The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
-/  be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
-/  specification.
-/  When use stack for the working buffer, take care on stack overflow. When use heap
-/  memory for the working buffer, memory management functions, ff_memalloc() and
-/  ff_memfree() in ffsystem.c, need to be added to the project. */
-
-
-#define FF_LFN_UNICODE	0
-/* This option switches the character encoding on the API when LFN is enabled.
-/
-/   0: ANSI/OEM in current CP (TCHAR = char)
-/   1: Unicode in UTF-16 (TCHAR = WCHAR)
-/   2: Unicode in UTF-8 (TCHAR = char)
-/   3: Unicode in UTF-32 (TCHAR = DWORD)
-/
-/  Also behavior of string I/O functions will be affected by this option.
-/  When LFN is not enabled, this option has no effect. */
-
-
-#define FF_LFN_BUF		255
-#define FF_SFN_BUF		12
-/* This set of options defines size of file name members in the FILINFO structure
-/  which is used to read out directory items. These values should be suffcient for
-/  the file names to read. The maximum possible length of the read file name depends
-/  on character encoding. When LFN is not enabled, these options have no effect. */
-
-
-#define FF_STRF_ENCODE	3
-/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
-/  f_putc(), f_puts and f_printf() convert the character encoding in it.
-/  This option selects assumption of character encoding ON THE FILE to be
-/  read/written via those functions.
-/
-/   0: ANSI/OEM in current CP
-/   1: Unicode in UTF-16LE
-/   2: Unicode in UTF-16BE
-/   3: Unicode in UTF-8
-*/
-
-
-#define FF_FS_RPATH		2
-/* This option configures support for relative path.
-/
-/   0: Disable relative path and remove related functions.
-/   1: Enable relative path. f_chdir() and f_chdrive() are available.
-/   2: f_getcwd() function is available in addition to 1.
-*/
-
-
-/*---------------------------------------------------------------------------/
-/ Drive/Volume Configurations
-/---------------------------------------------------------------------------*/
-
-#define FF_VOLUMES		4
-/* Number of volumes (logical drives) to be used. (1-10) */
-
-
-#define FF_STR_VOLUME_ID	1
-#define FF_VOLUME_STRS		"SD0","SD1","SD2","SD3"
-/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
-/  When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
-/  number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
-/  logical drives. Number of items must not be less than FF_VOLUMES. Valid
-/  characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
-/  compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
-/  not defined, a user defined volume string table needs to be defined as:
-/
-/  const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
-*/
-
-
-#define FF_MULTI_PARTITION	1
-/* This option switches support for multiple volumes on the physical drive.
-/  By default (0), each logical drive number is bound to the same physical drive
-/  number and only an FAT volume found on the physical drive will be mounted.
-/  When this function is enabled (1), each logical drive number can be bound to
-/  arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
-/  funciton will be available. */
-
-
-#define FF_MIN_SS		512
-#define FF_MAX_SS		512
-/* This set of options configures the range of sector size to be supported. (512,
-/  1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
-/  harddisk. But a larger value may be required for on-board flash memory and some
-/  type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
-/  for variable sector size mode and disk_ioctl() function needs to implement
-/  GET_SECTOR_SIZE command. */
-
-
-#define FF_USE_TRIM		0
-/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
-/  To enable Trim function, also CTRL_TRIM command should be implemented to the
-/  disk_ioctl() function. */
-
-
-#define FF_FS_NOFSINFO	0
-/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
-/  option, and f_getfree() function at first time after volume mount will force
-/  a full FAT scan. Bit 1 controls the use of last allocated cluster number.
-/
-/  bit0=0: Use free cluster count in the FSINFO if available.
-/  bit0=1: Do not trust free cluster count in the FSINFO.
-/  bit1=0: Use last allocated cluster number in the FSINFO if available.
-/  bit1=1: Do not trust last allocated cluster number in the FSINFO.
-*/
-
-
-
-/*---------------------------------------------------------------------------/
-/ System Configurations
-/---------------------------------------------------------------------------*/
-
-#define FF_FS_TINY		0
-/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
-/  At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
-/  Instead of private sector buffer eliminated from the file object, common sector
-/  buffer in the filesystem object (FATFS) is used for the file data transfer. */
-
-
-#define FF_FS_EXFAT		0
-/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
-/  To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
-/  Note that enabling exFAT discards ANSI C (C89) compatibility. */
-
-
-#define FF_FS_NORTC		0
-#define FF_NORTC_MON	1
-#define FF_NORTC_MDAY	1
-#define FF_NORTC_YEAR	2018
-/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
-/  any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
-/  the timestamp function. Every object modified by FatFs will have a fixed timestamp
-/  defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
-/  To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
-/  added to the project to read current time form real-time clock. FF_NORTC_MON,
-/  FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
-/  These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
-
-
-#define FF_FS_LOCK		0
-/* The option FF_FS_LOCK switches file lock function to control duplicated file open
-/  and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
-/  is 1.
-/
-/  0:  Disable file lock function. To avoid volume corruption, application program
-/      should avoid illegal open, remove and rename to the open objects.
-/  >0: Enable file lock function. The value defines how many files/sub-directories
-/      can be opened simultaneously under file lock control. Note that the file
-/      lock control is independent of re-entrancy. */
-
-
-/* #include <somertos.h>	// O/S definitions */
-#define FF_FS_REENTRANT	0
-#define FF_FS_TIMEOUT	1000
-#define FF_SYNC_t		HANDLE
-/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
-/  module itself. Note that regardless of this option, file access to different
-/  volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
-/  and f_fdisk() function, are always not re-entrant. Only file/directory access
-/  to the same volume is under control of this function.
-/
-/   0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
-/   1: Enable re-entrancy. Also user provided synchronization handlers,
-/      ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
-/      function, must be added to the project. Samples are available in
-/      option/syscall.c.
-/
-/  The FF_FS_TIMEOUT defines timeout period in unit of time tick.
-/  The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
-/  SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
-/  included somewhere in the scope of ff.h. */
-
-
-
-/*--- End of configuration options ---*/
+/*---------------------------------------------------------------------------/
+/  FatFs Functional Configurations
+/---------------------------------------------------------------------------*/
+
+#define FFCONF_DEF	86604	/* Revision ID */
+
+#include "user_config.h"
+
+/*---------------------------------------------------------------------------/
+/ Function Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_READONLY	0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/  Read-only configuration removes writing API functions, f_write(), f_sync(),
+/  f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/  and optional writing functions as well. */
+
+
+#define FF_FS_MINIMIZE	0
+/* This option defines minimization level to remove some basic API functions.
+/
+/   0: Basic functions are fully enabled.
+/   1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/      are removed.
+/   2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
+/   3: f_lseek() function is removed in addition to 2. */
+
+
+#define FF_USE_STRFUNC	0
+/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
+/
+/  0: Disable string functions.
+/  1: Enable without LF-CRLF conversion.
+/  2: Enable with LF-CRLF conversion. */
+
+
+#define FF_USE_FIND		0
+/* This option switches filtered directory read functions, f_findfirst() and
+/  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
+
+
+#define FF_USE_MKFS		0
+/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
+
+
+#define FF_USE_FASTSEEK	0
+/* This option switches fast seek function. (0:Disable or 1:Enable) */
+
+
+#define FF_USE_EXPAND	0
+/* This option switches f_expand function. (0:Disable or 1:Enable) */
+
+
+#define FF_USE_CHMOD	1
+/* This option switches attribute manipulation functions, f_chmod() and f_utime().
+/  (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
+
+
+#define FF_USE_LABEL	1
+/* This option switches volume label functions, f_getlabel() and f_setlabel().
+/  (0:Disable or 1:Enable) */
+
+
+#define FF_USE_FORWARD	0
+/* This option switches f_forward() function. (0:Disable or 1:Enable) */
+
+
+/*---------------------------------------------------------------------------/
+/ Locale and Namespace Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_CODE_PAGE	932
+/* This option specifies the OEM code page to be used on the target system.
+/  Incorrect code page setting can cause a file open failure.
+/
+/   437 - U.S.
+/   720 - Arabic
+/   737 - Greek
+/   771 - KBL
+/   775 - Baltic
+/   850 - Latin 1
+/   852 - Latin 2
+/   855 - Cyrillic
+/   857 - Turkish
+/   860 - Portuguese
+/   861 - Icelandic
+/   862 - Hebrew
+/   863 - Canadian French
+/   864 - Arabic
+/   865 - Nordic
+/   866 - Russian
+/   869 - Greek 2
+/   932 - Japanese (DBCS)
+/   936 - Simplified Chinese (DBCS)
+/   949 - Korean (DBCS)
+/   950 - Traditional Chinese (DBCS)
+/     0 - Include all code pages above and configured by f_setcp()
+*/
+
+
+#define FF_USE_LFN		3
+#define FF_MAX_LFN		(FS_OBJ_NAME_LEN+1+1)
+/* The FF_USE_LFN switches the support for LFN (long file name).
+/
+/   0: Disable LFN. FF_MAX_LFN has no effect.
+/   1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
+/   2: Enable LFN with dynamic working buffer on the STACK.
+/   3: Enable LFN with dynamic working buffer on the HEAP.
+/
+/  To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
+/  requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
+/  additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
+/  The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
+/  be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
+/  specification.
+/  When use stack for the working buffer, take care on stack overflow. When use heap
+/  memory for the working buffer, memory management functions, ff_memalloc() and
+/  ff_memfree() in ffsystem.c, need to be added to the project. */
+
+
+#define FF_LFN_UNICODE	0
+/* This option switches the character encoding on the API when LFN is enabled.
+/
+/   0: ANSI/OEM in current CP (TCHAR = char)
+/   1: Unicode in UTF-16 (TCHAR = WCHAR)
+/   2: Unicode in UTF-8 (TCHAR = char)
+/   3: Unicode in UTF-32 (TCHAR = DWORD)
+/
+/  Also behavior of string I/O functions will be affected by this option.
+/  When LFN is not enabled, this option has no effect. */
+
+
+#define FF_LFN_BUF		255
+#define FF_SFN_BUF		12
+/* This set of options defines size of file name members in the FILINFO structure
+/  which is used to read out directory items. These values should be suffcient for
+/  the file names to read. The maximum possible length of the read file name depends
+/  on character encoding. When LFN is not enabled, these options have no effect. */
+
+
+#define FF_STRF_ENCODE	3
+/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
+/  f_putc(), f_puts and f_printf() convert the character encoding in it.
+/  This option selects assumption of character encoding ON THE FILE to be
+/  read/written via those functions.
+/
+/   0: ANSI/OEM in current CP
+/   1: Unicode in UTF-16LE
+/   2: Unicode in UTF-16BE
+/   3: Unicode in UTF-8
+*/
+
+
+#define FF_FS_RPATH		2
+/* This option configures support for relative path.
+/
+/   0: Disable relative path and remove related functions.
+/   1: Enable relative path. f_chdir() and f_chdrive() are available.
+/   2: f_getcwd() function is available in addition to 1.
+*/
+
+
+/*---------------------------------------------------------------------------/
+/ Drive/Volume Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_VOLUMES		4
+/* Number of volumes (logical drives) to be used. (1-10) */
+
+
+#define FF_STR_VOLUME_ID	1
+#define FF_VOLUME_STRS		"SD0","SD1","SD2","SD3"
+/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
+/  When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
+/  number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
+/  logical drives. Number of items must not be less than FF_VOLUMES. Valid
+/  characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
+/  compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
+/  not defined, a user defined volume string table needs to be defined as:
+/
+/  const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
+*/
+
+
+#define FF_MULTI_PARTITION	1
+/* This option switches support for multiple volumes on the physical drive.
+/  By default (0), each logical drive number is bound to the same physical drive
+/  number and only an FAT volume found on the physical drive will be mounted.
+/  When this function is enabled (1), each logical drive number can be bound to
+/  arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/  funciton will be available. */
+
+
+#define FF_MIN_SS		512
+#define FF_MAX_SS		512
+/* This set of options configures the range of sector size to be supported. (512,
+/  1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
+/  harddisk. But a larger value may be required for on-board flash memory and some
+/  type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
+/  for variable sector size mode and disk_ioctl() function needs to implement
+/  GET_SECTOR_SIZE command. */
+
+
+#define FF_USE_TRIM		0
+/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
+/  To enable Trim function, also CTRL_TRIM command should be implemented to the
+/  disk_ioctl() function. */
+
+
+#define FF_FS_NOFSINFO	0
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/  option, and f_getfree() function at first time after volume mount will force
+/  a full FAT scan. Bit 1 controls the use of last allocated cluster number.
+/
+/  bit0=0: Use free cluster count in the FSINFO if available.
+/  bit0=1: Do not trust free cluster count in the FSINFO.
+/  bit1=0: Use last allocated cluster number in the FSINFO if available.
+/  bit1=1: Do not trust last allocated cluster number in the FSINFO.
+*/
+
+
+
+/*---------------------------------------------------------------------------/
+/ System Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_TINY		0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/  At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
+/  Instead of private sector buffer eliminated from the file object, common sector
+/  buffer in the filesystem object (FATFS) is used for the file data transfer. */
+
+
+#define FF_FS_EXFAT		0
+/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
+/  To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
+/  Note that enabling exFAT discards ANSI C (C89) compatibility. */
+
+
+#define FF_FS_NORTC		0
+#define FF_NORTC_MON	1
+#define FF_NORTC_MDAY	1
+#define FF_NORTC_YEAR	2018
+/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
+/  any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
+/  the timestamp function. Every object modified by FatFs will have a fixed timestamp
+/  defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
+/  To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
+/  added to the project to read current time form real-time clock. FF_NORTC_MON,
+/  FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
+/  These options have no effect at read-only configuration (FF_FS_READONLY = 1). */
+
+
+#define FF_FS_LOCK		0
+/* The option FF_FS_LOCK switches file lock function to control duplicated file open
+/  and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
+/  is 1.
+/
+/  0:  Disable file lock function. To avoid volume corruption, application program
+/      should avoid illegal open, remove and rename to the open objects.
+/  >0: Enable file lock function. The value defines how many files/sub-directories
+/      can be opened simultaneously under file lock control. Note that the file
+/      lock control is independent of re-entrancy. */
+
+
+/* #include <somertos.h>	// O/S definitions */
+#define FF_FS_REENTRANT	0
+#define FF_FS_TIMEOUT	1000
+#define FF_SYNC_t		HANDLE
+/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/  module itself. Note that regardless of this option, file access to different
+/  volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/  and f_fdisk() function, are always not re-entrant. Only file/directory access
+/  to the same volume is under control of this function.
+/
+/   0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
+/   1: Enable re-entrancy. Also user provided synchronization handlers,
+/      ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
+/      function, must be added to the project. Samples are available in
+/      option/syscall.c.
+/
+/  The FF_FS_TIMEOUT defines timeout period in unit of time tick.
+/  The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
+/  SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
+/  included somewhere in the scope of ff.h. */
+
+
+
+/*--- End of configuration options ---*/

+ 170 - 170
app/fatfs/ffsystem.c

@@ -1,170 +1,170 @@
-/*------------------------------------------------------------------------*/
-/* Sample Code of OS Dependent Functions for FatFs                        */
-/* (C)ChaN, 2018                                                          */
-/*------------------------------------------------------------------------*/
-
-#include <stdlib.h>
-#include "ff.h"
-
-
-#if FF_USE_LFN == 3	/* Dynamic memory allocation */
-
-/*------------------------------------------------------------------------*/
-/* Allocate a memory block                                                */
-/*------------------------------------------------------------------------*/
-
-void* ff_memalloc (	/* Returns pointer to the allocated memory block (null if not enough core) */
-	UINT msize		/* Number of bytes to allocate */
-)
-{
-	return malloc(msize);	/* Allocate a new memory block with POSIX API */
-}
-
-
-/*------------------------------------------------------------------------*/
-/* Free a memory block                                                    */
-/*------------------------------------------------------------------------*/
-
-void ff_memfree (
-	void* mblock	/* Pointer to the memory block to free (nothing to do if null) */
-)
-{
-	free(mblock);	/* Free the memory block with POSIX API */
-}
-
-#endif
-
-
-
-#if FF_FS_REENTRANT	/* Mutal exclusion */
-
-/*------------------------------------------------------------------------*/
-/* Create a Synchronization Object                                        */
-/*------------------------------------------------------------------------*/
-/* This function is called in f_mount() function to create a new
-/  synchronization object for the volume, such as semaphore and mutex.
-/  When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
-*/
-
-//const osMutexDef_t Mutex[FF_VOLUMES];	/* Table of CMSIS-RTOS mutex */
-
-
-int ff_cre_syncobj (	/* 1:Function succeeded, 0:Could not create the sync object */
-	BYTE vol,			/* Corresponding volume (logical drive number) */
-	FF_SYNC_t* sobj		/* Pointer to return the created sync object */
-)
-{
-	/* Win32 */
-	*sobj = CreateMutex(NULL, FALSE, NULL);
-	return (int)(*sobj != INVALID_HANDLE_VALUE);
-
-	/* uITRON */
-//	T_CSEM csem = {TA_TPRI,1,1};
-//	*sobj = acre_sem(&csem);
-//	return (int)(*sobj > 0);
-
-	/* uC/OS-II */
-//	OS_ERR err;
-//	*sobj = OSMutexCreate(0, &err);
-//	return (int)(err == OS_NO_ERR);
-
-	/* FreeRTOS */
-//	*sobj = xSemaphoreCreateMutex();
-//	return (int)(*sobj != NULL);
-
-	/* CMSIS-RTOS */
-//	*sobj = osMutexCreate(&Mutex[vol]);
-//	return (int)(*sobj != NULL);
-}
-
-
-/*------------------------------------------------------------------------*/
-/* Delete a Synchronization Object                                        */
-/*------------------------------------------------------------------------*/
-/* This function is called in f_mount() function to delete a synchronization
-/  object that created with ff_cre_syncobj() function. When a 0 is returned,
-/  the f_mount() function fails with FR_INT_ERR.
-*/
-
-int ff_del_syncobj (	/* 1:Function succeeded, 0:Could not delete due to an error */
-	FF_SYNC_t sobj		/* Sync object tied to the logical drive to be deleted */
-)
-{
-	/* Win32 */
-	return (int)CloseHandle(sobj);
-
-	/* uITRON */
-//	return (int)(del_sem(sobj) == E_OK);
-
-	/* uC/OS-II */
-//	OS_ERR err;
-//	OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
-//	return (int)(err == OS_NO_ERR);
-
-	/* FreeRTOS */
-//  vSemaphoreDelete(sobj);
-//	return 1;
-
-	/* CMSIS-RTOS */
-//	return (int)(osMutexDelete(sobj) == osOK);
-}
-
-
-/*------------------------------------------------------------------------*/
-/* Request Grant to Access the Volume                                     */
-/*------------------------------------------------------------------------*/
-/* This function is called on entering file functions to lock the volume.
-/  When a 0 is returned, the file function fails with FR_TIMEOUT.
-*/
-
-int ff_req_grant (	/* 1:Got a grant to access the volume, 0:Could not get a grant */
-	FF_SYNC_t sobj	/* Sync object to wait */
-)
-{
-	/* Win32 */
-	return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
-
-	/* uITRON */
-//	return (int)(wai_sem(sobj) == E_OK);
-
-	/* uC/OS-II */
-//	OS_ERR err;
-//	OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
-//	return (int)(err == OS_NO_ERR);
-
-	/* FreeRTOS */
-//	return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
-
-	/* CMSIS-RTOS */
-//	return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
-}
-
-
-/*------------------------------------------------------------------------*/
-/* Release Grant to Access the Volume                                     */
-/*------------------------------------------------------------------------*/
-/* This function is called on leaving file functions to unlock the volume.
-*/
-
-void ff_rel_grant (
-	FF_SYNC_t sobj	/* Sync object to be signaled */
-)
-{
-	/* Win32 */
-	ReleaseMutex(sobj);
-
-	/* uITRON */
-//	sig_sem(sobj);
-
-	/* uC/OS-II */
-//	OSMutexPost(sobj);
-
-	/* FreeRTOS */
-//	xSemaphoreGive(sobj);
-
-	/* CMSIS-RTOS */
-//	osMutexRelease(sobj);
-}
-
-#endif
-
+/*------------------------------------------------------------------------*/
+/* Sample Code of OS Dependent Functions for FatFs                        */
+/* (C)ChaN, 2018                                                          */
+/*------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include "ff.h"
+
+
+#if FF_USE_LFN == 3	/* Dynamic memory allocation */
+
+/*------------------------------------------------------------------------*/
+/* Allocate a memory block                                                */
+/*------------------------------------------------------------------------*/
+
+void* ff_memalloc (	/* Returns pointer to the allocated memory block (null if not enough core) */
+	UINT msize		/* Number of bytes to allocate */
+)
+{
+	return malloc(msize);	/* Allocate a new memory block with POSIX API */
+}
+
+
+/*------------------------------------------------------------------------*/
+/* Free a memory block                                                    */
+/*------------------------------------------------------------------------*/
+
+void ff_memfree (
+	void* mblock	/* Pointer to the memory block to free (nothing to do if null) */
+)
+{
+	free(mblock);	/* Free the memory block with POSIX API */
+}
+
+#endif
+
+
+
+#if FF_FS_REENTRANT	/* Mutal exclusion */
+
+/*------------------------------------------------------------------------*/
+/* Create a Synchronization Object                                        */
+/*------------------------------------------------------------------------*/
+/* This function is called in f_mount() function to create a new
+/  synchronization object for the volume, such as semaphore and mutex.
+/  When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
+*/
+
+//const osMutexDef_t Mutex[FF_VOLUMES];	/* Table of CMSIS-RTOS mutex */
+
+
+int ff_cre_syncobj (	/* 1:Function succeeded, 0:Could not create the sync object */
+	BYTE vol,			/* Corresponding volume (logical drive number) */
+	FF_SYNC_t* sobj		/* Pointer to return the created sync object */
+)
+{
+	/* Win32 */
+	*sobj = CreateMutex(NULL, FALSE, NULL);
+	return (int)(*sobj != INVALID_HANDLE_VALUE);
+
+	/* uITRON */
+//	T_CSEM csem = {TA_TPRI,1,1};
+//	*sobj = acre_sem(&csem);
+//	return (int)(*sobj > 0);
+
+	/* uC/OS-II */
+//	OS_ERR err;
+//	*sobj = OSMutexCreate(0, &err);
+//	return (int)(err == OS_NO_ERR);
+
+	/* FreeRTOS */
+//	*sobj = xSemaphoreCreateMutex();
+//	return (int)(*sobj != NULL);
+
+	/* CMSIS-RTOS */
+//	*sobj = osMutexCreate(&Mutex[vol]);
+//	return (int)(*sobj != NULL);
+}
+
+
+/*------------------------------------------------------------------------*/
+/* Delete a Synchronization Object                                        */
+/*------------------------------------------------------------------------*/
+/* This function is called in f_mount() function to delete a synchronization
+/  object that created with ff_cre_syncobj() function. When a 0 is returned,
+/  the f_mount() function fails with FR_INT_ERR.
+*/
+
+int ff_del_syncobj (	/* 1:Function succeeded, 0:Could not delete due to an error */
+	FF_SYNC_t sobj		/* Sync object tied to the logical drive to be deleted */
+)
+{
+	/* Win32 */
+	return (int)CloseHandle(sobj);
+
+	/* uITRON */
+//	return (int)(del_sem(sobj) == E_OK);
+
+	/* uC/OS-II */
+//	OS_ERR err;
+//	OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
+//	return (int)(err == OS_NO_ERR);
+
+	/* FreeRTOS */
+//  vSemaphoreDelete(sobj);
+//	return 1;
+
+	/* CMSIS-RTOS */
+//	return (int)(osMutexDelete(sobj) == osOK);
+}
+
+
+/*------------------------------------------------------------------------*/
+/* Request Grant to Access the Volume                                     */
+/*------------------------------------------------------------------------*/
+/* This function is called on entering file functions to lock the volume.
+/  When a 0 is returned, the file function fails with FR_TIMEOUT.
+*/
+
+int ff_req_grant (	/* 1:Got a grant to access the volume, 0:Could not get a grant */
+	FF_SYNC_t sobj	/* Sync object to wait */
+)
+{
+	/* Win32 */
+	return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
+
+	/* uITRON */
+//	return (int)(wai_sem(sobj) == E_OK);
+
+	/* uC/OS-II */
+//	OS_ERR err;
+//	OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
+//	return (int)(err == OS_NO_ERR);
+
+	/* FreeRTOS */
+//	return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
+
+	/* CMSIS-RTOS */
+//	return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
+}
+
+
+/*------------------------------------------------------------------------*/
+/* Release Grant to Access the Volume                                     */
+/*------------------------------------------------------------------------*/
+/* This function is called on leaving file functions to unlock the volume.
+*/
+
+void ff_rel_grant (
+	FF_SYNC_t sobj	/* Sync object to be signaled */
+)
+{
+	/* Win32 */
+	ReleaseMutex(sobj);
+
+	/* uITRON */
+//	sig_sem(sobj);
+
+	/* uC/OS-II */
+//	OSMutexPost(sobj);
+
+	/* FreeRTOS */
+//	xSemaphoreGive(sobj);
+
+	/* CMSIS-RTOS */
+//	osMutexRelease(sobj);
+}
+
+#endif
+

File diff suppressed because it is too large
+ 0 - 15487
app/fatfs/ffunicode.c


+ 1 - 1
app/http/Makefile

@@ -24,7 +24,7 @@ STD_CFLAGS=-std=gnu11 -Wimplicit
 #   makefile at its root level - these are then overridden
 #   for a subtree within the makefile rooted therein
 #
-#DEFINES += 
+#DEFINES +=
 
 #############################################################
 # Recursion Magic - Don't touch this!!

+ 11 - 11
app/http/httpclient.c

@@ -171,7 +171,7 @@ static void ICACHE_FLASH_ATTR http_send_callback( void * arg )
 	{
 		HTTPCLIENT_DEBUG( "All sent" );
 	}
-	else  
+	else
 	{
 		/* The headers were sent, now send the contents. */
 		HTTPCLIENT_DEBUG( "Sending request body" );
@@ -324,7 +324,7 @@ static void ICACHE_FLASH_ATTR http_disconnect_callback( void * arg )
 			{
 				HTTPCLIENT_ERR( "Invalid version in %s", req->buffer );
 			}
-			else  
+			else
 			{
 				http_status	= atoi( req->buffer + strlen( version_1_0 ) );
 
@@ -470,7 +470,7 @@ static void ICACHE_FLASH_ATTR http_timeout_callback( void *arg )
 	else
 #endif
 		result = espconn_disconnect( conn );
-		
+
 	if (result == ESPCONN_OK || result == ESPCONN_INPROGRESS)
 		return;
 	else
@@ -478,7 +478,7 @@ static void ICACHE_FLASH_ATTR http_timeout_callback( void *arg )
 		/* not connected; execute the callback ourselves. */
 		HTTPCLIENT_DEBUG( "manually Calling disconnect callback due to error %d", result );
 		http_disconnect_callback( arg );
-	}		
+	}
 }
 
 
@@ -502,7 +502,7 @@ static void ICACHE_FLASH_ATTR http_dns_callback( const char * hostname, ip_addr_
 		}
 		http_free_req( req );
 	}
-	else  
+	else
 	{
 		HTTPCLIENT_DEBUG( "DNS found %s " IPSTR, hostname, IP2STR( addr ) );
 
@@ -531,8 +531,8 @@ static void ICACHE_FLASH_ATTR http_dns_callback( const char * hostname, ip_addr_
 		if ( req->secure )
 		{
 			espconn_secure_connect( conn );
-		} 
-		else 
+		}
+		else
 #endif
 		{
 			espconn_connect( conn );
@@ -575,7 +575,7 @@ void ICACHE_FLASH_ATTR http_raw_request( const char * hostname, int port, bool s
 		/* Already in the local names table (or hostname was an IP address), execute the callback ourselves. */
 		http_dns_callback( hostname, &addr, req );
 	}
-	else  
+	else
 	{
 		if ( error == ESPCONN_ARG )
 		{
@@ -614,8 +614,8 @@ void ICACHE_FLASH_ATTR http_request( const char * url, const char * method, cons
 		port	= 443;
 		secure	= true;
 		url	+= strlen( "https://" );        /* Get rid of the protocol. */
-	} 
-	else 
+	}
+	else
 	{
 		HTTPCLIENT_ERR( "URL is not HTTP or HTTPS %s", url );
 		return;
@@ -643,7 +643,7 @@ void ICACHE_FLASH_ATTR http_request( const char * url, const char * method, cons
 		os_memcpy( hostname, url, path - url );
 		hostname[path - url] = '\0';
 	}
-	else  
+	else
 	{
 		port = atoi( colon + 1 );
 		if ( port == 0 )

+ 24 - 24
app/include/arch/cc.h

@@ -1,33 +1,33 @@
 /*
  * Copyright (c) 2001, Swedish Institute of Computer Science.
- * All rights reserved. 
+ * All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright 
- *    notice, this list of conditions and the following disclaimer in the 
- *    documentation and/or other materials provided with the distribution. 
- * 3. Neither the name of the Institute nor the names of its contributors 
- *    may be used to endorse or promote products derived from this software 
- *    without specific prior written permission. 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE. 
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 24 - 24
app/include/arch/perf.h

@@ -1,33 +1,33 @@
 /*
  * Copyright (c) 2001, Swedish Institute of Computer Science.
- * All rights reserved. 
+ * All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright 
- *    notice, this list of conditions and the following disclaimer in the 
- *    documentation and/or other materials provided with the distribution. 
- * 3. Neither the name of the Institute nor the names of its contributors 
- *    may be used to endorse or promote products derived from this software 
- *    without specific prior written permission. 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE. 
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 1 - 1
app/include/driver/spi.h

@@ -47,7 +47,7 @@ void spi_byte_read_espslave(uint8 spi_no,uint8 *data);
 void spi_slave_init(uint8 spi_no);
   //esp8266 slave isr handle funtion,tiggered when any transmission is finished.
   //the function is registered in spi_slave_init.
-void spi_slave_isr_handler(void *para); 
+void spi_slave_isr_handler(void *para);
 
 
 //hspi test function, used to test esp8266 spi slave

+ 1 - 1
app/include/driver/uart.h

@@ -106,7 +106,7 @@ typedef struct {
     UartBautRate      baut_rate;
     UartBitsNum4Char  data_bits;
     UartExistParity   exist_parity;
-    UartParityMode    parity;   
+    UartParityMode    parity;
     UartStopBitsNum   stop_bits;
 } UartConfig;
 

+ 14 - 14
app/include/lwip/api.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 14 - 14
app/include/lwip/api_msg.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 117 - 117
app/include/lwip/app/dhcpserver.h

@@ -1,117 +1,117 @@
-#ifndef __DHCPS_H__
-#define __DHCPS_H__
-
-#include "lwipopts.h"
-
-#define USE_DNS
-
-typedef struct dhcps_state{
-        sint16_t state;
-} dhcps_state;
-
-// ����dhcpclient�Զ����һ��DHCP msg�ṹ��
-typedef struct dhcps_msg {
-        uint8_t op, htype, hlen, hops;
-        uint8_t xid[4];
-        uint16_t secs, flags;
-        uint8_t ciaddr[4];
-        uint8_t yiaddr[4];
-        uint8_t siaddr[4];
-        uint8_t giaddr[4];
-        uint8_t chaddr[16];
-        uint8_t sname[64];
-        uint8_t file[128];
-        uint8_t options[312];
-}dhcps_msg;
-
-#ifndef LWIP_OPEN_SRC
-struct dhcps_lease {
-	bool enable;
-	struct ip_addr start_ip;
-	struct ip_addr end_ip;
-};
-
-enum dhcps_offer_option{
-	OFFER_START = 0x00,
-	OFFER_ROUTER = 0x01,
-	OFFER_END
-};
-#endif
-
-typedef enum {
-    DHCPS_TYPE_DYNAMIC,
-    DHCPS_TYPE_STATIC
-} dhcps_type_t;
-
-typedef enum {
-    DHCPS_STATE_ONLINE,
-    DHCPS_STATE_OFFLINE
-} dhcps_state_t;
-
-struct dhcps_pool{
-	struct ip_addr ip;
-	uint8 mac[6];
-	uint32 lease_timer;
-    dhcps_type_t type;
-    dhcps_state_t state;
-
-};
-
-typedef struct _list_node{
-	void *pnode;
-	struct _list_node *pnext;
-}list_node;
-
-extern uint32 dhcps_lease_time;
-#define DHCPS_LEASE_TIMER  dhcps_lease_time  //0x05A0
-#define DHCPS_MAX_LEASE 0x64
-#define BOOTP_BROADCAST 0x8000
-
-#define DHCP_REQUEST        1
-#define DHCP_REPLY          2
-#define DHCP_HTYPE_ETHERNET 1
-#define DHCP_HLEN_ETHERNET  6
-#define DHCP_MSG_LEN      236
-
-#define DHCPS_SERVER_PORT  67
-#define DHCPS_CLIENT_PORT  68
-
-#define DHCPDISCOVER  1
-#define DHCPOFFER     2
-#define DHCPREQUEST   3
-#define DHCPDECLINE   4
-#define DHCPACK       5
-#define DHCPNAK       6
-#define DHCPRELEASE   7
-
-#define DHCP_OPTION_SUBNET_MASK   1
-#define DHCP_OPTION_ROUTER        3
-#define DHCP_OPTION_DNS_SERVER    6
-#define DHCP_OPTION_REQ_IPADDR   50
-#define DHCP_OPTION_LEASE_TIME   51
-#define DHCP_OPTION_MSG_TYPE     53
-#define DHCP_OPTION_SERVER_ID    54
-#define DHCP_OPTION_INTERFACE_MTU 26
-#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31
-#define DHCP_OPTION_BROADCAST_ADDRESS 28
-#define DHCP_OPTION_REQ_LIST     55
-#define DHCP_OPTION_END         255
-
-//#define USE_CLASS_B_NET 1
-#define DHCPS_DEBUG          0
-#define MAX_STATION_NUM      8
-
-#define DHCPS_STATE_OFFER 1
-#define DHCPS_STATE_DECLINE 2
-#define DHCPS_STATE_ACK 3
-#define DHCPS_STATE_NAK 4
-#define DHCPS_STATE_IDLE 5
-#define DHCPS_STATE_RELEASE 6
-
-#define   dhcps_router_enabled(offer)	((offer & OFFER_ROUTER) != 0)
-
-void dhcps_start(struct ip_info *info);
-void dhcps_stop(void);
-
-#endif
-
+#ifndef __DHCPS_H__
+#define __DHCPS_H__
+
+#include "lwipopts.h"
+
+#define USE_DNS
+
+typedef struct dhcps_state{
+        sint16_t state;
+} dhcps_state;
+
+// ����dhcpclient�Զ����һ��DHCP msg�ṹ��
+typedef struct dhcps_msg {
+        uint8_t op, htype, hlen, hops;
+        uint8_t xid[4];
+        uint16_t secs, flags;
+        uint8_t ciaddr[4];
+        uint8_t yiaddr[4];
+        uint8_t siaddr[4];
+        uint8_t giaddr[4];
+        uint8_t chaddr[16];
+        uint8_t sname[64];
+        uint8_t file[128];
+        uint8_t options[312];
+}dhcps_msg;
+
+#ifndef LWIP_OPEN_SRC
+struct dhcps_lease {
+	bool enable;
+	struct ip_addr start_ip;
+	struct ip_addr end_ip;
+};
+
+enum dhcps_offer_option{
+	OFFER_START = 0x00,
+	OFFER_ROUTER = 0x01,
+	OFFER_END
+};
+#endif
+
+typedef enum {
+    DHCPS_TYPE_DYNAMIC,
+    DHCPS_TYPE_STATIC
+} dhcps_type_t;
+
+typedef enum {
+    DHCPS_STATE_ONLINE,
+    DHCPS_STATE_OFFLINE
+} dhcps_state_t;
+
+struct dhcps_pool{
+	struct ip_addr ip;
+	uint8 mac[6];
+	uint32 lease_timer;
+    dhcps_type_t type;
+    dhcps_state_t state;
+
+};
+
+typedef struct _list_node{
+	void *pnode;
+	struct _list_node *pnext;
+}list_node;
+
+extern uint32 dhcps_lease_time;
+#define DHCPS_LEASE_TIMER  dhcps_lease_time  //0x05A0
+#define DHCPS_MAX_LEASE 0x64
+#define BOOTP_BROADCAST 0x8000
+
+#define DHCP_REQUEST        1
+#define DHCP_REPLY          2
+#define DHCP_HTYPE_ETHERNET 1
+#define DHCP_HLEN_ETHERNET  6
+#define DHCP_MSG_LEN      236
+
+#define DHCPS_SERVER_PORT  67
+#define DHCPS_CLIENT_PORT  68
+
+#define DHCPDISCOVER  1
+#define DHCPOFFER     2
+#define DHCPREQUEST   3
+#define DHCPDECLINE   4
+#define DHCPACK       5
+#define DHCPNAK       6
+#define DHCPRELEASE   7
+
+#define DHCP_OPTION_SUBNET_MASK   1
+#define DHCP_OPTION_ROUTER        3
+#define DHCP_OPTION_DNS_SERVER    6
+#define DHCP_OPTION_REQ_IPADDR   50
+#define DHCP_OPTION_LEASE_TIME   51
+#define DHCP_OPTION_MSG_TYPE     53
+#define DHCP_OPTION_SERVER_ID    54
+#define DHCP_OPTION_INTERFACE_MTU 26
+#define DHCP_OPTION_PERFORM_ROUTER_DISCOVERY 31
+#define DHCP_OPTION_BROADCAST_ADDRESS 28
+#define DHCP_OPTION_REQ_LIST     55
+#define DHCP_OPTION_END         255
+
+//#define USE_CLASS_B_NET 1
+#define DHCPS_DEBUG          0
+#define MAX_STATION_NUM      8
+
+#define DHCPS_STATE_OFFER 1
+#define DHCPS_STATE_DECLINE 2
+#define DHCPS_STATE_ACK 3
+#define DHCPS_STATE_NAK 4
+#define DHCPS_STATE_IDLE 5
+#define DHCPS_STATE_RELEASE 6
+
+#define   dhcps_router_enabled(offer)	((offer & OFFER_ROUTER) != 0)
+
+void dhcps_start(struct ip_info *info);
+void dhcps_stop(void);
+
+#endif
+

+ 12 - 12
app/include/lwip/app/espconn.h

@@ -32,7 +32,7 @@
 
 #if 0
 #define espconn_printf(fmt, args...) os_printf(fmt,## args)
-#else 
+#else
 #define espconn_printf(fmt, args...)
 #endif
 
@@ -468,7 +468,7 @@ extern sint8 espconn_regist_time(struct espconn *espconn, uint32 interval, uint8
  * Description  : Used to specify the function that should be called when data
  * 				  has been successfully delivered to the remote host.
  * Parameters   : struct espconn *espconn -- espconn to set the sent callback
- * 				  espconn_sent_callback sent_cb -- sent callback function to 
+ * 				  espconn_sent_callback sent_cb -- sent callback function to
  * 				  call for this espconn when data is successfully sent
  * Returns      : none
 *******************************************************************************/
@@ -510,10 +510,10 @@ extern sint8 espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length);
 
 /******************************************************************************
  * FunctionName : espconn_regist_connectcb
- * Description  : used to specify the function that should be called when 
- * 				  connects to host. 
- * Parameters   : espconn -- espconn to set the connect callback 
- * 				  connect_cb -- connected callback function to call when connected 
+ * Description  : used to specify the function that should be called when
+ * 				  connects to host.
+ * Parameters   : espconn -- espconn to set the connect callback
+ * 				  connect_cb -- connected callback function to call when connected
  * Returns      : none
 *******************************************************************************/
 
@@ -521,9 +521,9 @@ extern sint8 espconn_regist_connectcb(struct espconn *espconn, espconn_connect_c
 
 /******************************************************************************
  * FunctionName : espconn_regist_recvcb
- * Description  : used to specify the function that should be called when recv 
+ * Description  : used to specify the function that should be called when recv
  * 				  data from host.
- * Parameters   : espconn -- espconn to set the recv callback 
+ * Parameters   : espconn -- espconn to set the recv callback
  * 				  recv_cb -- recv callback function to call when recv data
  * Returns      : none
 *******************************************************************************/
@@ -532,10 +532,10 @@ extern sint8 espconn_regist_recvcb(struct espconn *espconn, espconn_recv_callbac
 
 /******************************************************************************
  * FunctionName : espconn_regist_reconcb
- * Description  : used to specify the function that should be called when connection 
+ * Description  : used to specify the function that should be called when connection
  * 				  because of err disconnect.
- * Parameters   : espconn -- espconn to set the err callback 
- * 				  recon_cb -- err callback function to call when err 
+ * Parameters   : espconn -- espconn to set the err callback
+ * 				  recon_cb -- err callback function to call when err
  * Returns      : none
 *******************************************************************************/
 
@@ -596,7 +596,7 @@ extern sint8 espconn_get_keepalive(struct espconn *espconn, uint8 level, void *o
  * Description  : Resolve a hostname (string) into an IP address.
  * Parameters   : pespconn -- espconn to resolve a hostname
  *                hostname -- the hostname that is to be queried
- *                addr -- pointer to a ip_addr_t where to store the address if 
+ *                addr -- pointer to a ip_addr_t where to store the address if
  *                        it is already cached in the dns_table (only valid if
  *                        ESPCONN_OK is returned!)
  *                found -- a callback function to be called on success, failure

+ 58 - 58
app/include/lwip/app/espconn_tcp.h

@@ -1,58 +1,58 @@
-#ifndef __ESPCONN_TCP_H__
-#define __ESPCONN_TCP_H__
-
-#ifndef ESPCONN_TCP_DEBUG
-#define ESPCONN_TCP_DEBUG LWIP_DBG_OFF
-#endif
-#include "lwip/app/espconn.h"
-
-#ifndef ESPCONN_TCP_TIMER
-#define ESPCONN_TCP_TIMER 40
-#endif
-
-#define  espconn_keepalive_enable(pcb)   ((pcb)->so_options |= SOF_KEEPALIVE)
-#define  espconn_keepalive_disable(pcb)   ((pcb)->so_options &= ~SOF_KEEPALIVE)
-
-#define   espconn_manual_recv_disabled(espconn)  (((espconn)->pcommon.espconn_opt & ESPCONN_MANUALRECV) != 0)
-#define   espconn_manual_recv_enabled(espconn)  (((espconn)->pcommon.espconn_opt & ESPCONN_MANUALRECV) == 0)
-
-/******************************************************************************
- * FunctionName : espconn_kill_oldest_pcb
- * Description  : A oldest incoming connection has been killed.
- * Parameters   : none
- * Returns      : none
-*******************************************************************************/
-
-extern void espconn_kill_oldest_pcb(void);
-
-/******************************************************************************
- * FunctionName : espconn_tcp_disconnect
- * Description  : A new incoming connection has been disconnected.
- * Parameters   : espconn -- the espconn used to disconnect with host
- * Returns      : none
-*******************************************************************************/
-
-extern void espconn_tcp_disconnect(espconn_msg *pdiscon,u8 type);
-
-/******************************************************************************
- * FunctionName : espconn_tcp_client
- * Description  : Initialize the client: set up a connect PCB and bind it to 
- *                the defined port
- * Parameters   : espconn -- the espconn used to build client
- * Returns      : none
-*******************************************************************************/
-
-extern sint8 espconn_tcp_client(struct espconn* espconn);
-
-/******************************************************************************
- * FunctionName : espconn_tcp_server
- * Description  : Initialize the server: set up a listening PCB and bind it to 
- *                the defined port
- * Parameters   : espconn -- the espconn used to build server
- * Returns      : none
-*******************************************************************************/
-
-extern sint8 espconn_tcp_server(struct espconn *espconn);
-
-#endif /* __CLIENT_TCP_H__ */
-
+#ifndef __ESPCONN_TCP_H__
+#define __ESPCONN_TCP_H__
+
+#ifndef ESPCONN_TCP_DEBUG
+#define ESPCONN_TCP_DEBUG LWIP_DBG_OFF
+#endif
+#include "lwip/app/espconn.h"
+
+#ifndef ESPCONN_TCP_TIMER
+#define ESPCONN_TCP_TIMER 40
+#endif
+
+#define  espconn_keepalive_enable(pcb)   ((pcb)->so_options |= SOF_KEEPALIVE)
+#define  espconn_keepalive_disable(pcb)   ((pcb)->so_options &= ~SOF_KEEPALIVE)
+
+#define   espconn_manual_recv_disabled(espconn)  (((espconn)->pcommon.espconn_opt & ESPCONN_MANUALRECV) != 0)
+#define   espconn_manual_recv_enabled(espconn)  (((espconn)->pcommon.espconn_opt & ESPCONN_MANUALRECV) == 0)
+
+/******************************************************************************
+ * FunctionName : espconn_kill_oldest_pcb
+ * Description  : A oldest incoming connection has been killed.
+ * Parameters   : none
+ * Returns      : none
+*******************************************************************************/
+
+extern void espconn_kill_oldest_pcb(void);
+
+/******************************************************************************
+ * FunctionName : espconn_tcp_disconnect
+ * Description  : A new incoming connection has been disconnected.
+ * Parameters   : espconn -- the espconn used to disconnect with host
+ * Returns      : none
+*******************************************************************************/
+
+extern void espconn_tcp_disconnect(espconn_msg *pdiscon,u8 type);
+
+/******************************************************************************
+ * FunctionName : espconn_tcp_client
+ * Description  : Initialize the client: set up a connect PCB and bind it to
+ *                the defined port
+ * Parameters   : espconn -- the espconn used to build client
+ * Returns      : none
+*******************************************************************************/
+
+extern sint8 espconn_tcp_client(struct espconn* espconn);
+
+/******************************************************************************
+ * FunctionName : espconn_tcp_server
+ * Description  : Initialize the server: set up a listening PCB and bind it to
+ *                the defined port
+ * Parameters   : espconn -- the espconn used to build server
+ * Returns      : none
+*******************************************************************************/
+
+extern sint8 espconn_tcp_server(struct espconn *espconn);
+
+#endif /* __CLIENT_TCP_H__ */
+

+ 64 - 64
app/include/lwip/app/espconn_udp.h

@@ -1,64 +1,64 @@
-#ifndef __ESPCONN_UDP_H__
-#define __ESPCONN_UDP_H__
-
-#ifndef ESPCONN_UDP_DEBUG
-#define ESPCONN_UDP_DEBUG LWIP_DBG_OFF
-#endif
-
-#include "lwip/app/espconn.h"
-
-/******************************************************************************
- * FunctionName : espconn_udp_client
- * Description  : Initialize the client: set up a PCB and bind it to the port
- * Parameters   : pespconn -- the espconn used to build client
- * Returns      : none
-*******************************************************************************/
-
-extern sint8 espconn_udp_client(struct espconn *pespconn);
-
-/******************************************************************************
- * FunctionName : espconn_udp_disconnect
- * Description  : A new incoming connection has been disconnected.
- * Parameters   : espconn -- the espconn used to disconnect with host
- * Returns      : none
-*******************************************************************************/
-
-extern void espconn_udp_disconnect(espconn_msg *pdiscon);
-
-/******************************************************************************
- * FunctionName : espconn_udp_server
- * Description  : Initialize the server: set up a PCB and bind it to the port
- * Parameters   : pespconn -- the espconn used to build server
- * Returns      : none
-*******************************************************************************/
-
-extern sint8 espconn_udp_server(struct espconn *espconn);
-
-/******************************************************************************
- * FunctionName : espconn_udp_sent
- * Description  : sent data for client or server
- * Parameters   : void *arg -- client or server to send
- *                uint8* psent -- Data to send
- *                uint16 length -- Length of data to send
- * Returns      : none
-*******************************************************************************/
-
-extern err_t espconn_udp_sent(void *arg, uint8 *psent, uint16 length);
-
-/******************************************************************************
- * FunctionName : espconn_udp_sendto
- * Description  : sent data for UDP
- * Parameters   : void *arg -- UDP to send
- * 				  uint8* psent -- Data to send
- *                uint16 length -- Length of data to send
- * Returns      : return espconn error code.
- * - ESPCONN_OK. Successful. No error occured.
- * - ESPCONN_MEM. Out of memory.
- * - ESPCONN_RTE. Could not find route to destination address.
- * - More errors could be returned by lower protocol layers.
-*******************************************************************************/
-extern err_t espconn_udp_sendto(void *arg, uint8 *psent, uint16 length);
-
-#endif /* __ESPCONN_UDP_H__ */
-
-
+#ifndef __ESPCONN_UDP_H__
+#define __ESPCONN_UDP_H__
+
+#ifndef ESPCONN_UDP_DEBUG
+#define ESPCONN_UDP_DEBUG LWIP_DBG_OFF
+#endif
+
+#include "lwip/app/espconn.h"
+
+/******************************************************************************
+ * FunctionName : espconn_udp_client
+ * Description  : Initialize the client: set up a PCB and bind it to the port
+ * Parameters   : pespconn -- the espconn used to build client
+ * Returns      : none
+*******************************************************************************/
+
+extern sint8 espconn_udp_client(struct espconn *pespconn);
+
+/******************************************************************************
+ * FunctionName : espconn_udp_disconnect
+ * Description  : A new incoming connection has been disconnected.
+ * Parameters   : espconn -- the espconn used to disconnect with host
+ * Returns      : none
+*******************************************************************************/
+
+extern void espconn_udp_disconnect(espconn_msg *pdiscon);
+
+/******************************************************************************
+ * FunctionName : espconn_udp_server
+ * Description  : Initialize the server: set up a PCB and bind it to the port
+ * Parameters   : pespconn -- the espconn used to build server
+ * Returns      : none
+*******************************************************************************/
+
+extern sint8 espconn_udp_server(struct espconn *espconn);
+
+/******************************************************************************
+ * FunctionName : espconn_udp_sent
+ * Description  : sent data for client or server
+ * Parameters   : void *arg -- client or server to send
+ *                uint8* psent -- Data to send
+ *                uint16 length -- Length of data to send
+ * Returns      : none
+*******************************************************************************/
+
+extern err_t espconn_udp_sent(void *arg, uint8 *psent, uint16 length);
+
+/******************************************************************************
+ * FunctionName : espconn_udp_sendto
+ * Description  : sent data for UDP
+ * Parameters   : void *arg -- UDP to send
+ * 				  uint8* psent -- Data to send
+ *                uint16 length -- Length of data to send
+ * Returns      : return espconn error code.
+ * - ESPCONN_OK. Successful. No error occured.
+ * - ESPCONN_MEM. Out of memory.
+ * - ESPCONN_RTE. Could not find route to destination address.
+ * - More errors could be returned by lower protocol layers.
+*******************************************************************************/
+extern err_t espconn_udp_sendto(void *arg, uint8 *psent, uint16 length);
+
+#endif /* __ESPCONN_UDP_H__ */
+
+

+ 15 - 15
app/include/lwip/arch.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -71,7 +71,7 @@ extern "C" {
 
 #ifndef LWIP_UNUSED_ARG
 #define LWIP_UNUSED_ARG(x) (void)x
-#endif /* LWIP_UNUSED_ARG */ 
+#endif /* LWIP_UNUSED_ARG */
 
 
 #ifdef LWIP_PROVIDE_ERRNO

+ 1 - 1
app/include/lwip/autoip.h

@@ -40,7 +40,7 @@
  * Please coordinate changes and requests with Dominik Spies
  * <kontakt@dspies.de>
  */
- 
+
 #ifndef __LWIP_AUTOIP_H__
 #define __LWIP_AUTOIP_H__
 

+ 16 - 16
app/include/lwip/debug.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -65,7 +65,7 @@
 #define LWIP_ASSERT(message, assertion) do { if(!(assertion)) \
   LWIP_PLATFORM_ASSERT(message); } while(0)
 #else  /* LWIP_NOASSERT */
-#define LWIP_ASSERT(message, assertion) 
+#define LWIP_ASSERT(message, assertion)
 #endif /* LWIP_NOASSERT */
 
 /** if "expression" isn't true, then print "message" and execute "handler" expression */
@@ -91,7 +91,7 @@
                              } while(0)
 
 #else  /* LWIP_DEBUG */
-#define LWIP_DEBUGF(debug, message) 
+#define LWIP_DEBUGF(debug, message)
 #endif /* LWIP_DEBUG */
 
 #endif /* __LWIP_DEBUG_H__ */

+ 16 - 16
app/include/lwip/def.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -49,14 +49,14 @@ extern "C" {
 
 /** Get the absolute difference between 2 u32_t values (correcting overflows)
  * 'a' is expected to be 'higher' (without overflow) than 'b'. */
-#define LWIP_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1))) 
+#define LWIP_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1)))
 
 /* Endianess-optimized shifting of two u8_t to create one u16_t */
 #if BYTE_ORDER == LITTLE_ENDIAN
 #define LWIP_MAKE_U16(a, b) ((a << 8) | b)
 #else
 #define LWIP_MAKE_U16(a, b) ((b << 8) | a)
-#endif 
+#endif
 
 #ifndef LWIP_PLATFORM_BYTESWAP
 #define LWIP_PLATFORM_BYTESWAP 0

+ 9 - 9
app/include/lwip/dhcp.h

@@ -16,11 +16,11 @@ extern "C" {
 #endif
 
 /** period (in seconds) of the application calling dhcp_coarse_tmr() */
-#define DHCP_COARSE_TIMER_SECS 60 
+#define DHCP_COARSE_TIMER_SECS 60
 /** period (in milliseconds) of the application calling dhcp_coarse_tmr() */
 #define DHCP_COARSE_TIMER_MSECS (DHCP_COARSE_TIMER_SECS * 1000UL)
 /** period (in milliseconds) of the application calling dhcp_fine_tmr() */
-#define DHCP_FINE_TIMER_MSECS 500 
+#define DHCP_FINE_TIMER_MSECS 500
 
 #define DHCP_CHADDR_LEN 16U
 #define DHCP_SNAME_LEN  64U
@@ -28,9 +28,9 @@ extern "C" {
 
 struct dhcp
 {
-  /** transaction identifier of last sent request */ 
+  /** transaction identifier of last sent request */
   u32_t xid;
-  /** our connection to the DHCP server */ 
+  /** our connection to the DHCP server */
   struct udp_pcb *pcb;
   /** incoming msg */
   struct dhcp_msg *msg_in;
@@ -53,7 +53,7 @@ struct dhcp
   ip_addr_t offered_ip_addr;
   ip_addr_t offered_sn_mask;
   ip_addr_t offered_gw_addr;
- 
+
   u32_t offered_t0_lease; /* lease period (in seconds) */
   u32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */
   u32_t offered_t2_rebind; /* recommended rebind time (usually 66% of lease period)  */
@@ -132,7 +132,7 @@ void dhcp_arp_reply(struct netif *netif, ip_addr_t *addr);
 void dhcp_coarse_tmr(void);
 /** to be called every half second */
 void dhcp_fine_tmr(void);
- 
+
 /** DHCP message item offsets and length */
 #define DHCP_OP_OFS       0
 #define DHCP_HTYPE_OFS    1
@@ -153,7 +153,7 @@ void dhcp_fine_tmr(void);
 #define DHCP_COOKIE_OFS   DHCP_MSG_LEN
 #define DHCP_OPTIONS_OFS  (DHCP_MSG_LEN + 4)
 
-#define DHCP_CLIENT_PORT  68  
+#define DHCP_CLIENT_PORT  68
 #define DHCP_SERVER_PORT  67
 
 /** DHCP client states */
@@ -174,7 +174,7 @@ void dhcp_fine_tmr(void);
 /** AUTOIP cooperatation flags */
 #define DHCP_AUTOIP_COOP_STATE_OFF  0
 #define DHCP_AUTOIP_COOP_STATE_ON   1
- 
+
 #define DHCP_BOOTREQUEST  1
 #define DHCP_BOOTREPLY    2
 
@@ -199,7 +199,7 @@ void dhcp_fine_tmr(void);
 #define DHCP_OPTION_PAD 0
 #define DHCP_OPTION_SUBNET_MASK 1 /* RFC 2132 3.3 */
 #define DHCP_OPTION_ROUTER 3
-#define DHCP_OPTION_DNS_SERVER 6 
+#define DHCP_OPTION_DNS_SERVER 6
 #define DHCP_OPTION_HOSTNAME 12
 #define DHCP_OPTION_IP_TTL 23
 #define DHCP_OPTION_MTU 26

+ 1 - 1
app/include/lwip/dns.h

@@ -1,7 +1,7 @@
 /**
  * lwip DNS resolver header file.
 
- * Author: Jim Pettinato 
+ * Author: Jim Pettinato
  *   April 2007
 
  * ported from uIP resolv.c Copyright (c) 2002-2003, Adam Dunkels.

+ 14 - 14
app/include/lwip/err.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 14 - 14
app/include/lwip/icmp.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 23 - 23
app/include/lwip/igmp.h

@@ -2,29 +2,29 @@
  * Copyright (c) 2002 CITEL Technologies Ltd.
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms, with or without 
- * modification, are permitted provided that the following conditions 
- * are met: 
- * 1. Redistributions of source code must retain the above copyright 
- *    notice, this list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright 
- *    notice, this list of conditions and the following disclaimer in the 
- *    documentation and/or other materials provided with the distribution. 
- * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors 
- *    may be used to endorse or promote products derived from this software 
- *    without specific prior written permission. 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of CITEL Technologies Ltd nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY CITEL TECHNOLOGIES AND CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
- * ARE DISCLAIMED.  IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE 
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
- * SUCH DAMAGE. 
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL CITEL TECHNOLOGIES OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  *
  * This file is a contribution to the lwIP TCP/IP stack.
  * The Swedish Institute of Computer Science and Adam Dunkels
@@ -64,8 +64,8 @@ extern "C" {
  * these should really be linked from the interface, but
  * if we keep them separate we will not affect the lwip original code
  * too much
- * 
- * There will be a group for the all systems group address but this 
+ *
+ * There will be a group for the all systems group address but this
  * will not run the state machine as it is used to kick off reports
  * from all the other groups
  */

+ 14 - 14
app/include/lwip/inet.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 14 - 14
app/include/lwip/inet_chksum.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 14 - 14
app/include/lwip/init.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 15 - 15
app/include/lwip/ip.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -134,7 +134,7 @@ struct ip_hdr {
   PACK_STRUCT_FIELD(u16_t _chksum);
   /* source and destination IP addresses */
   PACK_STRUCT_FIELD(ip_addr_p_t src);
-  PACK_STRUCT_FIELD(ip_addr_p_t dest); 
+  PACK_STRUCT_FIELD(ip_addr_p_t dest);
 } PACK_STRUCT_STRUCT;
 PACK_STRUCT_END
 #ifdef PACK_STRUCT_USE_INCLUDES

+ 14 - 14
app/include/lwip/ip_frag.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Jani Monoses <jani@iv.ro>
  *
  */

+ 14 - 14
app/include/lwip/mem.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 14 - 14
app/include/lwip/memp.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 1 - 1
app/include/lwip/memp_std.h

@@ -15,7 +15,7 @@
 #define LWIP_MALLOC_MEMPOOL(num, size) LWIP_MEMPOOL(POOL_##size, num, (size + sizeof(struct memp_malloc_helper)), "MALLOC_"#size, attr)
 #define LWIP_MALLOC_MEMPOOL_START
 #define LWIP_MALLOC_MEMPOOL_END
-#endif /* LWIP_MALLOC_MEMPOOL */ 
+#endif /* LWIP_MALLOC_MEMPOOL */
 
 #ifndef LWIP_PBUF_MEMPOOL
 /* This treats "pbuf pools" just like any other pool.

+ 14 - 14
app/include/lwip/netbuf.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 12 - 12
app/include/lwip/netdb.h

@@ -1,5 +1,5 @@
 /*
- * Redistribution and use in source and binary forms, with or without modification, 
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -8,21 +8,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Simon Goldschmidt
  *
  */

+ 15 - 15
app/include/lwip/netif.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -288,7 +288,7 @@ void netif_set_status_callback(struct netif *netif, netif_status_callback_fn sta
 
 void netif_set_link_up(struct netif *netif)ICACHE_FLASH_ATTR;
 void netif_set_link_down(struct netif *netif)ICACHE_FLASH_ATTR;
-/** Ask if a link is up */ 
+/** Ask if a link is up */
 #define netif_is_link_up(netif) (((netif)->flags & NETIF_FLAG_LINK_UP) ? (u8_t)1 : (u8_t)0)
 
 #if LWIP_NETIF_LINK_CALLBACK

+ 13 - 13
app/include/lwip/netifapi.h

@@ -1,5 +1,5 @@
 /*
- * Redistribution and use in source and binary forms, with or without modification, 
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -8,23 +8,23 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  */
- 
+
 #ifndef __LWIP_NETIFAPI_H__
 #define __LWIP_NETIFAPI_H__
 

+ 30 - 30
app/include/lwip/opt.h

@@ -6,9 +6,9 @@
 
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -17,21 +17,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -60,7 +60,7 @@
 #define SYS_LIGHTWEIGHT_PROT            0
 #endif
 
-/** 
+/**
  * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
  * use lwIP facilities.
  */
@@ -183,8 +183,8 @@
 /**
  * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h
  * that defines additional pools beyond the "standard" ones required
- * by lwIP. If you set this to 1, you must have lwippools.h in your 
- * inlude path somewhere. 
+ * by lwIP. If you set this to 1, you must have lwippools.h in your
+ * inlude path somewhere.
  */
 #ifndef MEMP_USE_CUSTOM_POOLS
 #define MEMP_USE_CUSTOM_POOLS           0
@@ -332,7 +332,7 @@
 
 /**
  * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
- * for callback/timeout API communication. 
+ * for callback/timeout API communication.
  * (only needed if you use tcpip.c)
  */
 #ifndef MEMP_NUM_TCPIP_MSG_API
@@ -341,7 +341,7 @@
 
 /**
  * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
- * for incoming packets. 
+ * for incoming packets.
  * (only needed if you use tcpip.c)
  */
 #ifndef MEMP_NUM_TCPIP_MSG_INPKT
@@ -406,7 +406,7 @@
 #endif
 
 /**
- * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. 
+ * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
  */
 #ifndef PBUF_POOL_SIZE
 #define PBUF_POOL_SIZE                  16
@@ -727,7 +727,7 @@
 #endif
 
 /**
- * SNMP_PRIVATE_MIB: 
+ * SNMP_PRIVATE_MIB:
  * When using a private MIB, you have to create a file 'private_mib.h' that contains
  * a 'struct mib_array_node mib_private' which contains your MIB.
  */
@@ -775,7 +775,7 @@
    ----------------------------------
 */
 /**
- * LWIP_IGMP==1: Turn on IGMP module. 
+ * LWIP_IGMP==1: Turn on IGMP module.
  */
 #ifndef LWIP_IGMP
 #define LWIP_IGMP                       0
@@ -892,12 +892,12 @@
 #endif
 
 /**
- * TCP_WND: The size of a TCP window.  This must be at least 
+ * TCP_WND: The size of a TCP window.  This must be at least
  * (2 * TCP_MSS) for things to work well
  */
 #ifndef TCP_WND
 #define TCP_WND                         (4 * TCP_MSS)
-#endif 
+#endif
 
 /**
  * TCP_MAXRTX: Maximum number of retransmissions of data segments.
@@ -946,7 +946,7 @@
 
 
 /**
- * TCP_SND_BUF: TCP sender buffer space (bytes). 
+ * TCP_SND_BUF: TCP sender buffer space (bytes).
  */
 #ifndef TCP_SND_BUF
 #define TCP_SND_BUF                     256
@@ -1037,7 +1037,7 @@
 //#ifndef LWIP_EVENT_API
 //#define LWIP_EVENT_API                  0
 //#define LWIP_CALLBACK_API               1
-//#else 
+//#else
 //#define LWIP_EVENT_API                  1
 //#define LWIP_CALLBACK_API               0
 //#endif
@@ -1735,28 +1735,28 @@
 #ifndef CHECKSUM_GEN_IP
 #define CHECKSUM_GEN_IP                 1
 #endif
- 
+
 /**
  * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.
  */
 #ifndef CHECKSUM_GEN_UDP
 #define CHECKSUM_GEN_UDP                1
 #endif
- 
+
 /**
  * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.
  */
 #ifndef CHECKSUM_GEN_TCP
 #define CHECKSUM_GEN_TCP                1
 #endif
- 
+
 /**
  * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.
  */
 #ifndef CHECKSUM_CHECK_IP
 #define CHECKSUM_CHECK_IP               1
 #endif
- 
+
 /**
  * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.
  */

+ 17 - 17
app/include/lwip/pbuf.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -104,15 +104,15 @@ struct pbuf {
    * the stack itself, or pbuf->next pointers from a chain.
    */
   u16_t ref;
-  
+
   /* add a pointer for esf_buf */
-  void * eb; 
+  void * eb;
 };
 
 #if LWIP_SUPPORT_CUSTOM_PBUF
 /** Prototype for a function to free a custom pbuf */
 typedef void (*pbuf_free_custom_fn)(struct pbuf *p);
-  
+
 /** A custom pbuf: like a pbuf, but following a function pointer to free it. */
 struct pbuf_custom {
   /** The actual pbuf */

+ 44 - 44
app/include/lwip/puck_def.h

@@ -1,44 +1,44 @@
-/*
- * puck_def.h
- *
- *  Created on: Jul 22, 2010
- *      Author: dtoma
- */
-
-#ifndef PUCK_DEF_H_
-#define PUCK_DEF_H_
-
-
-
-#define INSTRUMENT_PORT      8760
-
-#define INSTRUMENT_LENGTH    80
-
-#define MDNS_NAME_LENGTH     68 //68
-
-char* PUCK_SERVICE    = NULL;
-//#define PUCK_SERVICE	"_Escpressif._tcp.local"
-#define DNS_SD_SERVICE       "_services._dns-sd._udp.local"
-#define SERVICE_DESCRIPTION  "PUCK PROTOCOL"
-#define PUCK_SERVICE_LENGTH  30
-
-#define UUID_LEN      		 	16
-#define DS_VERS_LEN    			2
-#define DS_SIZE_LEN    			2
-#define MAN_ID_LEN     			4
-#define MAN_MODEL_LEN  			2
-#define MAN_VERS_LEN   			2
-#define SER_NUM_LEN    			4
-#define NAME_LEN       			64
-#define PUCK_DATASHEET_SIZE   	96
-
-#define UUID_OFFSET       0
-#define DS_VERS_OFFSET    UUID_LEN + UUID_OFFSET
-#define DS_SIZE_OFFSET    DS_VERS_LEN + DS_VERS_OFFSET
-#define MAN_ID_OFFSET     DS_SIZE_LEN + DS_SIZE_OFFSET
-#define MAN_MODEL_OFFSET  MAN_ID_LEN + MAN_ID_OFFSET
-#define MAN_VERS_OFFSET   MAN_MODEL_LEN + MAN_MODEL_OFFSET
-#define SER_NUM_OFFSET    MAN_VERS_LEN + MAN_VERS_OFFSET
-#define NAME_OFFSET       SER_NUM_LEN + SER_NUM_OFFSET
-
-#endif /* __PUCK_DEF_H__ */
+/*
+ * puck_def.h
+ *
+ *  Created on: Jul 22, 2010
+ *      Author: dtoma
+ */
+
+#ifndef PUCK_DEF_H_
+#define PUCK_DEF_H_
+
+
+
+#define INSTRUMENT_PORT      8760
+
+#define INSTRUMENT_LENGTH    80
+
+#define MDNS_NAME_LENGTH     68 //68
+
+char* PUCK_SERVICE    = NULL;
+//#define PUCK_SERVICE	"_Escpressif._tcp.local"
+#define DNS_SD_SERVICE       "_services._dns-sd._udp.local"
+#define SERVICE_DESCRIPTION  "PUCK PROTOCOL"
+#define PUCK_SERVICE_LENGTH  30
+
+#define UUID_LEN      		 	16
+#define DS_VERS_LEN    			2
+#define DS_SIZE_LEN    			2
+#define MAN_ID_LEN     			4
+#define MAN_MODEL_LEN  			2
+#define MAN_VERS_LEN   			2
+#define SER_NUM_LEN    			4
+#define NAME_LEN       			64
+#define PUCK_DATASHEET_SIZE   	96
+
+#define UUID_OFFSET       0
+#define DS_VERS_OFFSET    UUID_LEN + UUID_OFFSET
+#define DS_SIZE_OFFSET    DS_VERS_LEN + DS_VERS_OFFSET
+#define MAN_ID_OFFSET     DS_SIZE_LEN + DS_SIZE_OFFSET
+#define MAN_MODEL_OFFSET  MAN_ID_LEN + MAN_ID_OFFSET
+#define MAN_VERS_OFFSET   MAN_MODEL_LEN + MAN_MODEL_OFFSET
+#define SER_NUM_OFFSET    MAN_VERS_LEN + MAN_VERS_OFFSET
+#define NAME_OFFSET       SER_NUM_LEN + SER_NUM_OFFSET
+
+#endif /* __PUCK_DEF_H__ */

+ 24 - 24
app/include/lwip/sio.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,17 +11,17 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
@@ -53,7 +53,7 @@ typedef void * sio_fd_t;
 #ifndef sio_open
 /**
  * Opens a serial device for communication.
- * 
+ *
  * @param devnum device number
  * @return handle to serial device if successful, NULL otherwise
  */
@@ -63,10 +63,10 @@ sio_fd_t sio_open(u8_t devnum)ICACHE_FLASH_ATTR;
 #ifndef sio_send
 /**
  * Sends a single character to the serial device.
- * 
+ *
  * @param c character to send
  * @param fd serial device handle
- * 
+ *
  * @note This function will block until the character can be sent.
  */
 void sio_send(u8_t c, sio_fd_t fd)ICACHE_FLASH_ATTR;
@@ -75,9 +75,9 @@ void sio_send(u8_t c, sio_fd_t fd)ICACHE_FLASH_ATTR;
 #ifndef sio_recv
 /**
  * Receives a single character from the serial device.
- * 
+ *
  * @param fd serial device handle
- * 
+ *
  * @note This function will block until a character is received.
  */
 u8_t sio_recv(sio_fd_t fd)ICACHE_FLASH_ATTR;
@@ -86,12 +86,12 @@ u8_t sio_recv(sio_fd_t fd)ICACHE_FLASH_ATTR;
 #ifndef sio_read
 /**
  * Reads from the serial device.
- * 
+ *
  * @param fd serial device handle
  * @param data pointer to data buffer for receiving
  * @param len maximum length (in bytes) of data to receive
  * @return number of bytes actually received - may be 0 if aborted by sio_read_abort
- * 
+ *
  * @note This function will block until data can be received. The blocking
  * can be cancelled by calling sio_read_abort().
  */
@@ -102,7 +102,7 @@ u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len)ICACHE_FLASH_ATTR;
 /**
  * Tries to read from the serial device. Same as sio_read but returns
  * immediately if no data is available and never blocks.
- * 
+ *
  * @param fd serial device handle
  * @param data pointer to data buffer for receiving
  * @param len maximum length (in bytes) of data to receive
@@ -114,12 +114,12 @@ u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len)ICACHE_FLASH_ATTR;
 #ifndef sio_write
 /**
  * Writes to the serial device.
- * 
+ *
  * @param fd serial device handle
  * @param data pointer to data to send
  * @param len length (in bytes) of data to send
  * @return number of bytes actually sent
- * 
+ *
  * @note This function will block until all data can be sent.
  */
 u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)ICACHE_FLASH_ATTR;
@@ -128,7 +128,7 @@ u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len)ICACHE_FLASH_ATTR;
 #ifndef sio_read_abort
 /**
  * Aborts a blocking sio_read() call.
- * 
+ *
  * @param fd serial device handle
  */
 void sio_read_abort(sio_fd_t fd)ICACHE_FLASH_ATTR;

+ 27 - 27
app/include/lwip/snmp.h

@@ -2,8 +2,8 @@
  * Copyright (c) 2001, 2002 Leon Woestenberg <leon.woestenberg@axon.tv>
  * Copyright (c) 2001, 2002 Axon Digital Design B.V., The Netherlands.
  * All rights reserved.
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -12,21 +12,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Leon Woestenberg <leon.woestenberg@axon.tv>
  *
  */
@@ -109,7 +109,7 @@ void snmp_set_sysname(u8_t *ocstr, u8_t *ocstrlen);
 void snmp_set_syslocation(u8_t *ocstr, u8_t *ocstrlen);
 
 /* network interface */
-void snmp_add_ifinoctets(struct netif *ni, u32_t value); 
+void snmp_add_ifinoctets(struct netif *ni, u32_t value);
 void snmp_inc_ifinucastpkts(struct netif *ni);
 void snmp_inc_ifinnucastpkts(struct netif *ni);
 void snmp_inc_ifindiscards(struct netif *ni);
@@ -167,7 +167,7 @@ void snmp_inc_icmpoutdestunreachs(void);
 void snmp_inc_icmpouttimeexcds(void);
 void snmp_inc_icmpoutparmprobs(void);
 void snmp_inc_icmpoutsrcquenchs(void);
-void snmp_inc_icmpoutredirects(void); 
+void snmp_inc_icmpoutredirects(void);
 void snmp_inc_icmpoutechos(void);
 void snmp_inc_icmpoutechoreps(void);
 void snmp_inc_icmpouttimestamps(void);
@@ -242,7 +242,7 @@ void snmp_get_snmpenableauthentraps(u8_t *value);
 #define snmp_set_syslocation(ocstr, ocstrlen);
 
 /* network interface */
-#define snmp_add_ifinoctets(ni,value) 
+#define snmp_add_ifinoctets(ni,value)
 #define snmp_inc_ifinucastpkts(ni)
 #define snmp_inc_ifinnucastpkts(ni)
 #define snmp_inc_ifindiscards(ni)
@@ -282,26 +282,26 @@ void snmp_get_snmpenableauthentraps(u8_t *value);
 
 /* ICMP */
 #define snmp_inc_icmpinmsgs()
-#define snmp_inc_icmpinerrors() 
-#define snmp_inc_icmpindestunreachs() 
+#define snmp_inc_icmpinerrors()
+#define snmp_inc_icmpindestunreachs()
 #define snmp_inc_icmpintimeexcds()
-#define snmp_inc_icmpinparmprobs() 
-#define snmp_inc_icmpinsrcquenchs() 
-#define snmp_inc_icmpinredirects() 
-#define snmp_inc_icmpinechos() 
+#define snmp_inc_icmpinparmprobs()
+#define snmp_inc_icmpinsrcquenchs()
+#define snmp_inc_icmpinredirects()
+#define snmp_inc_icmpinechos()
 #define snmp_inc_icmpinechoreps()
-#define snmp_inc_icmpintimestamps() 
+#define snmp_inc_icmpintimestamps()
 #define snmp_inc_icmpintimestampreps()
 #define snmp_inc_icmpinaddrmasks()
 #define snmp_inc_icmpinaddrmaskreps()
 #define snmp_inc_icmpoutmsgs()
 #define snmp_inc_icmpouterrors()
-#define snmp_inc_icmpoutdestunreachs() 
-#define snmp_inc_icmpouttimeexcds() 
+#define snmp_inc_icmpoutdestunreachs()
+#define snmp_inc_icmpouttimeexcds()
 #define snmp_inc_icmpoutparmprobs()
 #define snmp_inc_icmpoutsrcquenchs()
-#define snmp_inc_icmpoutredirects() 
-#define snmp_inc_icmpoutechos() 
+#define snmp_inc_icmpoutredirects()
+#define snmp_inc_icmpoutechos()
 #define snmp_inc_icmpoutechoreps()
 #define snmp_inc_icmpouttimestamps()
 #define snmp_inc_icmpouttimestampreps()

+ 1 - 1
app/include/lwip/snmp_asn1.h

@@ -2,7 +2,7 @@
  * @file
  * Abstract Syntax Notation One (ISO 8824, 8825) codec.
  */
- 
+
 /*
  * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands.
  * All rights reserved.

+ 4 - 4
app/include/lwip/snmp_structs.h

@@ -54,7 +54,7 @@ extern "C" {
 #endif
 
 /* MIB object instance */
-#define MIB_OBJECT_NONE 0 
+#define MIB_OBJECT_NONE 0
 #define MIB_OBJECT_SCALAR 1
 #define MIB_OBJECT_TAB 2
 
@@ -113,7 +113,7 @@ struct mib_node
   /** tests length and/or range BEFORE setting */
   u8_t (*set_test)(struct obj_def *od, u16_t len, void *value);
   /** sets object value, only to be called when set_test()  */
-  void (*set_value)(struct obj_def *od, u16_t len, void *value);  
+  void (*set_value)(struct obj_def *od, u16_t len, void *value);
   /** One out of MIB_NODE_AR, MIB_NODE_LR or MIB_NODE_EX */
   u8_t node_type;
   /* array or max list length */
@@ -161,7 +161,7 @@ struct mib_ram_array_node
 
 struct mib_list_node
 {
-  struct mib_list_node *prev;  
+  struct mib_list_node *prev;
   struct mib_list_node *next;
   s32_t objid;
   struct mib_node *nptr;
@@ -223,7 +223,7 @@ struct mib_external_node
   void (*get_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value);
   u8_t (*set_test_a)(u8_t rid, struct obj_def *od, u16_t len, void *value);
   void (*set_value_a)(u8_t rid, struct obj_def *od, u16_t len, void *value);
-  /** async Panic Close (agent returns error reply, 
+  /** async Panic Close (agent returns error reply,
       e.g. used for external transaction cleanup) */
   void (*get_object_def_pc)(u8_t rid, u8_t ident_len, s32_t *ident);
   void (*get_value_pc)(u8_t rid, struct obj_def *od);

+ 15 - 15
app/include/lwip/sockets.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -302,7 +302,7 @@ typedef struct ip_mreq {
 #endif /* FD_SET */
 
 /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided
- * by your system, set this to 0 and include <sys/time.h> in cc.h */ 
+ * by your system, set this to 0 and include <sys/time.h> in cc.h */
 #ifndef LWIP_TIMEVAL_PRIVATE
 #define LWIP_TIMEVAL_PRIVATE 1
 #endif

+ 15 - 15
app/include/lwip/stats.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -53,7 +53,7 @@ extern "C" {
 #else
 #define STAT_COUNTER     u16_t
 #define STAT_COUNTER_F   U16_F
-#endif 
+#endif
 
 struct stats_proto {
   STAT_COUNTER xmit;             /* Transmitted packets. */

+ 16 - 16
app/include/lwip/sys.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -76,7 +76,7 @@ typedef u8_t sys_mbox_t;
 /** sys_mbox_tryfetch() returns SYS_MBOX_EMPTY if appropriate.
  * For now we use the same magic value, but we allow this to change in future.
  */
-#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT 
+#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT
 
 #include "lwip/err.h"
 #include "arch/sys_arch.h"
@@ -115,7 +115,7 @@ void sys_mutex_lock(sys_mutex_t *mutex);
 void sys_mutex_unlock(sys_mutex_t *mutex);
 /** Delete a semaphore
  * @param mutex the mutex to delete */
-void sys_mutex_free(sys_mutex_t *mutex); 
+void sys_mutex_free(sys_mutex_t *mutex);
 #ifndef sys_mutex_valid
 /** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */
 int sys_mutex_valid(sys_mutex_t *mutex);

+ 25 - 25
app/include/lwip/tcp.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -174,7 +174,7 @@ struct tcp_pcb {
 
   /* ports are in host byte order */
   u16_t remote_port;
-  
+
   u8_t flags;
 #define TF_ACK_DELAY   ((u8_t)0x01U)   /* Delayed ACK. */
 #define TF_ACK_NOW     ((u8_t)0x02U)   /* Immediate ACK. */
@@ -196,12 +196,12 @@ struct tcp_pcb {
   /* Timers */
   u32_t tmr;
   u8_t polltmr, pollinterval;
-  
+
   /* Retransmission timer. */
   s16_t rtime;
-  
+
   u16_t mss;   /* maximum segment size */
-  
+
   /* RTT (round trip time) estimation variables */
   u32_t rttest; /* RTT estimate in 500ms ticks */
   u32_t rtseq;  /* sequence number being timed */
@@ -213,9 +213,9 @@ struct tcp_pcb {
   /* fast retransmit/recovery */
   u32_t lastack; /* Highest acknowledged seqno. */
   u8_t dupacks;
-  
+
   /* congestion avoidance/control variables */
-  u16_t cwnd;  
+  u16_t cwnd;
   u16_t ssthresh;
 
   /* sender variables */
@@ -226,7 +226,7 @@ struct tcp_pcb {
   u32_t snd_lbb;       /* Sequence number of next byte to be buffered. */
 
   u16_t acked;
-  
+
   u16_t snd_buf;   /* Available buffer space for sending (in bytes). */
 #define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3)
   u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */
@@ -234,12 +234,12 @@ struct tcp_pcb {
 #if TCP_OVERSIZE
   /* Extra bytes available at the end of the last pbuf in unsent. */
   u16_t unsent_oversize;
-#endif /* TCP_OVERSIZE */ 
+#endif /* TCP_OVERSIZE */
 
   /* These are ordered by sequence number: */
   struct tcp_seg *unsent;   /* Unsent (queued) segments. */
   struct tcp_seg *unacked;  /* Sent but unacknowledged segments. */
-#if TCP_QUEUE_OOSEQ  
+#if TCP_QUEUE_OOSEQ
   struct tcp_seg *ooseq;    /* Received out of sequence segments. */
 #endif /* TCP_QUEUE_OOSEQ */
 
@@ -269,7 +269,7 @@ struct tcp_pcb {
   u32_t keep_intvl;
   u32_t keep_cnt;
 #endif /* LWIP_TCP_KEEPALIVE */
-  
+
   /* Persist timer counter */
   u32_t persist_cnt;
   /* Persist timer back-off */
@@ -279,7 +279,7 @@ struct tcp_pcb {
   u8_t keep_cnt_sent;
 };
 
-struct tcp_pcb_listen {  
+struct tcp_pcb_listen {
 /* Common members of all PCB types */
   IP_PCB;
 /* Protocol specific PCB members */

+ 17 - 17
app/include/lwip/tcp_impl.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -284,7 +284,7 @@ struct tcp_seg {
   u16_t oversize_left;     /* Extra bytes available at the end of the last
                               pbuf in unsent (used for asserting vs.
                               tcp_pcb.unsent_oversized only) */
-#endif /* TCP_OVERSIZE_DBGCHECK */ 
+#endif /* TCP_OVERSIZE_DBGCHECK */
 #if TCP_CHECKSUM_ON_COPY
   u16_t chksum;
   u8_t  chksum_swapped;
@@ -313,7 +313,7 @@ extern u32_t tcp_ticks;
 
 /* The TCP PCB lists. */
 union tcp_listen_pcbs_t { /* List of all TCP PCBs in LISTEN state. */
-  struct tcp_pcb_listen *listen_pcbs; 
+  struct tcp_pcb_listen *listen_pcbs;
   struct tcp_pcb *pcbs;
 };
 extern struct tcp_pcb *tcp_bound_pcbs;
@@ -325,7 +325,7 @@ extern struct tcp_pcb *tcp_tw_pcbs;      /* List of all TCP PCBs in TIME-WAIT. *
 
 extern struct tcp_pcb *tcp_tmp_pcb;      /* Only used for temporary storage. */
 
-/* Axioms about the above lists:   
+/* Axioms about the above lists:
    1) Every TCP PCB that is not CLOSED is in one of the lists.
    2) A PCB is only in one of the lists.
    3) All PCBs in the tcp_listen_pcbs list is in LISTEN state.

+ 14 - 14
app/include/lwip/tcpip.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 14 - 14
app/include/lwip/timers.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *         Simon Goldschmidt
  *

+ 15 - 15
app/include/lwip/udp.h

@@ -1,8 +1,8 @@
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -11,21 +11,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -113,7 +113,7 @@ struct udp_pcb {
   /** receive callback function */
   udp_recv_fn recv;
   /** user-supplied argument for the recv callback */
-  void *recv_arg;  
+  void *recv_arg;
 };
 /* udp_pcbs export for exernal reference (e.g. SNMP agent) */
 extern struct udp_pcb *udp_pcbs;

+ 31 - 31
app/include/lwipopts.h

@@ -6,9 +6,9 @@
 
 /*
  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -17,21 +17,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */
@@ -54,7 +54,7 @@
 #define SYS_LIGHTWEIGHT_PROT            0
 #endif
 
-/** 
+/**
  * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
  * use lwIP facilities.
  */
@@ -177,8 +177,8 @@
 /**
  * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h
  * that defines additional pools beyond the "standard" ones required
- * by lwIP. If you set this to 1, you must have lwippools.h in your 
- * inlude path somewhere. 
+ * by lwIP. If you set this to 1, you must have lwippools.h in your
+ * inlude path somewhere.
  */
 #ifndef MEMP_USE_CUSTOM_POOLS
 #define MEMP_USE_CUSTOM_POOLS           0
@@ -326,7 +326,7 @@
 
 /**
  * MEMP_NUM_TCPIP_MSG_API: the number of struct tcpip_msg, which are used
- * for callback/timeout API communication. 
+ * for callback/timeout API communication.
  * (only needed if you use tcpip.c)
  */
 #ifndef MEMP_NUM_TCPIP_MSG_API
@@ -335,7 +335,7 @@
 
 /**
  * MEMP_NUM_TCPIP_MSG_INPKT: the number of struct tcpip_msg, which are used
- * for incoming packets. 
+ * for incoming packets.
  * (only needed if you use tcpip.c)
  */
 #ifndef MEMP_NUM_TCPIP_MSG_INPKT
@@ -400,7 +400,7 @@
 #endif
 
 /**
- * PBUF_POOL_SIZE: the number of buffers in the pbuf pool. 
+ * PBUF_POOL_SIZE: the number of buffers in the pbuf pool.
  */
 #ifndef PBUF_POOL_SIZE
 #define PBUF_POOL_SIZE                  10
@@ -712,7 +712,7 @@
 
 /**
  * SNMP_CONCURRENT_REQUESTS: Number of concurrent requests the module will
- * allow. At least one request buffer is required. 
+ * allow. At least one request buffer is required.
  */
 #ifndef SNMP_CONCURRENT_REQUESTS
 #define SNMP_CONCURRENT_REQUESTS        0
@@ -727,7 +727,7 @@
 #endif
 
 /**
- * SNMP_PRIVATE_MIB: 
+ * SNMP_PRIVATE_MIB:
  */
 #ifndef SNMP_PRIVATE_MIB
 #define SNMP_PRIVATE_MIB                0
@@ -773,7 +773,7 @@
    ----------------------------------
 */
 /**
- * LWIP_IGMP==1: Turn on IGMP module. 
+ * LWIP_IGMP==1: Turn on IGMP module.
  */
 #ifndef LWIP_IGMP
 #define LWIP_IGMP                       1
@@ -958,12 +958,12 @@
 #endif
 
 /**
- * TCP_WND: The size of a TCP window.  This must be at least 
+ * TCP_WND: The size of a TCP window.  This must be at least
  * (2 * TCP_MSS) for things to work well
  */
 #ifndef TCP_WND
 #define TCP_WND                         (*(volatile uint32*)0x600011F0)
-#endif 
+#endif
 
 /**
  * TCP_CALCULATE_EFF_SEND_MSS: "The maximum size of a segment that TCP really
@@ -979,7 +979,7 @@
 
 
 /**
- * TCP_SND_BUF: TCP sender buffer space (bytes). 
+ * TCP_SND_BUF: TCP sender buffer space (bytes).
  */
 #ifndef TCP_SND_BUF
 #define TCP_SND_BUF                     2 * TCP_MSS
@@ -1070,7 +1070,7 @@
 #ifndef LWIP_EVENT_API
 #define LWIP_EVENT_API                  0
 #define LWIP_CALLBACK_API               1
-#else 
+#else
 #define LWIP_EVENT_API                  1
 #define LWIP_CALLBACK_API               0
 #endif
@@ -1769,28 +1769,28 @@
 #ifndef CHECKSUM_GEN_IP
 #define CHECKSUM_GEN_IP                 1
 #endif
- 
+
 /**
  * CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP packets.
  */
 #ifndef CHECKSUM_GEN_UDP
 #define CHECKSUM_GEN_UDP                1
 #endif
- 
+
 /**
  * CHECKSUM_GEN_TCP==1: Generate checksums in software for outgoing TCP packets.
  */
 #ifndef CHECKSUM_GEN_TCP
 #define CHECKSUM_GEN_TCP                1
 #endif
- 
+
 /**
  * CHECKSUM_CHECK_IP==1: Check checksums in software for incoming IP packets.
  */
 #ifndef CHECKSUM_CHECK_IP
 #define CHECKSUM_CHECK_IP               1
 #endif
- 
+
 /**
  * CHECKSUM_CHECK_UDP==1: Check checksums in software for incoming UDP packets.
  */

+ 14 - 14
app/include/netif/etharp.h

@@ -2,9 +2,9 @@
  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
  * Copyright (c) 2003-2004 Leon Woestenberg <leon.woestenberg@axon.tv>
  * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands.
- * All rights reserved. 
- * 
- * Redistribution and use in source and binary forms, with or without modification, 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *
  * 1. Redistributions of source code must retain the above copyright notice,
@@ -13,21 +13,21 @@
  *    this list of conditions and the following disclaimer in the documentation
  *    and/or other materials provided with the distribution.
  * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission. 
+ *    derived from this software without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  *
  * This file is part of the lwIP TCP/IP stack.
- * 
+ *
  * Author: Adam Dunkels <adam@sics.se>
  *
  */

+ 2 - 2
app/include/netif/ppp_oe.h

@@ -6,13 +6,13 @@
 * The authors hereby grant permission to use, copy, modify, distribute,
 * and license this software and its documentation for any purpose, provided
 * that existing copyright notices are retained in all copies and that this
-* notice and the following disclaimer are included verbatim in any 
+* notice and the following disclaimer are included verbatim in any
 * distributions. No written agreement, license, or royalty fee is required
 * for any of the authorized uses.
 *
 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+ 2 - 2
app/include/netif/wlan_lwip_if.h

@@ -1,6 +1,6 @@
 /*
  *  Copyright (c) 2010-2011 	Espressif System
- *   
+ *
 */
 
 #ifndef _WLAN_LWIP_IF_H_
@@ -10,7 +10,7 @@
 #define LWIP_IF1_PRIO   29
 
 enum {
-	SIG_LWIP_RX = 0, 
+	SIG_LWIP_RX = 0,
 };
 
 struct netif * eagle_lwip_if_alloc(struct ieee80211_conn *conn, const uint8 *macaddr, struct ip_info *info);

+ 3 - 3
app/include/rtc/rtctime_internal.h

@@ -34,7 +34,7 @@
 
 /*
  * It is vital that this file is only included once in the entire
- * system. 
+ * system.
  */
 
 #ifndef _RTCTIME_INTERNAL_H_
@@ -533,7 +533,7 @@ static void rtc_time_enter_deep_sleep_us(uint32_t us)
 
   if (rtc_time_check_wake_magic())
     rtc_time_set_sleep_magic();
-  else 
+  else
     bbram_save();
 
   rtc_reg_write(RTC_TARGET_ADDR,rtc_time_read_raw()+cycles);
@@ -788,7 +788,7 @@ static int32_t rtc_time_adjust_delta_by_rate(int32_t delta) {
 }
 
 static uint64_t rtc_time_adjust_us_by_rate(uint64_t us, int force) {
-  uint64_t usoff = us - rtc_usatlastrate; 
+  uint64_t usoff = us - rtc_usatlastrate;
   uint64_t usadj = (usoff * ((1ull << 32) + (int) rtc_usrate)) >> 32;
   usadj = usadj + rtc_rateadjustedus;
 

+ 1 - 1
app/include/sys/espconn_mbedtls.h

@@ -64,7 +64,7 @@ typedef struct{
 #endif
 	pmbedtls_session	psession;
 	mbedtls_net_context fd;
-	mbedtls_net_context listen_fd;	
+	mbedtls_net_context listen_fd;
 	mbedtls_ctr_drbg_context ctr_drbg;
 	mbedtls_ssl_context ssl;
 	mbedtls_ssl_config conf;

+ 1 - 1
app/include/sys/socket.h

@@ -111,7 +111,7 @@ typedef enum{
   do {	\
 		mbedtls_parse_thread(s, event, error); \
   }while(0)
-  
+
 typedef enum{
 	ENTCONN_EVENT_NONE = 0,
 	NETCONN_EVENT_ESTABLISHED = 1,

+ 2 - 2
app/include/u8g2_displays.h

@@ -57,7 +57,7 @@
 
 #else
 
-// I2C displays can be defined in an external file. 
+// I2C displays can be defined in an external file.
 #define U8G2_DISPLAY_TABLE_I2C \
    U8G2_DISPLAY_TABLE_I2C_EXTRA
 
@@ -150,7 +150,7 @@
 
 #else
 
-// SPI displays can be defined in an external file. 
+// SPI displays can be defined in an external file.
 #define U8G2_DISPLAY_TABLE_SPI \
    U8G2_DISPLAY_TABLE_SPI_EXTRA
 

+ 1 - 1
app/include/u8g2_fonts.h

@@ -18,7 +18,7 @@
 
 #else
 //
-// The font table can be defined in an external file. 
+// The font table can be defined in an external file.
 #define U8G2_FONT_TABLE \
   U8G2_FONT_TABLE_EXTRA
 

+ 3 - 3
app/include/user_config.h

@@ -73,7 +73,7 @@
 
 #define BUILD_SPIFFS
 //#define SPIFFS_FIXED_LOCATION        0x100000
-//#define SPIFFS_MAX_FILESYSTEM_SIZE    0x20000	
+//#define SPIFFS_MAX_FILESYSTEM_SIZE    0x20000
 //#define SPIFFS_SIZE_1M_BOUNDARY
 #define SPIFFS_CACHE 1          // Enable if you use you SPIFFS in R/W mode
 #define SPIFFS_MAX_OPEN_FILES 4 // maximum number of open files for SPIFFS
@@ -119,10 +119,10 @@
 // management, using internal timer callbacks.  Whilst many Lua developers
 // prefer to implement equivalent features in Lua, others will prefer the
 // Wifi module to do this for them.  Uncomment the following to enable
-// this functionality.  See the relevant WiFi module documentation for 
+// this functionality.  See the relevant WiFi module documentation for
 // further details, as the scope of these changes is not obvious.
 
-//  Enable the wifi.startsmart() and wifi.stopsmart()  
+//  Enable the wifi.startsmart() and wifi.stopsmart()
 //#define WIFI_SMART_ENABLE
 
 //  Enable wifi.sta.config() event callbacks

+ 1 - 1
app/include/user_mbedtls.h

@@ -307,7 +307,7 @@ extern unsigned int max_content_len;
 #else
 // the current mbedtls integration doesn't allow to set the buffer size dynamically:
 //   MBEDTLS_SSL_MAX_FRAGMENT_LENGTH feature and dynamic sizing are mutually exclusive
-//   due to non-constant initializer element in app/mbedtls/library/ssl_tls.c:150 
+//   due to non-constant initializer element in app/mbedtls/library/ssl_tls.c:150
 // the buffer size is hardcoded here and value is taken from SSL_BUFFER_SIZE (user_config.h)
 #define MBEDTLS_SSL_MAX_CONTENT_LEN             SSL_BUFFER_SIZE /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */
 #endif

Some files were not shown because too many files changed in this diff