merge with master
[platform/core/system/system-server.git] / ss_mmc_handler.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include <unistd.h>
19 #include <sys/mount.h>
20 #include <errno.h>
21 #include <vconf.h>
22 #include <devman.h>
23 #include <fcntl.h>
24 #include <dirent.h>
25 #include <sysman.h>
26 #include "ss_log.h"
27 #include "ss_device_handler.h"
28
29 #define MOVINAND_DEV            "/dev/mmcblk0p1"
30 #define FORMAT_MMC              PREFIX"/sbin/mkfs.vfat "
31 #define FORMAT_MOVINAND         PREFIX"/bin/movi_format.sh"
32 #define FS_VFAT_MOUNT_OPT  "uid=0,gid=0,dmask=0000,fmask=0111,iocharset=iso8859-1,utf8,shortname=mixed,smackfsroot=*,smackfsdef=*"
33
34 int mmc_status;
35 int ss_mmc_inserted(void);
36 static int __umount_fs(void);
37
38 int get_mmcblk_num()
39 {
40         DIR *dp;
41         struct dirent *dir;
42         struct stat stat;
43         char buf[255];
44         int fd;
45         int r;
46         int mmcblk_num;
47
48         if ((dp = opendir("/sys/block")) == NULL) {
49                 PRT_TRACE_ERR("Can not open directory..\n");
50                 return -1;
51         }
52         chdir("/sys/block");
53
54         while ((dir = readdir(dp)) != NULL) {
55                 memset(&stat, 0, sizeof(struct stat));
56                 if(lstat(dir->d_name, &stat) < 0) {continue;}
57                 if (S_ISDIR(stat.st_mode) || S_ISLNK(stat.st_mode)) {
58                         if (strncmp(".", dir->d_name, 1) == 0
59                             || strncmp("..", dir->d_name, 2) == 0)
60                                 continue;
61                         if (strncmp("mmcblk", dir->d_name, 6) == 0) {
62                                 snprintf(buf, 255, "/sys/block/%s/device/type",
63                                          dir->d_name);
64
65                                 fd = open(buf, O_RDONLY);
66                                 if (fd == -1) {
67                                         PRT_TRACE_ERR("%s open error: %s", buf,
68                                                       strerror(errno));
69                                         continue;
70                                 }
71                                 r = read(fd, buf, 10);
72                                 if ((r >= 0) && (r < 10))
73                                         buf[r] = '\0';
74                                 else
75                                         PRT_TRACE_ERR("%s read error: %s", buf,
76                                                       strerror(errno));
77                                 close(fd);
78                                 if (strncmp("SD", buf, 2) == 0) {
79                                         char *str_mmcblk_num = strndup((dir->d_name) + 6, 1);
80                                         if (str_mmcblk_num == NULL) {
81                                                 PRT_TRACE_ERR("Memory Allocation Failed");
82                                                 closedir(dp);
83                                                 return -1; 
84                                         }
85                                         mmcblk_num =
86                                             atoi(str_mmcblk_num);
87
88                                         free(str_mmcblk_num);
89                                         closedir(dp);
90                                         PRT_TRACE("%d \n", mmcblk_num);
91                                         return mmcblk_num;
92                                 }
93                         }
94
95                 }
96         }
97         closedir(dp);
98         PRT_TRACE_ERR("Failed to find mmc block number\n");
99         return -1;
100 }
101
102 static int ss_mmc_format(keynode_t *key_nodes, void *data)
103 {
104         PRT_TRACE_ERR("mmc format called");
105         __umount_fs();
106         vconf_set_int(VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS, VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS_NOW);
107         device_set_property(DEVTYPE_MMC, MMC_PROP_FORMAT, 0);
108         vconf_set_int(VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS, VCONFKEY_SYSMAN_MMC_FORMAT_PROGRESS_NONE);
109         ss_mmc_inserted();
110         return 0;
111 }
112
113 int ss_mmc_unmounted(int argc, char **argv)
114 {
115         int option = -1;
116         int mmc_err = 0;
117         if (argc < 1) {
118                 PRT_TRACE_ERR("Option is wong");
119                 return -1;
120         }
121         if ((option = atoi(argv[0])) < 0) {
122                 PRT_TRACE_ERR("Option is wong : %d", option);
123                 return -1;
124         }
125
126         if (umount2(MMC_MOUNT_POINT, option) != 0) {
127                 mmc_err = errno;
128                 PRT_TRACE_ERR("Failed to unmount mmc card\n");
129                 vconf_set_int(VCONFKEY_SYSMAN_MMC_UNMOUNT,
130                               VCONFKEY_SYSMAN_MMC_UNMOUNT_FAILED);
131                 vconf_set_int(VCONFKEY_SYSMAN_MMC_ERR_STATUS,
132                                 mmc_err);
133                 return -1;
134
135         }
136         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
137                       VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
138         vconf_set_int(VCONFKEY_SYSMAN_MMC_UNMOUNT,
139                       VCONFKEY_SYSMAN_MMC_UNMOUNT_COMPLETED);
140         mmc_status = VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED;
141
142         return 0;
143 }
144
145 int ss_mmc_init()
146 {
147         /* mmc card mount */
148         ss_mmc_inserted();
149
150         ss_action_entry_add_internal(PREDEF_MOUNT_MMC, ss_mmc_inserted, NULL, NULL);
151         ss_action_entry_add_internal(PREDEF_UNMOUNT_MMC, ss_mmc_unmounted, NULL, NULL);
152         ss_action_entry_add_internal(PREDEF_FORMAT_MMC, ss_mmc_format, NULL, NULL);
153         return 0;
154 }
155
156 static int __mount_fs(char *path, const char *fs_name, const char *mount_data)
157 {
158         int ret, retry = 0;
159         do {
160                 if ((ret = mount(path, MMC_MOUNT_POINT, fs_name, 0, mount_data)) == 0) {
161                         PRT_TRACE("Mounted mmc card\n");
162                         return 0;
163                 }
164                 usleep(100000);
165         } while (ret == -1 && errno == ENOENT && retry++ < 10);
166
167         return errno;
168 }
169
170 static int __mmc_mount_fs(void)
171 {
172         char buf[NAME_MAX];
173         char params[NAME_MAX];
174         int fd;
175         int blk_num;
176
177         if (access(MMC_MOUNT_POINT, R_OK) != 0) {
178                 if (mkdir(MMC_MOUNT_POINT, 0755) < 0) {
179                         PRT_TRACE_ERR("Make Directory is failed");
180                         return errno;
181                 }
182         }
183
184         blk_num = get_mmcblk_num();
185         if (blk_num  == -1) {
186                 PRT_TRACE_ERR("fail to check mmc block");
187                 return -1;
188         }
189
190         snprintf(buf, sizeof(buf), "%s%dp1", MMC_DEV, blk_num);
191         fd = open(buf, O_RDONLY);
192         if (fd < 0) {
193                 PRT_TRACE_ERR("can't open the '%s': %s", buf, strerror(errno));
194                 snprintf(buf, sizeof(buf), "%s%d", MMC_DEV, blk_num);
195         }
196         close(fd);
197
198                 if (__mount_fs(buf, "vfat", FS_VFAT_MOUNT_OPT) != 0)
199                         return errno;
200         return 0;
201 }
202
203 int ss_mmc_inserted(void)
204 {
205         int r = 0;
206
207         if (mmc_status == VCONFKEY_SYSMAN_MMC_MOUNTED) {
208                 PRT_DBG("Mmc is already mounted.\n");
209                 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_MOUNTED);
210                 vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT, VCONFKEY_SYSMAN_MMC_MOUNT_ALREADY);
211
212                 return -1;
213         }
214
215         r = __mmc_mount_fs();
216         if (r == 0)
217                 goto mount_complete;
218         else if (r == -1)
219                 goto mount_fail;
220         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
221         vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT, VCONFKEY_SYSMAN_MMC_MOUNT_FAILED);
222         vconf_set_int(VCONFKEY_SYSMAN_MMC_ERR_STATUS, errno);
223         mmc_status = VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED;
224         PRT_TRACE_ERR("Failed to mount mmc card\n");
225         return -1;
226
227 mount_complete:
228         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_MOUNTED);
229         vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT, VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED);
230         mmc_status = VCONFKEY_SYSMAN_MMC_MOUNTED;
231         return 0;
232 mount_fail:
233         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_REMOVED);
234         vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT, VCONFKEY_SYSMAN_MMC_MOUNT_FAILED);
235         vconf_set_int(VCONFKEY_SYSMAN_MMC_ERR_STATUS, VCONFKEY_SYSMAN_MMC_EINVAL);
236         mmc_status = VCONFKEY_SYSMAN_MMC_REMOVED;
237         return 0;
238 }
239
240 static int __umount_fs(void)
241 {
242         int ret;
243         if ((ret = umount2(MMC_MOUNT_POINT, MNT_DETACH)) != 0) {
244                 PRT_TRACE_ERR("Failed to unmount mmc card\n");
245         }
246         mmc_status = VCONFKEY_SYSMAN_MMC_REMOVED;
247         return ret;
248 }
249
250 int ss_mmc_removed()
251 {
252         int mmc_err = 0;
253         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_REMOVED);
254         mmc_err = __umount_fs();
255         vconf_set_int(VCONFKEY_SYSMAN_MMC_ERR_STATUS, mmc_err);
256
257         return 0;
258 }