Renesas / Mbed OS GR-PEACH_Audio_Playback_Sample

Dependencies:   R_BSP TLV320_RBSP USBHost_custom

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sys_scan_folder.cpp Source File

sys_scan_folder.cpp

00001 /*******************************************************************************
00002 * DISCLAIMER
00003 * This software is supplied by Renesas Electronics Corporation and is only
00004 * intended for use with Renesas products. No other uses are authorized. This
00005 * software is owned by Renesas Electronics Corporation and is protected under
00006 * all applicable laws, including copyright laws.
00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
00016 * Renesas reserves the right, without notice, to make changes to this software
00017 * and to discontinue the availability of this software. By using this software,
00018 * you agree to the additional terms and conditions found by accessing the
00019 * following link:
00020 * http://www.renesas.com/disclaimer*
00021 * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
00022 *******************************************************************************/
00023 
00024 #include "mbed.h"
00025 #include "FATFileSystem.h"
00026 #include "USBHostMSD.h"
00027 #include "sys_scan_folder.h"
00028 
00029 /*--- Macro definition of folder structure scan. ---*/
00030 /* The character string to identify root directory. */
00031 #define STR_ROOT_FOR_F_OPENDIR  ""                      /* to use f_opendir() */
00032 #define STR_ROOT_FOR_FOPEN      "/" SYS_USB_MOUNT_NAME  /* to use fopen()  */
00033 
00034 /* The file extension of FLAC. */
00035 #define FILE_EXT_FLAC           ".flac"
00036 #define FILE_EXT_FLA            ".fla"
00037 
00038 #define CHR_FULL_STOP           '.'         /* 0x2E: FULL STOP */
00039 #define CHR_SOLIDUS             '/'         /* 0x2F: SOLIDUS */
00040 #define FOLD_ID_NOT_EXIST       (0xFFFFFFFFu)
00041 #define OPEN_MODE_READ_ONLY     "r"
00042 
00043 /* File path maximum size including the usb mount name size */
00044 #define USB_MOUNT_NAME_SIZE     (sizeof(STR_ROOT_FOR_FOPEN "/"))
00045 #define FILE_PATH_MAX_LEN       (60u)
00046 #define FILE_PATH_MAX_SIZE      (USB_MOUNT_NAME_SIZE + FILE_PATH_MAX_LEN)
00047 
00048 static const char_t *get_full_path(fid_scan_folder_t * const p_info, 
00049                                                 const item_t * const p_item);
00050 static bool open_dir(fid_scan_folder_t * const p_info, 
00051                         const item_t * const p_item, FATFS_DIR * const p_fdir);
00052 static bool read_dir(fid_scan_folder_t * const p_info, FATFS_DIR * const p_fdir, 
00053                             const char_t ** const p_name, bool * const p_flag_dir);
00054 static bool regist_item(item_t * const p_item, 
00055                             const char_t * const p_name, const uint32_t parent);
00056 static bool check_extension(const char_t * const p_name);
00057 
00058 static bool check_folder_depth(const fid_scan_folder_t * const p_info, 
00059                                                     const uint32_t folder_id);
00060 
00061 void fid_init(fid_scan_folder_t * const p_info)
00062 {
00063     if (p_info != NULL) {
00064         p_info->total_folder = 0u;
00065         p_info->total_track = 0u;
00066     }
00067 }
00068 
00069 bool fid_scan_folder_struct(fid_scan_folder_t * const p_info)
00070 {
00071     bool            ret = false;
00072     bool            result;
00073     bool            chk;
00074     uint32_t        i;
00075     item_t          *p_item;
00076     FATFS_DIR       fdir;
00077     const char_t    *p_name;
00078     bool            flg_dir;
00079     bool            chk_dep;
00080     
00081     if (p_info != NULL) {
00082         /* Initializes the scan data. */
00083         p_info->total_track = 0u;
00084         p_info->total_folder = 0u;
00085 
00086         /* Registers the identifier of the root directory to use f_opendir(). */
00087         (void) regist_item(&p_info->folder_list[0], STR_ROOT_FOR_F_OPENDIR, FOLD_ID_NOT_EXIST);
00088         p_info->total_folder++;
00089 
00090         /* Checks the item in all registered directory. */
00091         for (i = 0; i < p_info->total_folder; i++) {
00092             chk_dep = check_folder_depth(p_info, i);
00093             result = open_dir(p_info, &p_info->folder_list[i], &fdir);
00094             while (result == true) {
00095                 result = read_dir(p_info, &fdir, &p_name, &flg_dir);
00096                 if (result == true) {
00097                     /* Checks the attribute of this item. */
00098                     if (flg_dir == true) {
00099                         /* This item is directory. */
00100                         if ((chk_dep == true) && (p_info->total_folder < SYS_MAX_FOLDER_NUM)) {
00101                             p_item = &p_info->folder_list[p_info->total_folder];
00102                             chk = regist_item(p_item, p_name, i);
00103                             if (chk == true) {
00104                                 /* Register of directory item was success. */
00105                                 p_info->total_folder++;
00106                             }
00107                         }
00108                     } else {
00109                         /* This item is file. */
00110                         chk = check_extension(p_name);
00111                         if ((chk == true) && (p_info->total_track < SYS_MAX_TRACK_NUM)) {
00112                             /* This item is FLAC file. */
00113                             p_item = &p_info->track_list[p_info->total_track];
00114                             chk = regist_item(p_item, p_name, i);
00115                             if (chk == true) {
00116                                 /* Register of file item was success. */
00117                                 p_info->total_track++;
00118                             }
00119                         }
00120                     }
00121                 }
00122             }
00123         }
00124         /* Changes the identifier of the root directory to use fopen(). */
00125         (void) regist_item(&p_info->folder_list[0], STR_ROOT_FOR_FOPEN, FOLD_ID_NOT_EXIST);
00126 
00127         if (p_info->total_track > 0u) {
00128             ret = true;
00129         }
00130     }
00131 
00132     return ret;
00133 }
00134 
00135 FILE *fid_open_track(fid_scan_folder_t * const p_info, const uint32_t track_id)
00136 {
00137     FILE            *fp = NULL;
00138     const char_t    *p_path;
00139     size_t          path_len;
00140 
00141     if (p_info != NULL) {
00142         if (track_id < p_info->total_track) {
00143             p_path = get_full_path(p_info, &p_info->track_list[track_id]);
00144             if (p_path != NULL) {
00145                 path_len = strlen(p_path); 
00146                 /* File path maximum length is limited by the specification of "fopen". */
00147                 if (path_len < FILE_PATH_MAX_SIZE) {
00148                     fp = fopen(p_path, OPEN_MODE_READ_ONLY);
00149                 }
00150             }
00151         }
00152     }
00153     return fp;
00154 }
00155 
00156 void fid_close_track(FILE * const fp)
00157 {
00158     if (fp != NULL) {
00159         (void) fclose(fp);
00160     }
00161 }
00162 
00163 const char_t *fid_get_track_name(const fid_scan_folder_t * const p_info, 
00164                                                 const uint32_t track_id)
00165 {
00166     const char_t    *p_name = NULL;
00167 
00168     if (p_info != NULL) {
00169         if (track_id < p_info->total_track) {
00170             p_name = &p_info->track_list[track_id].name[0];
00171         }
00172     }
00173     return p_name;
00174 }
00175 
00176 uint32_t fid_get_total_track(const fid_scan_folder_t * const p_info)
00177 {
00178     uint32_t        ret = 0u;
00179 
00180     if (p_info != NULL) {
00181         ret = p_info->total_track;
00182     }
00183     return ret;
00184 }
00185 
00186 /** Gets the full path
00187  *
00188  *  @param p_info Pointer to the control data of folder scan module.
00189  *  @param p_item Pointer to the item structure of the folder / track.
00190  *
00191  *  @returns 
00192  *    Pointer to the full path.
00193  */
00194 static const char_t *get_full_path(fid_scan_folder_t * const p_info, 
00195                                         const item_t * const p_item)
00196 {
00197     const char_t    *p_path = NULL;
00198     const item_t    *p;
00199     const item_t    *item_list[SYS_MAX_FOLDER_DEPTH];
00200     uint32_t        i;
00201     uint32_t        item_cnt;
00202     uint32_t        buf_cnt;
00203     uint32_t        len;
00204     bool            err;
00205 
00206     if ((p_info != NULL) && (p_item != NULL)) {
00207         for (i = 0; i < SYS_MAX_FOLDER_DEPTH; i++) {
00208             item_list[i] = NULL;
00209         }
00210         p_info->work_buf[0] = '\0';
00211 
00212         /* Stores the item name until the root folder. */
00213         p = p_item;
00214         item_cnt = 0;
00215         while ((item_cnt < SYS_MAX_FOLDER_DEPTH) && 
00216                (p->parent_number < p_info->total_folder)) {
00217             item_list[item_cnt] = p;
00218             item_cnt++;
00219             p = &p_info->folder_list[p->parent_number];
00220         } 
00221         if (p->parent_number == FOLD_ID_NOT_EXIST) {
00222             buf_cnt = strlen(p->name);
00223             (void) strncpy(&p_info->work_buf[0], p->name, sizeof(p_info->work_buf));
00224             err = false;
00225             while ((item_cnt > 0u) && (err != true)) {
00226                 item_cnt--;
00227                 p = item_list[item_cnt];
00228                 /* Concatenates SOLIDUS character to the "work_buf" variable. */
00229                 if ((buf_cnt + 1u) < sizeof(p_info->work_buf)) {
00230                     p_info->work_buf[buf_cnt] = CHR_SOLIDUS;
00231                     buf_cnt++;
00232                 } else {
00233                     err = true;
00234                 }
00235                 /* Concatenates the item name to the "work_buf" variable. */
00236                 if (p != NULL) {
00237                     len = strlen(p->name);
00238                     if ((buf_cnt + len) < sizeof(p_info->work_buf)) {
00239                         (void) strncpy(&p_info->work_buf[buf_cnt], p->name, len);
00240                         buf_cnt += len;
00241                     } else {
00242                         err = true;
00243                     }
00244                 }
00245             }
00246             if (err != true) {
00247                 p_info->work_buf[buf_cnt] = '\0';
00248                 p_path = &p_info->work_buf[0];
00249             }
00250         }
00251     }
00252     return p_path;
00253 }
00254 
00255 /** Opens the directory
00256  *
00257  *  @param p_info Pointer to the control data of folder scan module.
00258  *  @param p_item Pointer to the item structure of the folder / track.
00259  *  @param p_fdir Pointer to the structure to store the directory object.
00260  *
00261  *  @returns 
00262  *    Results of process. true is success. false is failure.
00263  */
00264 static bool open_dir(fid_scan_folder_t * const p_info, 
00265                         const item_t * const p_item, FATFS_DIR * const p_fdir)
00266 {
00267     bool            ret = false;
00268     const char_t    *p_path;
00269     FRESULT         ferr;
00270 
00271     if ((p_info != NULL) && (p_item != NULL) && (p_fdir != NULL)) {
00272         p_path = get_full_path(p_info, p_item);
00273         if (p_path != NULL) {
00274             ferr = f_opendir(p_fdir, p_path);
00275             if (ferr == FR_OK) {
00276                 ret = true;
00277             }
00278         }
00279     }
00280     return ret;
00281 }
00282 
00283 /** Reads the directory
00284  *
00285  *  @param p_info Pointer to the control data of folder scan module.
00286  *  @param p_fdir Pointer to the structure of the directory object.
00287  *  @param p_flag_dir Pointer to the variable to store the directory flag.
00288  *
00289  *  @returns 
00290  *    Pointer to the name.
00291  */
00292 static bool read_dir(fid_scan_folder_t * const p_info, FATFS_DIR * const p_fdir, 
00293                             const char_t ** const p_name, bool * const p_flag_dir)
00294 {
00295     bool            ret = false;
00296     FRESULT         ferr;
00297     FILINFO         finfo;
00298 
00299     if ((p_info != NULL) && (p_fdir != NULL) && 
00300         (p_name != NULL) && (p_flag_dir != NULL)) {
00301         /* Sets the buffer to store the long file name. */
00302         finfo.lfname = &p_info->work_buf[0];
00303         finfo.lfsize = sizeof(p_info->work_buf);
00304         ferr = f_readdir(p_fdir, &finfo);
00305         if ((ferr == FR_OK) && ((int32_t)finfo.fname[0] != '\0')) {
00306             if (finfo.lfname != NULL) {
00307                 if ((int32_t)finfo.lfname[0] == '\0') {
00308                     /* Long file name does not exist. */
00309                     (void) strncpy(finfo.lfname, finfo.fname, finfo.lfsize);
00310                 }
00311                 /* Adds the NULL terminal character. */
00312                 /* This is fail-safe processing. */
00313                 finfo.lfname[finfo.lfsize - 1u] = '\0';
00314 
00315                 ret = true;
00316                 *p_name = finfo.lfname;
00317                 if ((finfo.fattrib & AM_DIR) != 0) {
00318                     /* This item is directory. */
00319                     *p_flag_dir = true;
00320                 } else {
00321                     /* This item is file. */
00322                     *p_flag_dir = false;
00323                 }
00324             }
00325         }
00326     }
00327     return ret;
00328 }
00329 
00330 /** Registers the item of the folder / track
00331  *
00332  *  @param p_item Pointer to the structure to store the item of the folder / track.
00333  *  @param p_name Pointer to the name of the item.
00334  *  @param parent Number of the parent folder of the item.
00335  *
00336  *  @returns 
00337  *    Results of process. true is success. false is failure.
00338  */
00339 static bool regist_item(item_t * const p_item, 
00340                             const char_t * const p_name, const uint32_t parent)
00341 {
00342     bool        ret = false;
00343     uint32_t    len;
00344 
00345     if ((p_item != NULL) && (p_name != NULL)) {
00346         len = strlen(p_name);
00347         if ((len + 1u) < sizeof(p_item->name)) {
00348             (void) strncpy(p_item->name, p_name, sizeof(p_item->name));
00349             p_item->name[sizeof(p_item->name) - 1u] = '\0';
00350             p_item->parent_number = parent;
00351             ret = true;
00352         }
00353     }
00354     return ret;
00355 }
00356 
00357 /** Checks the extension of the track name
00358  *
00359  *  @param p_name Pointer to the name of the track.
00360  *
00361  *  @returns 
00362  *    Results of the checking. true is FLAC file. false is other file.
00363  */
00364 static bool check_extension(const char_t * const p_name)
00365 {
00366     bool            ret = false;
00367     const char_t    *p;
00368 
00369     if (p_name != NULL) {
00370         p = strrchr(p_name, CHR_FULL_STOP);
00371         if (p != NULL) {
00372             if (strncasecmp(p, FILE_EXT_FLAC, sizeof(FILE_EXT_FLAC)) == 0) {
00373                 ret = true;
00374             } else if (strncasecmp(p, FILE_EXT_FLA, sizeof(FILE_EXT_FLA)) == 0) {
00375                 ret = true;
00376             } else {
00377                 /* DO NOTHING */
00378             }
00379         }
00380     }
00381     return ret;
00382 }
00383 
00384 /** Checks the folder depth in the scan range
00385  *
00386  *  @param p_info Pointer to the control data of folder scan module.
00387  *  @param folder_id Folder ID [0 - (total folder - 1)]
00388  *
00389  *  @returns 
00390  *    Results of the checking. true is the scan range. false is out of a scan range.
00391  */
00392 static bool check_folder_depth(const fid_scan_folder_t * const p_info, 
00393                                                     const uint32_t folder_id)
00394 {
00395     bool            ret = false;
00396     uint32_t        depth;
00397     uint32_t        parent_id;
00398 
00399     if (p_info != NULL) {
00400         /* Counts the folder depth. */
00401         parent_id = folder_id;
00402         depth = 0u;
00403         while ((depth < SYS_MAX_FOLDER_DEPTH) && 
00404                (parent_id < p_info->total_folder)) {
00405             depth++;
00406             parent_id = p_info->folder_list[parent_id].parent_number;
00407         } 
00408         if (parent_id == FOLD_ID_NOT_EXIST) {
00409             /* Found the root folder. */
00410             if (depth < SYS_MAX_FOLDER_DEPTH) {
00411                 ret = true;
00412             }
00413         }
00414     }
00415     return ret;
00416 }