3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "usb_accessory_private.h"
20 /* This function initializes socket for ipc with usb-server */
21 int ipc_request_client_init(int *sock_remote)
24 if (!sock_remote) return -1;
26 struct sockaddr_un remote;
28 if (((*sock_remote) = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
30 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)");
33 remote.sun_family = AF_UNIX;
34 strncpy(remote.sun_path, SOCK_PATH, strlen(SOCK_PATH)+1);
35 len = strlen(remote.sun_path) + sizeof(remote.sun_family);
37 if (connect((*sock_remote), (struct sockaddr *)&remote, len) == -1) {
39 USB_LOG("FAIL: connect((*sock_remote), (struct sockaddr *)&remote, len)");
46 /* This function closes socket for ipc with usb-server */
47 int ipc_request_client_close(int *sock_remote)
50 if (!sock_remote) return -1;
56 /* This function requests something to usb-server by ipc with socket and gets the results */
57 int request_to_usb_server(int sock_remote, int request, char *answer, char *pkgName)
61 char str[SOCK_STR_LEN];
63 USB_LOG("request: %d, pkgName: %s\n", request, pkgName);
64 snprintf(str, SOCK_STR_LEN, "%d|%s", request, pkgName);
65 if (send (sock_remote, str, strlen(str)+1, 0) == -1) {
66 USB_LOG("FAIL: send (sock_remote, str, strlen(str)+1, 0)\n");
69 if ((t = recv(sock_remote, answer, SOCK_STR_LEN, 0)) > 0) {
70 if (t < SOCK_STR_LEN) {
72 } else { /* t == SOCK_STR_LEN */
73 answer[SOCK_STR_LEN-1] = '\0';
75 USB_LOG("[CLIENT] Received value: %s\n", answer);
77 USB_LOG("FAIL: recv(sock_remote, str, SOCK_STR_LEN, 0)\n");
84 int handle_input_to_server(void *data, char *buf)
89 struct AccCbData *permCbData = (struct AccCbData *)data;
90 int input = atoi(buf);
91 USB_LOG("Input: %d\n", input);
94 case REQ_ACC_PERM_NOTI_YES_BTN:
95 permCbData->accessory->accPermission = true;
96 permCbData->request_perm_cb_func((struct usb_accessory_s*)(permCbData->user_data), true);
98 case REQ_ACC_PERM_NOTI_NO_BTN:
99 permCbData->accessory->accPermission = false;
100 permCbData->request_perm_cb_func((struct usb_accessory_s*)(permCbData->user_data), false);
109 static int read_message(int fd, char *str, int len)
114 ret = read(fd, str, len);
116 if (EINTR == errno) {
117 USB_LOG("Re-read for error(EINTR)\n");
120 USB_LOG("FAIL: read(fd, str, len)\n");
130 int ipc_noti_client_init(void)
136 struct sockaddr_un serveraddr;
138 sock_local = socket(AF_UNIX, SOCK_STREAM, 0);
139 if (sock_local < 0) {
141 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)\n");
144 serveraddr.sun_family = AF_UNIX;
145 strncpy(serveraddr.sun_path, ACC_SOCK_PATH, strlen(ACC_SOCK_PATH)+1);
146 USB_LOG("socket file name: %s\n", serveraddr.sun_path);
147 unlink(serveraddr.sun_path);
148 len = strlen(serveraddr.sun_path) + sizeof(serveraddr.sun_family);
150 if (bind (sock_local, (struct sockaddr *)&serveraddr, len) < 0) {
152 USB_LOG("FAIL: bind (sock_local, (struct sockaddr_un *)serveraddr)\n");
157 ret = chown(ACC_SOCK_PATH, 5000, 5000);
158 if (ret < 0) USB_LOG("FAIL: chown(ACC_SOCK_PATH, 5000, 5000)");
159 ret = chmod(ACC_SOCK_PATH, 0777);
160 if (ret < 0) USB_LOG("FAIL: chmod(ACC_SOCK_PATH, 0777);");
162 if (listen (sock_local, 5) == -1) {
164 USB_LOG("FAIL: listen (sock_local, 5)\n");
173 int ipc_noti_client_close(int *sock_remote)
181 gboolean ipc_noti_client_cb(GIOChannel *g_io_ch, GIOCondition condition, gpointer data)
184 if (!data) return FALSE;
185 if (!g_io_ch) return FALSE;
188 struct sockaddr_un client_address;
191 char input_buf[SOCK_STR_LEN];
192 char output_buf[SOCK_STR_LEN];
196 fd = g_io_channel_unix_get_fd(g_io_ch);
198 USB_LOG("FAIL: g_io_channel_unix_get_fd(g_io_ch)\n");
199 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
200 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
201 g_io_channel_unref(g_io_ch);
205 client_len = sizeof(client_address);
206 client_sockfd = accept(fd, (struct sockaddr *)&client_address, (socklen_t *)&client_len);
207 if (client_sockfd == -1) {
209 USB_LOG("FAIL: accept(fd, (struct sockaddr *)&client_address, (socklen_t *)&client_len)\n");
210 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
211 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
212 g_io_channel_unref(g_io_ch);
213 ret = ipc_noti_client_close(&client_sockfd);
214 if (ret < 0) USB_LOG("FAIL: ipc_noti_client_close(client_sockfd)\n");
218 if(read_message(client_sockfd, input_buf, sizeof(input_buf)) < 0) {
219 USB_LOG("FAIL: read_message(client_sockfd, &buf)\n");
220 snprintf(output_buf, strlen("FAIL"), "%d", IPC_FAIL);
221 ret = write(client_sockfd, &output_buf, sizeof(output_buf));
222 if (ret < 0) USB_LOG("FAIL: write(client_sockfd, &output_buf, sizeof(output_buf))\n");
223 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
224 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
225 g_io_channel_unref(g_io_ch);
226 ret = ipc_noti_client_close(&client_sockfd);
227 if (ret < 0) USB_LOG("FAIL: ipc_noti_client_close(client_sockfd)\n");
230 USB_LOG("read(): %s\n", input_buf);
231 snprintf(output_buf, SOCK_STR_LEN, "%d", IPC_SUCCESS);
232 ret = write(client_sockfd, &output_buf, sizeof(output_buf));
233 if (ret < 0) USB_LOG("FAIL: write(client_sockfd, &output_buf, sizeof(output_buf))\n");
234 gio_ret = g_io_channel_shutdown(g_io_ch, TRUE, &err);
235 if (G_IO_STATUS_ERROR == gio_ret) USB_LOG("ERROR: g_io_channel_shutdown(g_io_ch)\n");
236 g_io_channel_unref(g_io_ch);
237 ret = ipc_noti_client_close(&client_sockfd);
238 if (ret < 0) USB_LOG("FAIL: ipc_noti_client_close(client_sockfd)\n");
240 ret = handle_input_to_server((void *)data, input_buf);
241 if (ret < 0) USB_LOG("FAIL: handle_input_to_server(input_buf, data)\n");
247 /* This function returns the app id.
248 * After calling this function, the memory space should be freed */
253 USB_LOG("pid: %d\n", pid);
254 char appId[APP_ID_LEN];
255 int ret = aul_app_get_appid_bypid(getpid(), appId, APP_ID_LEN);
256 um_retvm_if(AUL_R_OK != ret, NULL, "FAIL: aul_app_get_appid_bypid(getpid(), appId)\n");
258 return strdup(appId);
261 /* This function find an accessory attached just now
262 * Currently This function supports just one accessory */
263 static int getChangedAcc (struct usb_accessory_s **attAcc)
266 if (attAcc == NULL) return -1;
267 struct usb_accessory_list *accList = NULL;
270 accList = (struct usb_accessory_list *)malloc(sizeof(struct usb_accessory_list));
271 um_retvm_if(!accList, -1, "accList == NULL");
273 ret = getAccList(&accList);
275 USB_LOG("FAIL: getAccList(&accList)");
280 *attAcc = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
281 snprintf((*attAcc)->manufacturer, ACC_ELEMENT_LEN, "%s", accList->accessory->manufacturer);
282 snprintf((*attAcc)->model, ACC_ELEMENT_LEN, "%s", accList->accessory->model);
283 snprintf((*attAcc)->description, ACC_ELEMENT_LEN, "%s", accList->accessory->description);
284 snprintf((*attAcc)->version, ACC_ELEMENT_LEN, "%s", accList->accessory->version);
285 snprintf((*attAcc)->uri, ACC_ELEMENT_LEN, "%s", accList->accessory->uri);
286 snprintf((*attAcc)->serial, ACC_ELEMENT_LEN, "%s", accList->accessory->serial);
294 /* This func release memory of an accessory attached just now */
295 static int freeChangedAcc (struct usb_accessory_s **attAcc)
298 if (attAcc == NULL) return -1;
304 /* Callback function which is called when accessory vconf key is changed */
305 void accessory_status_changed_cb(keynode_t *in_key, void* data)
309 struct AccCbData *conCbData = (struct AccCbData *)data;
310 struct usb_accessory_s *changedAcc = NULL;
313 ret = vconf_get_int(VCONFKEY_USB_ACCESSORY_STATUS, &val);
314 um_retm_if(ret < 0, "FAIL: vconf_get_int(VCONFKEY_USB_ACCESSORY_STATUS)\n");
317 case VCONFKEY_USB_ACCESSORY_STATUS_DISCONNECTED:
318 conCbData->connection_cb_func(NULL, false, conCbData->user_data);
320 case VCONFKEY_USB_ACCESSORY_STATUS_CONNECTED:
321 ret = getChangedAcc(&changedAcc);
322 um_retm_if(ret < 0, "FAIL: getChangedAcc(&changedAcc)\n");
324 conCbData->connection_cb_func(changedAcc, true, conCbData->user_data);
326 ret = freeChangedAcc(&changedAcc);
327 um_retm_if(ret < 0, "FAIL: freeChangedAcc(&changedAcc)\n");
330 USB_LOG("ERROR: The value of VCONFKEY_USB_ACCESSORY_STATUS is invalid\n");
336 /* Get an element from a string which has all information of an accessory */
337 static bool getAccElement(char *totalInfo[], char accInfo[])
340 if (!totalInfo) return false;
341 if (!accInfo) return false;
343 char *finder = *totalInfo;
347 if (finder == NULL) {
348 USB_LOG("ERROR: finder == NULL");
352 if (*finder == '|' || *finder == '\0') {
354 snprintf(accInfo, ACC_ELEMENT_LEN, "%s", *totalInfo);
355 USB_LOG("Info: %s", accInfo);
356 *totalInfo = ++finder;
367 /* Get all element separated from a string which has all information of an accessory */
368 static int getAccInfo(char *totalInfo[], struct usb_accessory_s **accessory)
371 bool ret = getAccElement(totalInfo, (*accessory)->manufacturer);
372 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, manufacturer)\n");
373 ret = getAccElement(totalInfo, (*accessory)->model);
374 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, model)\n");
375 ret = getAccElement(totalInfo, (*accessory)->description);
376 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, description)\n");
377 ret = getAccElement(totalInfo, (*accessory)->version);
378 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, version)\n");
379 ret = getAccElement(totalInfo, (*accessory)->uri);
380 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, uri)\n");
381 ret = getAccElement(totalInfo, (*accessory)->serial);
382 um_retvm_if(ret == false, -1, "FAIL: getAccElement(totalInfo, serial)\n");
388 /* This function finds a list which contain all accessories attached
389 * Currently, Tizen usb accessory is designed for just one accessory */
390 bool getAccList(struct usb_accessory_list **accList)
393 if (accList == NULL || *accList == NULL) return false;
394 struct usb_accessory_s *accessory = NULL;
395 accessory = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
396 (*accList)->next = NULL;
397 (*accList)->accessory = accessory;
398 accessory->accPermission = false;
402 char buf[SOCK_STR_LEN];
403 ret = ipc_request_client_init(&sock_remote);
404 um_retvm_if(ret < 0, false, "FAIL: ipc_request_client_init(&sock_remote)\n");
406 ret = request_to_usb_server(sock_remote, GET_ACC_INFO, buf, NULL);
407 um_retvm_if(ret < 0, false, "FAIL: request_to_usb_server(GET_ACC_INFO)\n");
408 USB_LOG("GET_ACC_INFO: %s\n", buf);
410 ret = ipc_request_client_close(&sock_remote);
411 um_retvm_if(ret < 0, false, "FAIL: ipc_request_client_close(&sock_remote)\n");
413 char *tempInfo = buf;
414 ret = getAccInfo(&tempInfo, &((*accList)->accessory));
415 um_retvm_if(ret < 0, false, "FAIL: getAccInfo(&tempInfo, accList)\n");
417 USB_LOG("Acc manufacturer: %s\n", (*accList)->accessory->manufacturer);
418 USB_LOG("Acc model: %s\n", (*accList)->accessory->model);
419 USB_LOG("Acc description: %s\n", (*accList)->accessory->description);
420 USB_LOG("Acc version: %s\n", (*accList)->accessory->version);
421 USB_LOG("Acc uri: %s\n", (*accList)->accessory->uri);
422 USB_LOG("Acc serial: %s\n", (*accList)->accessory->serial);
428 /* Release memory of accessory list */
429 bool freeAccList(struct usb_accessory_list *accList)
432 if (accList == NULL) return true;
433 struct usb_accessory_list *tmpList = NULL;
436 accList = accList->next;
437 FREE(tmpList->accessory);
454 USB_LOG("Machine name: %s", name.machine);
455 if (strcasestr(name.machine, "emul")) {