Fix bug in usbotg_storage_mounted and usbotg_camera_added.
[platform/core/system/system-popup.git] / src / usb / usbotg-mobile.c
1 /*
2  *  system-popup
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18 */
19
20 #include "popup-common.h"
21 #include <appsvc.h>
22 #include <app_control.h>
23
24
25 #define MYFILES_APPNAME "org.tizen.myfile"
26 #define GALLERY_APPNAME "org.tizen.gallery"
27
28 #define USB_MOUNT_ROOT_PATH     "/opt/storage"
29 #define USB_MOUNT_PATH          "_DEVICE_PATH_"
30
31 #define BUF_MAX 128
32
33 #define DEVICED_PATH                    "/Org/Tizen/System/DeviceD"
34 #define DEVICED_IFACE                   "org.tizen.system.deviced"
35 #define DEVICED_PATH_USBHOST    DEVICED_PATH"/Usbhost"
36 #define DEVICED_IFACE_USBHOST   DEVICED_IFACE".Usbhost"
37 #define SIGNAL_NAME_UNMOUNT             "unmount_storage"
38
39 static char added_path[BUF_MAX];
40 static char removed_path[BUF_MAX];
41
42 enum ext_app {
43         EXT_MYFILES,
44         EXT_GALLERY,
45 };
46
47 static const struct popup_ops storage_mounted_ops;
48 static const struct popup_ops unmount_storage_ops;
49 static const struct popup_ops camera_added_ops;
50 static const struct popup_ops storage_mount_failed_ops;
51 static const struct popup_ops storage_removed_unsafe_ops;
52
53 static void remove_otg_popup(const struct popup_ops *ops, char *path)
54 {
55         int len;
56         char *popup_path;
57
58         if (ops == &storage_mounted_ops)
59                 popup_path = added_path;
60         else if (ops == &unmount_storage_ops)
61                 popup_path = removed_path;
62         else
63                 popup_path = NULL;
64
65         if (popup_path) {
66                 if (!path)
67                         return;
68                 len = strlen(popup_path);
69                 if (len != strlen(path))
70                         return;
71                 if (strncmp(popup_path, path, len))
72                         return;
73         }
74
75         unload_simple_popup(ops);
76 }
77
78 static void set_myfiles_param(bundle *b)
79 {
80         if (!b)
81                 return;
82
83         if (strlen(added_path) > 0)
84                 appsvc_add_data(b, "path", added_path);
85         else
86                 appsvc_add_data(b, "path", USB_MOUNT_ROOT_PATH);
87         appsvc_set_pkgname(b, MYFILES_APPNAME);
88 }
89
90 static void set_gallery_param(bundle *b)
91 {
92         if (!b)
93                 return;
94         appsvc_add_data(b, "album-id", "GALLERY_ALBUM_PTP_ID");
95         appsvc_set_pkgname(b, GALLERY_APPNAME);
96 }
97
98 static struct ext_app_type {
99         int type;
100         void (*set_param)(bundle *b);
101 } app_type[] = {
102         { EXT_MYFILES   , set_myfiles_param     },
103         { EXT_GALLERY   , set_gallery_param     },
104 };
105
106 static void launch_app(int type)
107 {
108         app_control_h app_control;
109
110         int ret, i, type_len;
111
112         type_len = ARRAY_SIZE(app_type);
113         for (i = 0 ; i < ARRAY_SIZE(app_type) ; i++) {
114                 if (type == app_type[i].type)
115                         break;
116         }
117         if (i == type_len) {
118                 _E("Invalid type (%d)", type);
119                 return;
120         }
121
122         ret = app_control_create(&app_control);
123         if (ret != APP_CONTROL_ERROR_NONE)
124                 return;
125
126         if (type == 0)
127                 ret = app_control_set_app_id(app_control, MYFILES_APPNAME);
128         else if (type == 1)
129                 ret = app_control_set_app_id(app_control, GALLERY_APPNAME);
130         else {
131                 _E("No matched type(%d)", type);
132                 return;
133         }
134
135         if (ret != APP_CONTROL_ERROR_NONE) {
136                 (void)app_control_destroy(app_control);
137                 return;
138         }
139
140         ret = app_control_send_launch_request(app_control, NULL, NULL);
141         if (ret != APP_CONTROL_ERROR_NONE)
142                 _E("Failed to send launch request");
143
144         (void)app_control_destroy(app_control);
145 }
146
147 static void storage_browse(const struct popup_ops *ops)
148 {
149         unload_simple_popup(ops);
150         launch_app(EXT_MYFILES);
151         terminate_if_no_popup();
152 }
153
154 static void camera_browse(const struct popup_ops *ops)
155 {
156         unload_simple_popup(ops);
157         launch_app(EXT_GALLERY);
158         terminate_if_no_popup();
159 }
160
161 static void storage_unmount(const struct popup_ops *ops)
162 {
163         char *param[1];
164         int ret;
165
166         unload_simple_popup(ops);
167
168         param[0] = removed_path;
169
170         ret = broadcast_dbus_signal(DEVICED_PATH_USBHOST,
171                         DEVICED_IFACE_USBHOST,
172                         SIGNAL_NAME_UNMOUNT, "s", param);
173         if (ret < 0)
174                 _E("FAIL: broadcast_dbus_signal()");
175
176         memset(removed_path, 0, sizeof(removed_path));
177
178         terminate_if_no_popup();
179 }
180
181 static int storage_mounted_launch(bundle *b, const struct popup_ops *ops)
182 {
183         int ret;
184         struct object_ops *obj;
185         char *path;
186
187         if (!ops)
188                 return -1;
189
190         ret = get_object_by_ops(ops, &obj);
191         if (ret < 0) {
192                 _E("Failed to get object (%d)", ret);
193                 return -2;
194         }
195
196         path = (char *)bundle_get_val(obj->b, USB_MOUNT_PATH);
197         if (!path) {
198                 _E("Failed to get mount path");
199                 return -3;
200         }
201
202         _I("USB storage mount path (%s)", path);
203         snprintf(added_path, sizeof(added_path), "%s", path);
204         return 0;
205 }
206
207 static int unmount_storage_launch(bundle *b, const struct popup_ops *ops)
208 {
209         int ret;
210         struct object_ops *obj;
211         char *path;
212
213         if (!ops)
214                 return -1;
215
216         ret = get_object_by_ops(ops, &obj);
217         _D("ops = %s obj = %s", ops, obj);
218         if (ret < 0) {
219                 _E("Failed to get object (%d)", ret);
220                 return -2;
221         }
222
223         path = (char *)bundle_get_val(obj->b, USB_MOUNT_PATH);
224         if (!path) {
225                 _E("Failed to get mount path");
226                 return -3;
227         }
228
229         remove_otg_popup(&storage_mounted_ops, path);
230
231         snprintf(removed_path, sizeof(removed_path), "%s", path);
232         return 0;
233 }
234
235 static int storage_unmounted(bundle *b, const struct popup_ops *ops)
236 {
237         char *path;
238
239         if (!b || !ops)
240                 return -EINVAL;
241
242         path = (char *)bundle_get_val(b, USB_MOUNT_PATH);
243         if (!path) {
244                 _E("Failed to get mount path");
245                 return -ENOENT;
246         }
247
248         remove_otg_popup(&storage_mounted_ops, path);
249         remove_otg_popup(&unmount_storage_ops, path);
250
251         terminate_if_no_popup();
252         return 0;
253 }
254
255 static int camera_removed(bundle *b, const struct popup_ops *ops)
256 {
257         remove_otg_popup(&camera_added_ops, NULL);
258         terminate_if_no_popup();
259         return 0;
260 }
261
262 static const struct popup_ops storage_mounted_ops = {
263         .name                   = "usbotg_storage_mounted",
264         .show                   = load_simple_popup,
265         .title                  = "IDS_ST_BODY_USB_STORAGE_ABB",
266         .content                = "IDS_USB_BODY_BROWSE_STORAGE_CONNECTED_VIA_USB_Q",
267         .left_text              = "IDS_COM_SK_CANCEL",
268         .right_text             = "IDS_BT_SK_BROWSE",
269         .right                  = storage_browse,
270         .pre                    = storage_mounted_launch,
271 };
272
273 static const struct popup_ops storage_unmounted_ops = {
274         .name                   = "usbotg_storage_unmounted",
275         .show                   = storage_unmounted,
276 };
277
278 static const struct popup_ops unmount_storage_ops = {
279         .name                   = "usbotg_unmount_storage",
280         .show                   = load_simple_popup,
281         .title                  = "IDS_ST_BODY_USB_STORAGE_ABB",
282         .content                = "IDS_COM_POP_UNMOUNT_USB_MASS_STORAGE_BEFORE_REMOVING_TO_AVOID_DATA_LOSS",
283         .left_text              = "IDS_COM_SK_CANCEL",
284         .right_text             = "IDS_USB_BUTTON_UNMOUNT",
285         .right                  = storage_unmount,
286         .pre                    = unmount_storage_launch,
287 };
288
289 static const struct popup_ops camera_added_ops = {
290         .name                   = "usbotg_camera_added",
291         .show                   = load_simple_popup,
292         .title                  = "IDS_CAM_HEADER_CAMERA_M_APPLICATION",
293         .content                = "IDS_USB_BODY_BROWSE_CAMERA_CONNECTED_VIA_USB_Q",
294         .left_text              = "IDS_COM_SK_CANCEL",
295         .right_text             = "IDS_BT_SK_BROWSE",
296         .right                  = camera_browse,
297 };
298
299 static const struct popup_ops camera_removed_ops = {
300         .name                   = "usbotg_camera_removed",
301         .show                   = camera_removed,
302 };
303
304 static const struct popup_ops storage_mount_failed_ops = {
305         .name                   = "usbotg_storage_mount_failed",
306         .show                   = load_simple_popup,
307         .title                  = "IDS_COM_HEADER_ATTENTION",
308         .content                = "IDS_COM_BODY_USB_STORAGE_BLANK_OR_HAS_UNSUPPORTED_FILE_SYSTEM",
309         .left_text              = "IDS_COM_SK_OK",
310 };
311
312 static const struct popup_ops storage_removed_unsafe_ops = {
313         .name                   = "usbotg_storage_removed_unsafe",
314         .show                   = load_simple_popup,
315         .title                  = "IDS_COM_HEADER_ATTENTION",
316         .content                = "IDS_COM_POP_USB_MASS_STORAGE_UNEXPECTEDLY_REMOVED",
317         .left_text              = "IDS_COM_SK_OK",
318 };
319
320
321 /* Constructor to register mount_failed button */
322 static __attribute__ ((constructor)) void usbotg_register_popup(void)
323 {
324         register_popup(&storage_mounted_ops);
325         register_popup(&storage_unmounted_ops);
326         register_popup(&unmount_storage_ops);
327         register_popup(&camera_added_ops);
328         register_popup(&camera_removed_ops);
329         register_popup(&storage_mount_failed_ops);
330         register_popup(&storage_removed_unsafe_ops);
331 }