apply FSL(Flora Software License)
[framework/system/system-server.git] / ss_mmc_handler.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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
33 int mmc_status;
34
35 int get_mmcblk_num()
36 {
37         DIR *dp;
38         struct dirent *dir;
39         struct stat stat;
40         char buf[255];
41         int fd;
42         int r;
43         int mmcblk_num;
44
45         if ((dp = opendir("/sys/block")) == NULL) {
46                 PRT_TRACE_ERR("Can not open directory..\n");
47                 return -1;
48         }
49         chdir("/sys/block");
50
51         while (dir = readdir(dp)) {
52                 memset(&stat, 0, sizeof(struct stat));
53                 lstat(dir->d_name, &stat);
54                 if (S_ISDIR(stat.st_mode) || S_ISLNK(stat.st_mode)) {
55                         if (strncmp(".", dir->d_name, 1) == 0
56                             || strncmp("..", dir->d_name, 2) == 0)
57                                 continue;
58                         if (strncmp("mmcblk", dir->d_name, 6) == 0) {
59                                 snprintf(buf, 255, "/sys/block/%s/device/type",
60                                          dir->d_name);
61
62                                 fd = open(buf, O_RDONLY);
63                                 if (fd == -1)
64                                         PRT_TRACE_ERR("%s open error: %s", buf,
65                                                       strerror(errno));
66                                 r = read(fd, buf, 10);
67                                 if ((r >= 0) && (r < 10))
68                                         buf[r] = '\0';
69                                 else
70                                         PRT_TRACE_ERR("%s read error: %s", buf,
71                                                       strerror(errno));
72                                 close(fd);
73                                 if (strncmp("SD", buf, 2) == 0) {
74                                         char *str_mmcblk_num = strndup((dir->d_name) + 6, 1);
75                                         if (str_mmcblk_num == NULL) {
76                                                 PRT_TRACE_ERR("Memory Allocation Failed");
77                                                 closedir(dp);
78                                                 return -1; 
79                                         }
80                                         mmcblk_num =
81                                             atoi(str_mmcblk_num);
82
83                                         free(str_mmcblk_num);
84                                         closedir(dp);
85                                         PRT_TRACE("%d \n", mmcblk_num);
86                                         return mmcblk_num;
87                                 }
88                         }
89
90                 }
91         }
92         closedir(dp);
93         PRT_TRACE_ERR("Failed to find mmc block number\n");
94         return -1;
95 }
96
97 static int ss_mmc_format_tmp(keynode_t *key_nodes, void *data)
98 {
99         PRT_TRACE_ERR("mmc_format called");
100         if (vconf_keynode_get_int(key_nodes) == 1) {
101                 PRT_TRACE_ERR("format start");
102                 device_set_property(DEVTYPE_MMC, MMC_PROP_FORMAT, 0);
103
104         }
105
106         return 0;
107 }
108
109 static int ss_mmc_format(keynode_t *key_nodes, void *data)
110 {
111         PRT_TRACE_ERR("mmc format called");
112         device_set_property(DEVTYPE_MMC, MMC_PROP_FORMAT, 0);
113
114         return 0;
115 }
116
117 int ss_mmc_unmounted(int argc, char **argv)
118 {
119         int option = -1;
120
121         if (argc < 1) {
122                 PRT_TRACE_ERR("Option is wong");
123                 return -1;
124         }
125         if ((option = atoi(argv[0])) < 0) {
126                 PRT_TRACE_ERR("Option is wong : %d", option);
127                 return -1;
128         }
129
130         if (umount2(MMC_MOUNT_POINT, option) != 0) {
131                 PRT_TRACE_ERR("Failed to unmount mmc card\n");
132                 vconf_set_int(VCONFKEY_SYSMAN_MMC_UNMOUNT,
133                               VCONFKEY_SYSMAN_MMC_UNMOUNT_FAILED);
134                 return -1;
135
136         }
137         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
138                       VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
139         vconf_set_int(VCONFKEY_SYSMAN_MMC_UNMOUNT,
140                       VCONFKEY_SYSMAN_MMC_UNMOUNT_COMPLETED);
141         mmc_status = VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED;
142
143         return 0;
144 }
145
146 int ss_mmc_init()
147 {
148         /* mmc card mount */
149         ss_mmc_inserted();
150
151         vconf_notify_key_changed("memory/mmc/format", (void *)ss_mmc_format_tmp,
152                                  NULL);
153
154         ss_action_entry_add_internal(PREDEF_MOUNT_MMC, ss_mmc_inserted, NULL,
155                                      NULL);
156         ss_action_entry_add_internal(PREDEF_UNMOUNT_MMC, ss_mmc_unmounted, NULL,
157                                      NULL);
158         ss_action_entry_add_internal(PREDEF_FORMAT_MMC, ss_mmc_format, NULL,
159                                      NULL);
160         return 0;
161 }
162
163 int ss_mmc_inserted()
164 {
165         char buf[NAME_MAX];
166         int blk_num, ret, retry = 0;
167         char opt[NAME_MAX];
168         char *popt = opt;
169
170         if (mmc_status == VCONFKEY_SYSMAN_MMC_MOUNTED) {
171                 PRT_DBG("Mmc is already mounted.\n");
172                 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
173                               VCONFKEY_SYSMAN_MMC_MOUNTED);
174                 vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT,
175                               VCONFKEY_SYSMAN_MMC_MOUNT_ALREADY);
176                 return -1;
177         }
178
179         if (access(MMC_MOUNT_POINT, R_OK) != 0)
180                 mkdir(MMC_MOUNT_POINT, 0755);
181
182         if ((blk_num = get_mmcblk_num()) == -1) {
183                 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
184                               VCONFKEY_SYSMAN_MMC_REMOVED);
185                 vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT,
186                               VCONFKEY_SYSMAN_MMC_MOUNT_FAILED);
187                 mmc_status = VCONFKEY_SYSMAN_MMC_REMOVED;
188                 return 0;
189         }
190         popt = NULL;
191
192         snprintf(buf, sizeof(buf), "%s%d", MMC_DEV, blk_num);
193         if (mount
194             (buf, MMC_MOUNT_POINT, "vfat", 0,
195              "uid=0,gid=0,dmask=0000,fmask=0111,iocharset=iso8859-1,utf8,shortname=mixed")
196             == 0) {
197                 PRT_DBG("Mounted mmc card\n");
198                 vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
199                               VCONFKEY_SYSMAN_MMC_MOUNTED);
200                 vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT,
201                               VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED);
202                 mmc_status = VCONFKEY_SYSMAN_MMC_MOUNTED;
203                 return 0;
204         }
205         do {
206                 snprintf(buf, sizeof(buf), "%s%dp1", MMC_DEV, blk_num);
207                 if ((ret =
208                      mount(buf, MMC_MOUNT_POINT, "vfat", 0,
209                            "uid=0,gid=0,dmask=0000,fmask=0111,iocharset=iso8859-1,utf8,shortname=mixed"))
210                     == 0) {
211                         PRT_DBG("Mounted mmc card partition 1(%s)\n", buf);
212                         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
213                                       VCONFKEY_SYSMAN_MMC_MOUNTED);
214                         vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT,
215                                       VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED);
216                         mmc_status = VCONFKEY_SYSMAN_MMC_MOUNTED;
217                         return 0;
218                 }
219                 usleep(100000);
220         } while (ret == -1 && errno == ENOENT && retry++ < 10);
221
222         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS,
223                       VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED);
224         vconf_set_int(VCONFKEY_SYSMAN_MMC_MOUNT,
225                       VCONFKEY_SYSMAN_MMC_MOUNT_FAILED);
226         mmc_status = VCONFKEY_SYSMAN_MMC_INSERTED_NOT_MOUNTED;
227         PRT_TRACE_ERR("Failed to mount mmc card\n");
228         return -1;
229 }
230
231 int ss_mmc_removed()
232 {
233         vconf_set_int(VCONFKEY_SYSMAN_MMC_STATUS, VCONFKEY_SYSMAN_MMC_REMOVED);
234
235         if (umount2(MMC_MOUNT_POINT, MNT_DETACH) != 0) {
236                 PRT_TRACE_ERR("Failed to unmount mmc card\n");
237         }
238         mmc_status = VCONFKEY_SYSMAN_MMC_REMOVED;
239
240         return 0;
241 }