268c8d828707f482dc48d0722c0c97e2f9dab2e7
[platform/core/system/deviced.git] / src / devicectl / usb.c
1 /*
2  * devicectl
3  *
4  * Copyright (c) 2012 - 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 <stdio.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <shared/common.h>
25 #include <core/launch.h>
26 #include "usb.h"
27
28 #define USB_SDB "sdb"
29 #define USB_SSH "ssh"
30
31 #define ARG_MAX 10
32 #define CMD_MAX 128
33
34 static struct usb_sysfs {
35         char *path;
36         char *value;
37 } usb_confs[] = {
38         { "/sys/class/usb_mode/usb0/enable",          "0"    },
39         { "/sys/class/usb_mode/usb0/idVendor",        "04e8" },
40         { "/sys/class/usb_mode/usb0/idProduct",       NULL   },
41         { "/sys/class/usb_mode/usb0/funcs_fconf",     NULL   },
42         { "/sys/class/usb_mode/usb0/funcs_sconf",     NULL   },
43         { "/sys/class/usb_mode/usb0/bDeviceClass",    "239"  },
44         { "/sys/class/usb_mode/usb0/bDeviceSubClass", "2"    },
45         { "/sys/class/usb_mode/usb0/bDeviceProtocol", "1"    },
46         { "/sys/class/usb_mode/usb0/enable",          "1"    },
47 };
48
49 static int launch_app(char **argv)
50 {
51         pid_t pid;
52
53         if (!argv || !argv[0])
54                 return -EINVAL;
55
56         pid = fork();
57
58         if (pid < 0) {
59                 printf("Failed to call fork().\n");
60                 return -ENOMEM;
61         }
62
63         if (pid > 0) { /*parent*/
64                 return pid;
65         }
66
67         /*child*/
68
69         if (execvp(argv[0], argv) < 0)
70                 printf("Failed to call execvp: %d\n", errno);
71
72         return 0;
73 }
74
75 static int write_sysfs(char *path, char *value)
76 {
77         FILE *fp;
78         int ret;
79
80         if (!path || !value)
81                 return -ENOMEM;
82
83         fp = fopen(path, "w");
84         if (!fp) {
85                 printf("Failed to open '%s'.\n", path);
86                 return -ENOMEM;
87         }
88
89         ret = fwrite(value, sizeof(char), strlen(value), fp);
90         fclose(fp);
91         if (ret < strlen(value)) {
92                 printf("Failed to write '%s'.\n", value);
93                 ret = -ENOMEM;
94         }
95
96         return ret;
97 }
98
99 static int set_usb_configuration(char *idproduct, char *fconf, char *sconf)
100 {
101         int i, ret;
102
103         usb_confs[2].value = idproduct;
104         usb_confs[3].value = fconf;
105         usb_confs[4].value = sconf;
106
107         for (i = 0; i < ARRAY_SIZE(usb_confs); i++) {
108                 ret = write_sysfs(usb_confs[i].path, usb_confs[i].value);
109                 if (ret < 0) {
110                         printf("Failed to write usb setting. path=%s value=%s\n", usb_confs[i].path, usb_confs[i].value);
111                         return ret;
112                 }
113         }
114
115         return 0;
116 }
117
118 static int divide_cmd(char **command, int len, char *cmd)
119 {
120         char *param, *next, *term;
121         int cnt = 0;
122
123         if (!cmd)
124                 return -EINVAL;
125
126         term = strchr(cmd, '\0');
127         if (!term)
128                 return -EINVAL;
129
130         memset(command, 0, len);
131
132         param = cmd;
133         while (1) {
134                 if (*param == '\0')
135                         break;
136                 if (*param == ' ') {
137                         param++;
138                         continue;
139                 }
140
141                 next = strchr(param, ' ');
142                 if (!next) {
143                         command[cnt++] = param;
144                         break;
145                 }
146
147                 if (next == param) {
148                         param++;
149                         continue;
150                 }
151
152                 *next = '\0';
153                 command[cnt++] = param;
154                 param = next + 1;
155         }
156
157         return 0;
158 }
159
160 static int run_cmd(char *cmd)
161 {
162         int ret;
163         char *command[ARG_MAX];
164         char in_cmd[CMD_MAX];
165
166         if (!cmd)
167                 return -EINVAL;
168
169         snprintf(in_cmd, sizeof(in_cmd), "%s", cmd);
170
171         ret = divide_cmd(command, sizeof(command), in_cmd);
172         if (ret < 0)
173                 return ret;
174
175         ret = launch_app(command);
176         if (ret < 0)
177                 return ret;
178
179         return 0;
180
181 }
182
183 static int load_sdb(void)
184 {
185         int ret;
186
187         ret = set_usb_configuration("6860", "mtp", "mtp,acm,sdb");
188         if (ret < 0)
189                 return ret;
190
191         return run_cmd("/usr/bin/systemctl start sdbd.service");
192 }
193
194 static int load_ssh(void)
195 {
196         int ret;
197
198         ret = set_usb_configuration("6863", "rndis", " ");
199         if (ret < 0)
200                 return ret;
201
202         ret = run_cmd("/sbin/ifconfig usb0 192.168.129.3 up");
203         if (ret < 0)
204                 return ret;
205
206         ret = run_cmd("/sbin/route add -net 192.168.129.0 netmask 255.255.255.0 dev usb0");
207         if (ret < 0)
208                 return ret;
209
210         ret = run_cmd("/usr/bin/systemctl start sshd.service");
211         if (ret < 0)
212                 return ret;
213
214         return 0;
215 }
216
217 static int unload_sdb(void)
218 {
219         int ret;
220
221         ret = write_sysfs(usb_confs[0].path, usb_confs[0].value);
222         if (ret < 0)
223                 return ret;
224
225         ret = run_cmd("/usr/bin/systemctl stop sdbd.service");
226         if (ret < 0)
227                 return ret;
228
229         return 0;
230 }
231
232 static int unload_ssh(void)
233 {
234         int ret;
235
236         ret = write_sysfs(usb_confs[0].path, usb_confs[0].value);
237         if (ret < 0)
238                 return ret;
239
240         ret = run_cmd("/sbin/ifconfig usb0 down");
241         if (ret < 0)
242                 return ret;
243
244         ret = run_cmd("/usr/bin/systemctl stop sshd.service");
245         if (ret < 0)
246                 return ret;
247
248         return 0;
249 }
250
251 int load_usb_mode(char *opt)
252 {
253         if (!opt) {
254                 printf("Failed: Forth parameter is NULL.\n");
255                 return -EINVAL;
256         }
257
258         if (!strncmp(opt, USB_SDB, strlen(opt)))
259                 return load_sdb();
260
261         if (!strncmp(opt, USB_SSH, strlen(opt)))
262                 return load_ssh();
263
264         printf("Failed: Forth parameter(%s) is invalid.\n", opt);
265         return -EINVAL;
266 }
267
268 int unload_usb_mode(char *opt)
269 {
270         if (!opt) {
271                 printf("Failed: Forth parameter is NULL.\n");
272                 return -EINVAL;
273         }
274
275         if (!strncmp(opt, USB_SDB, strlen(opt)))
276                 return unload_sdb();
277
278         if (!strncmp(opt, USB_SSH, strlen(opt)))
279                 return unload_ssh();
280
281         printf("Failed: Forth parameter(%s) is invalid.\n", opt);
282         return -EINVAL;
283 }