diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/rbpaths.c | 117 | ||||
-rw-r--r-- | firmware/export/config/samsungypr0.h | 8 | ||||
-rw-r--r-- | firmware/export/mv.h | 1 | ||||
-rw-r--r-- | firmware/export/rbpaths.h | 5 | ||||
-rw-r--r-- | firmware/include/file.h | 2 | ||||
-rw-r--r-- | firmware/target/hosted/samsungypr/ypr0/system-ypr0.c | 165 |
6 files changed, 267 insertions, 31 deletions
diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c index 8efb6dd238..dba39476fc 100644 --- a/firmware/common/rbpaths.c +++ b/firmware/common/rbpaths.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #undef rmdir | 48 | #undef rmdir |
49 | #undef dirent | 49 | #undef dirent |
50 | #undef DIR | 50 | #undef DIR |
51 | #undef readlink | ||
51 | 52 | ||
52 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | 53 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) |
53 | static const char rbhome[] = "/sdcard"; | 54 | static const char rbhome[] = "/sdcard"; |
@@ -61,6 +62,9 @@ const char *rbhome; | |||
61 | * over the ones where Rockbox is installed to. Classic example would be | 62 | * over the ones where Rockbox is installed to. Classic example would be |
62 | * $HOME/.config/rockbox.org vs /usr/share/rockbox */ | 63 | * $HOME/.config/rockbox.org vs /usr/share/rockbox */ |
63 | #define HAVE_SPECIAL_DIRS | 64 | #define HAVE_SPECIAL_DIRS |
65 | #define IS_HOME(p) (!strcmp(p, rbhome)) | ||
66 | #else | ||
67 | #define IS_HOME(p) (!strcmp(p, HOME_DIR)) | ||
64 | #endif | 68 | #endif |
65 | 69 | ||
66 | /* flags for get_user_file_path() */ | 70 | /* flags for get_user_file_path() */ |
@@ -70,6 +74,35 @@ const char *rbhome; | |||
70 | /* file or directory? */ | 74 | /* file or directory? */ |
71 | #define IS_FILE (1<<1) | 75 | #define IS_FILE (1<<1) |
72 | 76 | ||
77 | #ifdef HAVE_MULTIDRIVE | ||
78 | /* A special link is created under e.g. HOME_DIR/<microSD1>, e.g. to access | ||
79 | * external storage in a convinient location, much similar to the mount | ||
80 | * point on our native targets. Here they are treated as symlink (one which | ||
81 | * doesn't actually exist in the filesystem and therefore we have to override | ||
82 | * readlink() */ | ||
83 | static const char *handle_special_links(const char* link, unsigned flags, | ||
84 | char *buf, const size_t bufsize) | ||
85 | { | ||
86 | (void) flags; | ||
87 | char vol_string[VOL_ENUM_POS + 8]; | ||
88 | int len = sprintf(vol_string, VOL_NAMES, 1); | ||
89 | |||
90 | /* link might be passed with or without HOME_DIR expanded. To handle | ||
91 | * both perform substring matching (VOL_NAMES is unique enough) */ | ||
92 | const char *begin = strstr(link, vol_string); | ||
93 | if (begin) | ||
94 | { | ||
95 | /* begin now points to the start of vol_string within link, | ||
96 | * we want to copy the remainder of the paths, prefixed by | ||
97 | * the actual mount point (the remainder might be "") */ | ||
98 | snprintf(buf, bufsize, MULTIDRIVE_DIR"%s", begin + len); | ||
99 | return buf; | ||
100 | } | ||
101 | |||
102 | return link; | ||
103 | } | ||
104 | #endif | ||
105 | |||
73 | #ifdef HAVE_SPECIAL_DIRS | 106 | #ifdef HAVE_SPECIAL_DIRS |
74 | void paths_init(void) | 107 | void paths_init(void) |
75 | { | 108 | { |
@@ -156,38 +189,31 @@ static const char* _get_user_file_path(const char *path, | |||
156 | return ret; | 189 | return ret; |
157 | } | 190 | } |
158 | 191 | ||
192 | #elif !defined(paths_init) | ||
193 | void paths_init(void) { } | ||
194 | #endif | ||
159 | 195 | ||
160 | static const char* handle_special_dirs(const char* dir, unsigned flags, | 196 | static const char* handle_special_dirs(const char* dir, unsigned flags, |
161 | char *buf, const size_t bufsize) | 197 | char *buf, const size_t bufsize) |
162 | { | 198 | { |
199 | (void) flags; (void) buf; (void) bufsize; | ||
200 | #ifdef HAVE_SPECIAL_DIRS | ||
163 | if (!strncmp(HOME_DIR, dir, HOME_DIR_LEN)) | 201 | if (!strncmp(HOME_DIR, dir, HOME_DIR_LEN)) |
164 | { | 202 | { |
165 | const char *p = dir + HOME_DIR_LEN; | 203 | const char *p = dir + HOME_DIR_LEN; |
166 | while (*p == '/') p++; | 204 | while (*p == '/') p++; |
167 | snprintf(buf, bufsize, "%s/%s", rbhome, p); | 205 | snprintf(buf, bufsize, "%s/%s", rbhome, p); |
168 | return buf; | 206 | dir = buf; |
169 | } | 207 | } |
170 | else if (!strncmp(ROCKBOX_DIR, dir, ROCKBOX_DIR_LEN)) | 208 | else if (!strncmp(ROCKBOX_DIR, dir, ROCKBOX_DIR_LEN)) |
171 | return _get_user_file_path(dir, flags, buf, bufsize); | 209 | dir = _get_user_file_path(dir, flags, buf, bufsize); |
172 | 210 | #endif | |
173 | return dir; | 211 | #ifdef HAVE_MULTIDRIVE |
174 | } | 212 | dir = handle_special_links(dir, flags, buf, bufsize); |
175 | |||
176 | #else /* !HAVE_SPECIAL_DIRS */ | ||
177 | |||
178 | #ifndef paths_init | ||
179 | void paths_init(void) { } | ||
180 | #endif | 213 | #endif |
181 | |||
182 | static const char* handle_special_dirs(const char* dir, unsigned flags, | ||
183 | char *buf, const size_t bufsize) | ||
184 | { | ||
185 | (void) flags; (void) buf; (void) bufsize; | ||
186 | return dir; | 214 | return dir; |
187 | } | 215 | } |
188 | 216 | ||
189 | #endif | ||
190 | |||
191 | int app_open(const char *name, int o, ...) | 217 | int app_open(const char *name, int o, ...) |
192 | { | 218 | { |
193 | char realpath[MAX_PATH]; | 219 | char realpath[MAX_PATH]; |
@@ -235,6 +261,7 @@ int app_rename(const char *old, const char *new) | |||
235 | * get_dir_info() */ | 261 | * get_dir_info() */ |
236 | struct __dir { | 262 | struct __dir { |
237 | DIR *dir; | 263 | DIR *dir; |
264 | IF_MD(int volumes_returned); | ||
238 | char path[]; | 265 | char path[]; |
239 | }; | 266 | }; |
240 | 267 | ||
@@ -246,23 +273,31 @@ struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir) | |||
246 | struct dirinfo ret; | 273 | struct dirinfo ret; |
247 | char path[MAX_PATH]; | 274 | char path[MAX_PATH]; |
248 | 275 | ||
249 | snprintf(path, sizeof(path), "%s/%s", parent->path, dir->d_name); | ||
250 | memset(&ret, 0, sizeof(ret)); | 276 | memset(&ret, 0, sizeof(ret)); |
251 | 277 | ||
278 | #ifdef HAVE_MULTIDRIVE | ||
279 | char vol_string[VOL_ENUM_POS + 8]; | ||
280 | sprintf(vol_string, VOL_NAMES, 1); | ||
281 | if (!strcmp(vol_string, dir->d_name)) | ||
282 | { | ||
283 | ret.attribute = ATTR_LINK; | ||
284 | strcpy(path, MULTIDRIVE_DIR); | ||
285 | } | ||
286 | else | ||
287 | #endif | ||
288 | snprintf(path, sizeof(path), "%s/%s", parent->path, dir->d_name); | ||
289 | |||
252 | if (!stat(path, &s)) | 290 | if (!stat(path, &s)) |
253 | { | 291 | { |
254 | if (S_ISDIR(s.st_mode)) | 292 | if (S_ISDIR(s.st_mode)) |
255 | { | 293 | ret.attribute |= ATTR_DIRECTORY; |
256 | ret.attribute = ATTR_DIRECTORY; | 294 | |
257 | } | ||
258 | ret.size = s.st_size; | 295 | ret.size = s.st_size; |
259 | tm = localtime(&(s.st_mtime)); | 296 | tm = localtime(&(s.st_mtime)); |
260 | } | 297 | } |
261 | 298 | ||
262 | if (!lstat(path, &s) && S_ISLNK(s.st_mode)) | 299 | if (!lstat(path, &s) && S_ISLNK(s.st_mode)) |
263 | { | ||
264 | ret.attribute |= ATTR_LINK; | 300 | ret.attribute |= ATTR_LINK; |
265 | } | ||
266 | 301 | ||
267 | if (tm) | 302 | if (tm) |
268 | { | 303 | { |
@@ -296,6 +331,7 @@ DIR* app_opendir(const char *_name) | |||
296 | free(buf); | 331 | free(buf); |
297 | return NULL; | 332 | return NULL; |
298 | } | 333 | } |
334 | IF_MD(this->volumes_returned = 0); | ||
299 | return (DIR*)this; | 335 | return (DIR*)this; |
300 | } | 336 | } |
301 | 337 | ||
@@ -311,6 +347,18 @@ int app_closedir(DIR *dir) | |||
311 | struct dirent* app_readdir(DIR* dir) | 347 | struct dirent* app_readdir(DIR* dir) |
312 | { | 348 | { |
313 | struct __dir *d = (struct __dir*)dir; | 349 | struct __dir *d = (struct __dir*)dir; |
350 | #ifdef HAVE_MULTIDRIVE | ||
351 | /* this is not MT-safe but OK according to man readdir */ | ||
352 | static struct dirent voldir; | ||
353 | if (d->volumes_returned < (NUM_VOLUMES-1) | ||
354 | && volume_present(d->volumes_returned+1) | ||
355 | && IS_HOME(d->path)) | ||
356 | { | ||
357 | d->volumes_returned += 1; | ||
358 | sprintf(voldir.d_name, VOL_NAMES, d->volumes_returned); | ||
359 | return &voldir; | ||
360 | } | ||
361 | #endif | ||
314 | return readdir(d->dir); | 362 | return readdir(d->dir); |
315 | } | 363 | } |
316 | 364 | ||
@@ -329,3 +377,26 @@ int app_rmdir(const char* name) | |||
329 | const char *fname = handle_special_dirs(name, NEED_WRITE, realpath, sizeof(realpath)); | 377 | const char *fname = handle_special_dirs(name, NEED_WRITE, realpath, sizeof(realpath)); |
330 | return rmdir(fname); | 378 | return rmdir(fname); |
331 | } | 379 | } |
380 | |||
381 | |||
382 | /* On MD we create a virtual symlink for the external drive, | ||
383 | * for this we need to override readlink(). */ | ||
384 | ssize_t app_readlink(const char *path, char *buf, size_t bufsiz) | ||
385 | { | ||
386 | char _buf[MAX_PATH]; | ||
387 | (void) path; (void) buf; (void) bufsiz; | ||
388 | path = handle_special_dirs(path, 0, _buf, sizeof(_buf)); | ||
389 | #ifdef HAVE_MULTIDRIVE | ||
390 | /* if path == _buf then we can be sure handle_special_dir() did something | ||
391 | * and path is not an ordinary directory */ | ||
392 | if (path == _buf && !strncmp(path, MULTIDRIVE_DIR, sizeof(MULTIDRIVE_DIR)-1)) | ||
393 | { | ||
394 | /* copying NUL is not required as per readlink specification */ | ||
395 | ssize_t len = strlen(path); | ||
396 | memcpy(buf, path, len); | ||
397 | return len; | ||
398 | } | ||
399 | #endif | ||
400 | /* does not append NUL !! */ | ||
401 | return readlink(path, buf, bufsiz); | ||
402 | } | ||
diff --git a/firmware/export/config/samsungypr0.h b/firmware/export/config/samsungypr0.h index 361c9697c5..bed5a2f977 100644 --- a/firmware/export/config/samsungypr0.h +++ b/firmware/export/config/samsungypr0.h | |||
@@ -161,6 +161,10 @@ | |||
161 | /* This folder resides in the ReadOnly CRAMFS. It is binded to /mnt/media0/.rockbox */ | 161 | /* This folder resides in the ReadOnly CRAMFS. It is binded to /mnt/media0/.rockbox */ |
162 | #define BOOTDIR "/.rockbox" | 162 | #define BOOTDIR "/.rockbox" |
163 | 163 | ||
164 | /* No special storage */ | 164 | /* External SD card can be mounted */ |
165 | #define CONFIG_STORAGE STORAGE_HOSTFS | 165 | #define CONFIG_STORAGE (STORAGE_HOSTFS|STORAGE_SD) |
166 | #define HAVE_MULTIDRIVE | ||
167 | #define NUM_DRIVES 2 | ||
168 | #define HAVE_HOTSWAP | ||
166 | #define HAVE_STORAGE_FLUSH | 169 | #define HAVE_STORAGE_FLUSH |
170 | #define MULTIDRIVE_DIR "/mnt/mmc" | ||
diff --git a/firmware/export/mv.h b/firmware/export/mv.h index 05c9c6349f..1d0a536663 100644 --- a/firmware/export/mv.h +++ b/firmware/export/mv.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #ifndef __MV_H__ | 22 | #ifndef __MV_H__ |
23 | #define __MV_H__ | 23 | #define __MV_H__ |
24 | 24 | ||
25 | #include <stdbool.h> | ||
25 | #include "config.h" | 26 | #include "config.h" |
26 | 27 | ||
27 | /* FixMe: These macros are a bit nasty and perhaps misplaced here. | 28 | /* FixMe: These macros are a bit nasty and perhaps misplaced here. |
diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h index 0a5b36c5ab..1f7e1a2643 100644 --- a/firmware/export/rbpaths.h +++ b/firmware/export/rbpaths.h | |||
@@ -60,7 +60,6 @@ | |||
60 | #else /* APPLICATION */ | 60 | #else /* APPLICATION */ |
61 | 61 | ||
62 | #define HOME_DIR "<HOME>" /* replaced at runtime */ | 62 | #define HOME_DIR "<HOME>" /* replaced at runtime */ |
63 | #define HOME_DIR_LEN (sizeof(HOME_DIR)-1) | ||
64 | 63 | ||
65 | #define PLUGIN_DIR ROCKBOX_LIBRARY_PATH "/rockbox/rocks" | 64 | #define PLUGIN_DIR ROCKBOX_LIBRARY_PATH "/rockbox/rocks" |
66 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) | 65 | #if (CONFIG_PLATFORM & PLATFORM_ANDROID) |
@@ -73,10 +72,13 @@ extern void paths_init(void); | |||
73 | 72 | ||
74 | #endif /* !APPLICATION || SAMSUNG_YPR0 */ | 73 | #endif /* !APPLICATION || SAMSUNG_YPR0 */ |
75 | 74 | ||
75 | #define HOME_DIR_LEN (sizeof(HOME_DIR)-1) | ||
76 | |||
76 | #ifdef APPLICATION | 77 | #ifdef APPLICATION |
77 | 78 | ||
78 | #include <dirent.h> | 79 | #include <dirent.h> |
79 | #include <fcntl.h> | 80 | #include <fcntl.h> |
81 | #include <unistd.h> | ||
80 | 82 | ||
81 | int app_open(const char *name, int o, ...); | 83 | int app_open(const char *name, int o, ...); |
82 | int app_creat(const char* name, mode_t mode); | 84 | int app_creat(const char* name, mode_t mode); |
@@ -87,6 +89,7 @@ int app_closedir(DIR *dir); | |||
87 | struct dirent* app_readdir(DIR* dir); | 89 | struct dirent* app_readdir(DIR* dir); |
88 | int app_mkdir(const char* name); | 90 | int app_mkdir(const char* name); |
89 | int app_rmdir(const char* name); | 91 | int app_rmdir(const char* name); |
92 | ssize_t app_readlink(const char *path, char *buf, size_t bufsiz); | ||
90 | 93 | ||
91 | #endif | 94 | #endif |
92 | 95 | ||
diff --git a/firmware/include/file.h b/firmware/include/file.h index 9b7f123999..77930864c7 100644 --- a/firmware/include/file.h +++ b/firmware/include/file.h | |||
@@ -43,6 +43,7 @@ | |||
43 | # define creat(x,m) app_creat(x, m) | 43 | # define creat(x,m) app_creat(x, m) |
44 | # define remove(x) app_remove(x) | 44 | # define remove(x) app_remove(x) |
45 | # define rename(x,y) app_rename(x,y) | 45 | # define rename(x,y) app_rename(x,y) |
46 | # define readlink(x,y,z) app_readlink(x,y,z) | ||
46 | # if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) | 47 | # if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) |
47 | /* SDL overrides a few more */ | 48 | /* SDL overrides a few more */ |
48 | # define read(x,y,z) sim_read(x,y,z) | 49 | # define read(x,y,z) sim_read(x,y,z) |
@@ -59,6 +60,7 @@ | |||
59 | # define read(x,y,z) sim_read(x,y,z) | 60 | # define read(x,y,z) sim_read(x,y,z) |
60 | # define write(x,y,z) sim_write(x,y,z) | 61 | # define write(x,y,z) sim_write(x,y,z) |
61 | # define close(x) sim_close(x) | 62 | # define close(x) sim_close(x) |
63 | /* readlink() not used in the sim yet */ | ||
62 | extern int sim_open(const char *name, int o, ...); | 64 | extern int sim_open(const char *name, int o, ...); |
63 | extern int sim_creat(const char *name, mode_t mode); | 65 | extern int sim_creat(const char *name, mode_t mode); |
64 | #endif | 66 | #endif |
diff --git a/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c b/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c index 477b71c6a2..893c710861 100644 --- a/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c +++ b/firmware/target/hosted/samsungypr/ypr0/system-ypr0.c | |||
@@ -19,16 +19,26 @@ | |||
19 | ****************************************************************************/ | 19 | ****************************************************************************/ |
20 | 20 | ||
21 | #include <stdlib.h> | 21 | #include <stdlib.h> |
22 | #include <string.h> | ||
23 | #include <inttypes.h> | 22 | #include <inttypes.h> |
24 | #include <unistd.h> | 23 | #include <unistd.h> |
24 | #include <sys/mount.h> | ||
25 | #include <errno.h> | ||
26 | |||
25 | #include "system.h" | 27 | #include "system.h" |
28 | #include "kernel.h" | ||
29 | #include "thread.h" | ||
30 | |||
31 | #include "string-extra.h" | ||
26 | #include "panic.h" | 32 | #include "panic.h" |
27 | #include "debug.h" | 33 | #include "debug.h" |
28 | #include "hostfs.h" | 34 | #include "storage.h" |
29 | 35 | #include "mv.h" | |
30 | #include "ascodec.h" | 36 | #include "ascodec.h" |
31 | #include "gpio-ypr.h" | 37 | #include "gpio-ypr.h" |
38 | #include "ascodec.h" | ||
39 | #include "backlight.h" | ||
40 | #include "rbunicode.h" | ||
41 | #include "logdiskf.h" | ||
32 | 42 | ||
33 | void power_off(void) | 43 | void power_off(void) |
34 | { | 44 | { |
@@ -61,15 +71,160 @@ void system_exception_wait(void) | |||
61 | system_reboot(); | 71 | system_reboot(); |
62 | } | 72 | } |
63 | 73 | ||
74 | /* MicroSD card removal / insertion management */ | ||
75 | |||
76 | bool hostfs_removable(IF_MD_NONVOID(int drive)) | ||
77 | { | ||
78 | #ifdef HAVE_MULTIDRIVE | ||
79 | if (drive > 0) /* Active LOW */ | ||
80 | return true; | ||
81 | else | ||
82 | #endif | ||
83 | return false; /* internal: always present */ | ||
84 | } | ||
85 | |||
86 | bool hostfs_present(IF_MD_NONVOID(int drive)) | ||
87 | { | ||
88 | #ifdef HAVE_MULTIDRIVE | ||
89 | if (drive > 0) /* Active LOW */ | ||
90 | return (!gpio_control(DEV_CTRL_GPIO_IS_HIGH, GPIO_SD_SENSE, 0, 0)); | ||
91 | else | ||
92 | #endif | ||
93 | return true; /* internal: always present */ | ||
94 | } | ||
95 | |||
96 | #ifdef HAVE_HOTSWAP | ||
97 | bool volume_removable(int volume) | ||
98 | { | ||
99 | /* don't support more than one partition yet, so volume == drive */ | ||
100 | return hostfs_removable(volume); | ||
101 | } | ||
102 | |||
103 | bool volume_present(int volume) | ||
104 | { | ||
105 | /* don't support more than one partition yet, so volume == drive */ | ||
106 | return hostfs_present(volume); | ||
107 | } | ||
108 | #endif | ||
109 | |||
110 | static int unmount_sd(void) | ||
111 | { | ||
112 | int ret; | ||
113 | do | ||
114 | { | ||
115 | ret = umount("/mnt/mmc"); | ||
116 | } while (ret && errno != EBUSY && errno != EINVAL); | ||
117 | |||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int mount_sd(void) | ||
122 | { | ||
123 | int ret; | ||
124 | /* kludge to make sure we get our wanted mount flags. This is needed | ||
125 | * when the sd was already mounted before we booted */ | ||
126 | unmount_sd(); | ||
127 | char iocharset[64] = "iocharset="; | ||
128 | strlcat(iocharset, get_current_codepage_name_linux(), sizeof(iocharset)); | ||
129 | ret = mount("/dev/mmcblk0p1", "/mnt/mmc", "vfat", | ||
130 | MS_MGC_VAL | MS_SYNCHRONOUS | MS_RELATIME, | ||
131 | iocharset); | ||
132 | /* failure probably means the kernel does not support the iocharset. | ||
133 | * retry without to load the default */ | ||
134 | if (ret == -1) | ||
135 | ret = mount("/dev/mmcblk0p1", "/mnt/mmc", "vfat", | ||
136 | MS_MGC_VAL | MS_SYNCHRONOUS | MS_RELATIME, NULL); | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | #ifdef HAVE_HOTSWAP | ||
141 | |||
142 | static int sd_thread_stack[DEFAULT_STACK_SIZE]; | ||
143 | |||
144 | enum { | ||
145 | STATE_POLL, | ||
146 | STATE_DEBOUNCE, | ||
147 | STATE_MOUNT, | ||
148 | }; | ||
149 | |||
150 | static void NORETURN_ATTR sd_thread(void) | ||
151 | { | ||
152 | int ret, state = STATE_POLL; | ||
153 | bool last_present, present; | ||
154 | int attempts = 0; | ||
155 | |||
156 | last_present = present = storage_present(1); /* shut up gcc */ | ||
157 | |||
158 | while (1) | ||
159 | { | ||
160 | switch (state) | ||
161 | { | ||
162 | case STATE_POLL: | ||
163 | sleep(HZ/3); | ||
164 | attempts = 0; | ||
165 | present = storage_present(1); | ||
166 | if (last_present != present) | ||
167 | state = STATE_DEBOUNCE; | ||
168 | break; | ||
169 | |||
170 | case STATE_DEBOUNCE: | ||
171 | sleep(HZ/5); | ||
172 | present = storage_present(1); | ||
173 | if (last_present == present) | ||
174 | { | ||
175 | if (present) | ||
176 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | ||
177 | else | ||
178 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | ||
179 | state = STATE_MOUNT; | ||
180 | } | ||
181 | else | ||
182 | state = STATE_POLL; | ||
183 | break; | ||
184 | |||
185 | case STATE_MOUNT: | ||
186 | sleep(HZ/10); | ||
187 | if (present) | ||
188 | ret = mount_sd(); | ||
189 | else | ||
190 | ret = unmount_sd(); | ||
191 | if (ret == 0) | ||
192 | { | ||
193 | NOTEF("Successfully %smounted SD card\n", present ? "":"un"); | ||
194 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
195 | state = STATE_POLL; | ||
196 | } | ||
197 | else if (++attempts > 20) /* stop retrying after 2s */ | ||
198 | { | ||
199 | ERRORF("Failed to %smount SD card. Giving up.", present ? "":"un"); | ||
200 | state = STATE_POLL; | ||
201 | } | ||
202 | /* else: need to retry a few times because the kernel is | ||
203 | * busy setting up the SD (=> do not change state) */ | ||
204 | break; | ||
205 | } | ||
206 | last_present = present; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | #endif | ||
211 | |||
64 | void hostfs_init(void) | 212 | void hostfs_init(void) |
65 | { | 213 | { |
66 | /* stub */ | 214 | /* Setup GPIO pin for microSD sense, copied from OF */ |
215 | gpio_control(DEV_CTRL_GPIO_SET_MUX, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); | ||
216 | gpio_control(DEV_CTRL_GPIO_SET_INPUT, GPIO_SD_SENSE, CONFIG_DEFAULT, 0); | ||
217 | if (storage_present(IF_MD(1))) | ||
218 | mount_sd(); | ||
219 | #ifdef HAVE_HOTSWAP | ||
220 | create_thread(sd_thread, sd_thread_stack, sizeof(sd_thread_stack), 0, | ||
221 | "sd thread" IF_PRIO(, PRIORITY_BACKGROUND) IF_COP(, CPU)); | ||
222 | #endif | ||
67 | } | 223 | } |
68 | 224 | ||
69 | int hostfs_flush(void) | 225 | int hostfs_flush(void) |
70 | { | 226 | { |
71 | sync(); | 227 | sync(); |
72 | |||
73 | return 0; | 228 | return 0; |
74 | } | 229 | } |
75 | 230 | ||