Skip to content

Commit 2b61b1f

Browse files
committed
Hooks for user file changes and magic file override.
1 parent 18fa963 commit 2b61b1f

File tree

2 files changed

+147
-59
lines changed

2 files changed

+147
-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"
@@ -169,9 +170,28 @@ void vfs_user_build_filesystem()
169170
}
170171
}
171172

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

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

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

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

253-
if (VFS_FILE_DELETED == change) {
281+
else if (VFS_FILE_DELETED == change) {
254282
if (!memcmp(filename, assert_file, sizeof(vfs_filename_t))) {
255283
// Clear assert and remount to update the drive
256284
util_assert_clear();
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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 "virtual_fs.h"
26+
27+
#ifdef __cplusplus
28+
extern "C" {
29+
#endif
30+
31+
//! @brief Hook for file changes in root directory.
32+
//!
33+
//! @param filename Name of the file that has changed.
34+
//! @param change Type of change.
35+
//! @param file
36+
//! @param new_file_data Data being written to the file if _change_ is #VFS_FILE_CHANGED.
37+
//! @retval true The hook handled the change notification, the caller should do nothing else.
38+
//! @retval false The hook did nothing, continue with normal behaviour.
39+
__WEAK bool vfs_user_file_change_handler_hook(const vfs_filename_t filename,
40+
vfs_file_change_t change, vfs_file_t file, vfs_file_t new_file_data);
41+
42+
//! @brief Hook for magic files.
43+
//!
44+
//! This hook is intended to simplify checking for magic files. In addition to allowing support for
45+
//! new magic files, you can also change the behaviour of or disable standard magic files.
46+
//!
47+
//! @param filename Name of the file that was created.
48+
//! @param[out] do_remount Whether the caller should remount the MSD volume. Only applies if true
49+
//! is returned. The default is true, so if the hook does not modify this parameter and returns
50+
//! true, a remount is performed.
51+
//! @retval true The hook handled the specified file. A remount will be performed if requested,
52+
//! but otherwise no other standard behaviour is applied.
53+
//! @retval false The hook did not handle the file; continue with canonical behaviour.
54+
__WEAK bool vfs_user_magic_file_hook(const vfs_filename_t filename, bool *do_remount);
55+
56+
#ifdef __cplusplus
57+
}
58+
#endif
59+
60+
#endif // VFS_USER_H

0 commit comments

Comments
 (0)