2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "usb_accessory_private.h"
19 /* This function initializes socket for ipc with usb-server */
20 int ipc_request_client_init(int *sock_remote)
23 if (!sock_remote) return -1;
25 struct sockaddr_un remote;
27 if (((*sock_remote) = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
29 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)");
32 remote.sun_family = AF_UNIX;
33 strncpy(remote.sun_path, SOCK_PATH, strlen(SOCK_PATH)+1);
34 len = strlen(remote.sun_path) + sizeof(remote.sun_family);
36 if (connect((*sock_remote), (struct sockaddr *)&remote, len) == -1) {
38 USB_LOG("FAIL: connect((*sock_remote), (struct sockaddr *)&remote, len)");
45 /* This function closes socket for ipc with usb-server */
46 int ipc_request_client_close(int *sock_remote)
49 if (!sock_remote) return -1;
55 /* This function requests something to usb-server by ipc with socket and gets the results */
56 int request_to_usb_server(int sock_remote, int request, char *answer, char *pkgName)
60 char str[SOCK_STR_LEN];
62 USB_LOG("request: %d, pkgName: %s\n", request, pkgName);
63 snprintf(str, SOCK_STR_LEN, "%d|%s", request, pkgName);
64 if (send (sock_remote, str, strlen(str)+1, 0) == -1) {
65 USB_LOG("FAIL: send (sock_remote, str, strlen(str)+1, 0)\n");
68 if ((t = recv(sock_remote, answer, SOCK_STR_LEN, 0)) > 0) {
70 USB_LOG("[CLIENT] Received value: %s\n", answer);
72 USB_LOG("FAIL: recv(sock_remote, str, SOCK_STR_LEN, 0)\n");
79 int handle_input_to_server(void *data, char *buf)
84 struct AccCbData *permCbData = (struct AccCbData *)data;
85 int input = atoi(buf);
86 USB_LOG("Input: %d\n", input);
89 case REQ_ACC_PERM_NOTI_YES_BTN:
90 permCbData->accessory->accPermission = true;
91 permCbData->request_perm_cb_func((struct usb_accessory_s*)(permCbData->user_data), true);
93 case REQ_ACC_PERM_NOTI_NO_BTN:
94 permCbData->accessory->accPermission = false;
95 permCbData->request_perm_cb_func((struct usb_accessory_s*)(permCbData->user_data), false);
104 static int read_message(int fd, char *str, int len)
109 ret = read(fd, str, len);
111 if (EINTR == errno) {
112 USB_LOG("Re-read for error(EINTR)\n");
115 USB_LOG("FAIL: read(fd, str, len)\n");
125 int ipc_noti_client_init(void)
131 struct sockaddr_un serveraddr;
133 sock_local = socket(AF_UNIX, SOCK_STREAM, 0);
134 if (sock_local < 0) {
136 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)\n");
139 serveraddr.sun_family = AF_UNIX;
140 strncpy(serveraddr.sun_path, ACC_SOCK_PATH, strlen(ACC_SOCK_PATH)+1);
141 USB_LOG("socket file name: %s\n", serveraddr.sun_path);
142 unlink(serveraddr.sun_path);
143 len = strlen(serveraddr.sun_path) + sizeof(serveraddr.sun_family);
145 if (bind (sock_local, (struct sockaddr *)&serveraddr, len) < 0) {
147 USB_LOG("FAIL: bind (sock_local, (struct sockaddr_un *)serveraddr)\n");
151 ret = chown(ACC_SOCK_PATH, 5000, 5000);
152 if (ret < 0) USB_LOG("FAIL: chown(ACC_SOCK_PATH, 5000, 5000)");
153 ret = chmod(ACC_SOCK_PATH, 0777);
154 if (ret < 0) USB_LOG("FAIL: chmod(ACC_SOCK_PATH, 0777);");
156 if (listen (sock_local, 5) == -1) {
158 USB_LOG("FAIL: listen (sock_local, 5)\n");
166 int ipc_noti_client_close(int *sock_remote)
174 gboolean ipc_noti_client_cb(GIOChannel *g_io_ch, GIOCondition condition, gpointer data)
177 if (!data) return FALSE;
178 if (!g_io_ch) return FALSE;
181 struct sockaddr_un client_address;
184 char input_buf[SOCK_STR_LEN];
185 char output_buf[SOCK_STR_LEN];
189 fd = g_io_channel_unix_get_fd(g_io_ch);
191 USB_LOG("FAIL: g_io_channel_unix_get_fd(g_io_ch)\n");
192 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
193 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
194 g_io_channel_unref(g_io_ch);
198 client_len = sizeof(client_address);
199 client_sockfd = accept(fd, (struct sockaddr *)&client_address, (socklen_t *)&client_len);
200 if (client_sockfd == -1) {
202 USB_LOG("FAIL: accept(fd, (struct sockaddr *)&client_address, (socklen_t *)&client_len)\n");
203 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
204 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
205 g_io_channel_unref(g_io_ch);
206 ret = ipc_noti_client_close(&client_sockfd);
207 if (ret < 0) USB_LOG("FAIL: ipc_noti_client_close(client_sockfd)\n");
211 if(read_message(client_sockfd, input_buf, sizeof(input_buf)) < 0) {
212 USB_LOG("FAIL: read_message(client_sockfd, &buf)\n");
213 snprintf(output_buf, strlen("FAIL"), "%d", IPC_FAIL);
214 ret = write(client_sockfd, &output_buf, sizeof(output_buf));
215 if (ret < 0) USB_LOG("FAIL: write(client_sockfd, &output_buf, sizeof(output_buf))\n");
216 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
217 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
218 g_io_channel_unref(g_io_ch);
219 ret = ipc_noti_client_close(&client_sockfd);
220 if (ret < 0) USB_LOG("FAIL: ipc_noti_client_close(client_sockfd)\n");
223 USB_LOG("read(): %s\n", input_buf);
224 snprintf(output_buf, SOCK_STR_LEN, "%d", IPC_SUCCESS);
225 ret = write(client_sockfd, &output_buf, sizeof(output_buf));
226 if (ret < 0) USB_LOG("FAIL: write(client_sockfd, &output_buf, sizeof(output_buf))\n");
227 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
228 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
229 g_io_channel_unref(g_io_ch);
230 ret = ipc_noti_client_close(&client_sockfd);
231 if (ret < 0) USB_LOG("FAIL: ipc_noti_client_close(client_sockfd)\n");
233 ret = handle_input_to_server((void *)data, input_buf);
234 if (ret < 0) USB_LOG("FAIL: handle_input_to_server(input_buf, data)\n");
240 /* This function returns the app id.
241 * After calling this function, the memory space should be freed */
246 USB_LOG("pid: %d\n", pid);
247 char appId[APP_ID_LEN];
248 int ret = aul_app_get_appid_bypid(getpid(), appId, APP_ID_LEN);
249 um_retvm_if(AUL_R_OK != ret, NULL, "FAIL: aul_app_get_appid_bypid(getpid(), appId)\n");
251 return strdup(appId);
254 /* This function find an accessory attached just now
255 * Currently This function supports just one accessory */
256 static int getChangedAcc (struct usb_accessory_s **attAcc)
259 if (attAcc == NULL) return -1;
260 struct usb_accessory_list *accList = NULL;
261 bool ret = getAccList(&accList);
262 um_retvm_if(ret == false, -1, "FAIL: getAccList(&accList)\n");
263 um_retvm_if(accList == NULL, -1, "accList == NULL\n");
264 *attAcc = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
265 snprintf((*attAcc)->manufacturer, ACC_ELEMENT_LEN, "%s", accList->accessory->manufacturer);
266 snprintf((*attAcc)->model, ACC_ELEMENT_LEN, "%s", accList->accessory->model);
267 snprintf((*attAcc)->description, ACC_ELEMENT_LEN, "%s", accList->accessory->description);
268 snprintf((*attAcc)->version, ACC_ELEMENT_LEN, "%s", accList->accessory->version);
269 snprintf((*attAcc)->uri, ACC_ELEMENT_LEN, "%s", accList->accessory->uri);
270 snprintf((*attAcc)->serial, ACC_ELEMENT_LEN, "%s", accList->accessory->serial);
271 ret = freeAccList(accList);
272 um_retvm_if(ret == false, -1, "FAIL: freeAccList(accList)\n");
278 /* This func release memory of an accessory attached just now */
279 static int freeChangedAcc (struct usb_accessory_s **attAcc)
282 if (attAcc == NULL) return -1;
288 /* Callback function which is called when accessory vconf key is changed */
289 void accessory_status_changed_cb(keynode_t *in_key, void* data)
293 struct AccCbData *conCbData = (struct AccCbData *)data;
294 struct usb_accessory_s *changedAcc = NULL;
297 ret = vconf_get_int(VCONFKEY_USB_ACCESSORY_STATUS, &val);
298 um_retm_if(ret < 0, "FAIL: vconf_get_int(VCONFKEY_USB_ACCESSORY_STATUS)\n");
301 case VCONFKEY_USB_ACCESSORY_STATUS_DISCONNECTED:
302 conCbData->connection_cb_func(NULL, false, conCbData->user_data);
304 case VCONFKEY_USB_ACCESSORY_STATUS_CONNECTED:
305 ret = getChangedAcc(&changedAcc);
306 um_retm_if(ret < 0, "FAIL: getChangedAcc(&changedAcc)\n");
308 conCbData->connection_cb_func(changedAcc, true, conCbData->user_data);
310 ret = freeChangedAcc(&changedAcc);
311 um_retm_if(ret < 0, "FAIL: freeChangedAcc(&changedAcc)\n");
314 USB_LOG("ERROR: The value of VCONFKEY_USB_ACCESSORY_STATUS is invalid\n");
320 /* Get an element from a string which has all information of an accessory */
321 static bool getAccElement(char *totalInfo[], char accInfo[])
324 if (!totalInfo) return false;
325 if (!accInfo) return false;
327 char *finder = *totalInfo;
331 if (finder == NULL) {
332 USB_LOG("ERROR: finder == NULL");
336 if (*finder == '|' || *finder == '\0') {
338 snprintf(accInfo, ACC_ELEMENT_LEN, "%s", *totalInfo);
339 USB_LOG("Info: %s", accInfo);
340 *totalInfo = ++finder;
351 /* Get all element separated from a string which has all information of an accessory */
352 static int getAccInfo(char *totalInfo[], struct usb_accessory_s **accessory)
355 bool ret = getAccElement(totalInfo, (*accessory)->manufacturer);
356 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, manufacturer)\n");
357 ret = getAccElement(totalInfo, (*accessory)->model);
358 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, model)\n");
359 ret = getAccElement(totalInfo, (*accessory)->description);
360 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, description)\n");
361 ret = getAccElement(totalInfo, (*accessory)->version);
362 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, version)\n");
363 ret = getAccElement(totalInfo, (*accessory)->uri);
364 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, uri)\n");
365 ret = getAccElement(totalInfo, (*accessory)->serial);
366 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, serial)\n");
371 /* This function finds a list which contain all accessories attached
372 * Currently, Tizen usb accessory is designed for just one accessory */
373 //bool getAccList(struct usb_accessory_s **accList)
374 bool getAccList(struct usb_accessory_list **accList)
377 if (*accList != NULL) return false;
378 *accList = (struct usb_accessory_list *)malloc(sizeof(struct usb_accessory_list));
379 struct usb_accessory_s *accessory = NULL;
380 accessory = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
381 (*accList)->next = NULL;
382 (*accList)->accessory = accessory;
383 accessory->accPermission = false;
387 char buf[SOCK_STR_LEN];
388 ret = ipc_request_client_init(&sock_remote);
389 um_retvm_if(ret < 0, false, "FAIL: ipc_request_client_init(&sock_remote)\n");
391 ret = request_to_usb_server(sock_remote, GET_ACC_INFO, buf, NULL);
392 um_retvm_if(ret < 0, false, "FAIL: request_to_usb_server(GET_ACC_INFO)\n");
393 USB_LOG("GET_ACC_INFO: %s\n", buf);
395 ret = ipc_request_client_close(&sock_remote);
396 um_retvm_if(ret < 0, false, "FAIL: ipc_request_client_close(&sock_remote)\n");
398 char *tempInfo = buf;
399 ret = getAccInfo(&tempInfo, &((*accList)->accessory));
400 um_retvm_if(ret < 0, false, "FAIL: getAccInfo(&tempInfo, accList)\n");
402 USB_LOG("Acc manufacturer: %s\n", (*accList)->accessory->manufacturer);
403 USB_LOG("Acc model: %s\n", (*accList)->accessory->model);
404 USB_LOG("Acc description: %s\n", (*accList)->accessory->description);
405 USB_LOG("Acc version: %s\n", (*accList)->accessory->version);
406 USB_LOG("Acc uri: %s\n", (*accList)->accessory->uri);
407 USB_LOG("Acc serial: %s\n", (*accList)->accessory->serial);
413 /* Release memory of accessory list */
414 bool freeAccList(struct usb_accessory_list *accList)
417 if (accList == NULL) return true;
418 struct usb_accessory_list *tmpList = NULL;
421 accList = accList->next;
422 FREE(tmpList->accessory);
439 USB_LOG("Machine name: %s", name.machine);
440 if (strcasestr(name.machine, "emul")) {