Skip to content

Commit 262b777

Browse files
committed
Hooks for user file changes and magic file override.
1 parent c15cc70 commit 262b777

File tree

2 files changed

+148
-59
lines changed

2 files changed

+148
-59
lines changed

source/daplink/drag-n-drop/vfs_user.c

Lines changed: 87 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @brief Implementation of vfs_user.h
44
*
55
* DAPLink Interface Firmware
6-
* Copyright (c) 2009-2019, ARM Limited, All Rights Reserved
6+
* Copyright (c) 2009-2020, ARM Limited, All Rights Reserved
77
* SPDX-License-Identifier: Apache-2.0
88
*
99
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -23,6 +23,7 @@
2323
#include "ctype.h"
2424
#include "string.h"
2525

26+
#include "vfs_user.h"
2627
#include "vfs_manager.h"
2728
#include "macro.h"
2829
#include "error.h"
@@ -168,9 +169,28 @@ void vfs_user_build_filesystem()
168169
}
169170
}
170171

172+
// Default file change hook.
173+
__WEAK bool vfs_user_file_change_handler_hook(const vfs_filename_t filename, vfs_file_change_t change,
174+
vfs_file_t file, vfs_file_t new_file_data)
175+
{
176+
return false;
177+
}
178+
179+
// Default magic file hook.
180+
__WEAK bool vfs_user_magic_file_hook(const vfs_filename_t filename, bool *do_remount)
181+
{
182+
return false;
183+
}
184+
171185
// Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback
172186
void vfs_user_file_change_handler(const vfs_filename_t filename, vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data)
173187
{
188+
// Call file changed hook. If it returns true, then it handled the request and we have nothing
189+
// more to do.
190+
if (vfs_user_file_change_handler_hook(filename, change, file, new_file_data)) {
191+
return;
192+
}
193+
174194
// Allow settings to be changed if automation mode is
175195
// enabled or if the user is holding the reset button
176196
bool btn_pressed = gpio_get_reset_btn();
@@ -183,73 +203,81 @@ void vfs_user_file_change_handler(const vfs_filename_t filename, vfs_file_change
183203
// Unused
184204
}
185205

186-
if (VFS_FILE_CREATED == change) {
206+
else if (VFS_FILE_CREATED == change) {
207+
bool do_remount = true; // Almost all magic files cause a remount.
187208
int32_t which_magic_file = -1;
188209

189-
// Compare the new file's name to our table of magic filenames.
190-
for (int32_t i = 0; i < ARRAY_SIZE(s_magic_file_info); ++i) {
191-
if (!memcmp(filename, s_magic_file_info[i].name, sizeof(vfs_filename_t))) {
192-
which_magic_file = i;
210+
// Let the hook examine the filename. If it returned false then look for the standard
211+
// magic files.
212+
if (!vfs_user_magic_file_hook(filename, &do_remount)) {
213+
// Compare the new file's name to our table of magic filenames.
214+
for (int32_t i = 0; i < ARRAY_SIZE(s_magic_file_info); ++i) {
215+
if (!memcmp(filename, s_magic_file_info[i].name, sizeof(vfs_filename_t))) {
216+
which_magic_file = i;
217+
}
193218
}
194-
}
195-
196-
// Check if we matched a magic filename and handle it.
197-
if (which_magic_file != -1) {
198-
bool do_remount = true; // Almost all magic files cause a remount.
199-
200-
switch (which_magic_file) {
201-
case kDAPLinkModeActionFile:
202-
if (daplink_is_interface()) {
203-
config_ram_set_hold_in_bl(true);
204-
} else {
205-
// Do nothing - bootloader will go to interface by default
206-
}
207-
break;
208-
case kTestAssertActionFile:
209-
// Test asserts
210-
util_assert(0);
211-
do_remount = false;
212-
break;
213-
case kRefreshActionFile:
214-
// Remount to update the drive
215-
break;
216-
case kEraseActionFile:
217-
erase_target();
218-
break;
219-
case kAutoResetConfigFile:
220-
config_set_auto_rst(true);
221-
break;
222-
case kHardResetConfigFile:
223-
config_set_auto_rst(false);
224-
break;
225-
case kAutomationOnConfigFile:
226-
config_set_automation_allowed(true);
227-
break;
228-
case kAutomationOffConfigFile:
229-
config_set_automation_allowed(false);
230-
break;
231-
case kOverflowOnConfigFile:
232-
config_set_overflow_detect(true);
233-
break;
234-
case kOverflowOffConfigFile:
235-
config_set_overflow_detect(false);
236-
break;
237-
case kMSDOnConfigFile:
238-
config_ram_set_disable_msd(false);
239-
break;
240-
case kMSDOffConfigFile:
241-
config_ram_set_disable_msd(true);
242-
break;
243219

220+
// Check if we matched a magic filename and handle it.
221+
if (which_magic_file != -1) {
222+
switch (which_magic_file) {
223+
case kDAPLinkModeActionFile:
224+
if (daplink_is_interface()) {
225+
config_ram_set_hold_in_bl(true);
226+
} else {
227+
// Do nothing - bootloader will go to interface by default
228+
}
229+
break;
230+
case kTestAssertActionFile:
231+
// Test asserts
232+
util_assert(0);
233+
do_remount = false;
234+
break;
235+
case kRefreshActionFile:
236+
// Remount to update the drive
237+
break;
238+
case kEraseActionFile:
239+
erase_target();
240+
break;
241+
case kAutoResetConfigFile:
242+
config_set_auto_rst(true);
243+
break;
244+
case kHardResetConfigFile:
245+
config_set_auto_rst(false);
246+
break;
247+
case kAutomationOnConfigFile:
248+
config_set_automation_allowed(true);
249+
break;
250+
case kAutomationOffConfigFile:
251+
config_set_automation_allowed(false);
252+
break;
253+
case kOverflowOnConfigFile:
254+
config_set_overflow_detect(true);
255+
break;
256+
case kOverflowOffConfigFile:
257+
config_set_overflow_detect(false);
258+
break;
259+
case kMSDOnConfigFile:
260+
config_ram_set_disable_msd(false);
261+
break;
262+
case kMSDOffConfigFile:
263+
config_ram_set_disable_msd(true);
264+
break;
265+
default:
266+
util_assert(false);
267+
}
244268
}
245-
246-
if (do_remount) {
247-
vfs_mngr_fs_remount();
269+
else {
270+
do_remount = false;
248271
}
249272
}
273+
274+
// Remount if requested.
275+
if (do_remount) {
276+
vfs_mngr_fs_remount();
277+
}
250278
}
251279

252-
if (VFS_FILE_DELETED == change) {
280+
else if (VFS_FILE_DELETED == change) {
253281
if (!memcmp(filename, assert_file, sizeof(vfs_filename_t))) {
254282
// Clear assert and remount to update the drive
255283
util_assert_clear();
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* @file vfs_user.h
3+
* @brief VFS user files header.
4+
*
5+
* DAPLink Interface Firmware
6+
* Copyright (c) 2020, ARM Limited, All Rights Reserved
7+
* SPDX-License-Identifier: Apache-2.0
8+
*
9+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
10+
* not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
*/
21+
22+
#ifndef VFS_USER_H
23+
#define VFS_USER_H
24+
25+
#include <stdbool.h>
26+
#include "virtual_fs.h"
27+
28+
#ifdef __cplusplus
29+
extern "C" {
30+
#endif
31+
32+
//! @brief Hook for file changes in root directory.
33+
//!
34+
//! @param filename Name of the file that has changed.
35+
//! @param change Type of change.
36+
//! @param file
37+
//! @param new_file_data Data being written to the file if _change_ is #VFS_FILE_CHANGED.
38+
//! @retval true The hook handled the change notification, the caller should do nothing else.
39+
//! @retval false The hook did nothing, continue with normal behaviour.
40+
bool vfs_user_file_change_handler_hook(const vfs_filename_t filename,
41+
vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data);
42+
43+
//! @brief Hook for magic files.
44+
//!
45+
//! This hook is intended to simplify checking for magic files. In addition to allowing support for
46+
//! new magic files, you can also change the behaviour of or disable standard magic files.
47+
//!
48+
//! @param filename Name of the file that was created.
49+
//! @param[out] do_remount Whether the caller should remount the MSD volume. Only applies if true
50+
//! is returned. The default is true, so if the hook does not modify this parameter and returns
51+
//! true, a remount is performed.
52+
//! @retval true The hook handled the specified file. A remount will be performed if requested,
53+
//! but otherwise no other standard behaviour is applied.
54+
//! @retval false The hook did not handle the file; continue with canonical behaviour.
55+
bool vfs_user_magic_file_hook(const vfs_filename_t filename, bool *do_remount);
56+
57+
#ifdef __cplusplus
58+
}
59+
#endif
60+
61+
#endif // VFS_USER_H

0 commit comments

Comments
 (0)