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 #define NUM_ACC_INFO_SEPARATOR 5
22 static void show_acc_info(struct usb_accessory_s *accessory)
28 USB_LOG("*******************************");
29 USB_LOG("** Acc manufacturer: %s", accessory->manufacturer);
30 USB_LOG("** Acc model : %s", accessory->model);
31 USB_LOG("** Acc description : %s", accessory->description);
32 USB_LOG("** Acc version : %s", accessory->version);
33 USB_LOG("** Acc uri : %s", accessory->uri);
34 USB_LOG("** Acc serial : %s", accessory->serial);
35 USB_LOG("*******************************");
39 void free_accessory(struct usb_accessory_s *accessory)
44 FREE(accessory->manufacturer);
45 FREE(accessory->model);
46 FREE(accessory->description);
47 FREE(accessory->version);
49 FREE(accessory->serial);
55 /* Release memory of accessory list */
56 void free_acc_list(struct usb_accessory_list *accList)
60 struct usb_accessory_list *tmpList;
61 struct usb_accessory_s *accessory;
68 accList = accList->next;
69 accessory = tmpList->accessory;
71 free_accessory(accessory);
78 /* This function initializes socket for ipc with usb-server */
79 int ipc_request_client_init()
84 struct sockaddr_un remote;
86 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
87 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)");
91 remote.sun_family = AF_UNIX;
92 strncpy(remote.sun_path, SOCK_PATH, sizeof(remote.sun_path));
94 if (connect(sock, (struct sockaddr *)&remote, sizeof(remote)) == -1) {
95 USB_LOG("FAIL: connect(sock, (struct sockaddr *)&remote, len)");
104 /* This function requests something to usb-server by ipc with socket and gets the results */
105 int request_to_usb_server(int sockRemote, int request, void *data, char *answer, int answerLen)
110 char str[SOCK_STR_LEN];
117 case REQ_ACC_PERMISSION:
118 case HAS_ACC_PERMISSION:
119 pkgName = (char *)data;
120 USB_LOG("request: %d, pkgName: %s", request, pkgName);
121 snprintf(str, sizeof(str), "%d|%s", request, pkgName);
124 USB_LOG("request: %d", request);
125 snprintf(str, sizeof(str), "%d|", request);
129 if (send (sockRemote, str, strlen(str)+1, 0) == -1) {
130 USB_LOG("FAIL: send (sock_remote, str, strlen(str)+1, 0)");
134 if ((t = recv(sockRemote, answer, answerLen, 0)) > 0) {
137 } else { /* t == answerLen */
138 answer[answerLen-1] = '\0';
140 USB_LOG("[CLIENT] Received value: %s", answer);
146 USB_LOG("FAIL: recv(sock_remote, str, answerLen, 0)");
152 static int handle_input_to_server(void *data, char *buf)
156 struct AccCbData *permCbData;
164 permCbData = (struct AccCbData *)data;
166 USB_LOG("Input: %d", input);
169 case REQ_ACC_PERM_NOTI_YES_BTN:
170 permCbData->accessory->accPermission = true;
171 permCbData->request_perm_cb_func(
172 (struct usb_accessory_s*)(permCbData->user_data), true);
174 case REQ_ACC_PERM_NOTI_NO_BTN:
175 permCbData->accessory->accPermission = false;
176 permCbData->request_perm_cb_func(
177 (struct usb_accessory_s*)(permCbData->user_data), false);
180 USB_LOG("FAIL: buf (%s) is improper", buf);
187 static int read_message(int fd, char *str, int len)
196 ret = read(fd, str, len);
202 if (EINTR == errno) {
203 USB_LOG("Re-read for error(EINTR)");
207 USB_LOG("FAIL: read(fd, str, len)");
212 int ipc_noti_client_init(void)
217 struct sockaddr_un serveraddr;
219 sock_local = socket(AF_UNIX, SOCK_STREAM, 0);
220 if (sock_local < 0) {
221 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)");
225 serveraddr.sun_family = AF_UNIX;
226 strncpy(serveraddr.sun_path, ACC_SOCK_PATH, strlen(ACC_SOCK_PATH)+1);
227 USB_LOG("socket file name: %s", serveraddr.sun_path);
229 unlink(serveraddr.sun_path);
231 if (bind (sock_local, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
232 USB_LOG("FAIL: bind (sock_local, (struct sockaddr_un *)serveraddr)");
237 ret = chown(ACC_SOCK_PATH, 5000, 5000);
239 USB_LOG("FAIL: chown(ACC_SOCK_PATH, 5000, 5000)");
244 ret = chmod(ACC_SOCK_PATH, 0777);
246 USB_LOG("FAIL: chmod(ACC_SOCK_PATH, 0777);");
251 if (listen (sock_local, 5) == -1) {
252 USB_LOG("FAIL: listen (sock_local, 5)");
261 gboolean ipc_noti_client_cb(GIOChannel *gioCh, GIOCondition condition, gpointer data)
268 struct sockaddr_un clientaddr;
270 char inbuf[SOCK_STR_LEN];
271 char outbuf[SOCK_STR_LEN];
280 fd = g_io_channel_unix_get_fd(gioCh);
282 USB_LOG("FAIL: g_io_channel_unix_get_fd()");
286 clientlen = sizeof(clientaddr);
287 sockfd = accept(fd, (struct sockaddr *)&clientaddr, (socklen_t *)&clientlen);
289 USB_LOG("FAIL: accept()");
293 if(read_message(sockfd, inbuf, sizeof(inbuf)) < 0) {
294 USB_LOG("FAIL: read_message()");
295 snprintf(outbuf, sizeof(outbuf), "%d", IPC_FAIL);
296 if (0 > write(sockfd, &outbuf, sizeof(outbuf)))
297 USB_LOG("FAIL: write()");
301 USB_LOG("read(): %s", inbuf);
302 snprintf(outbuf, sizeof(outbuf), "%d", IPC_SUCCESS);
303 ret = write(sockfd, &outbuf, sizeof(outbuf));
305 USB_LOG("FAIL: write()");
307 ret = handle_input_to_server((void *)data, inbuf);
309 USB_LOG("FAIL: handle_input_to_server()");
314 gret = g_io_channel_shutdown(gioCh, TRUE, &err);
315 if (G_IO_STATUS_ERROR == gret)
316 USB_LOG("ERROR: g_io_channel_shutdown(gioCh)");
317 g_io_channel_unref(gioCh);
323 /* This function returns the app id.
324 * After calling this function, the memory space should be freed */
330 char appId[APP_ID_LEN];
332 ret = aul_app_get_appid_bypid(getpid(), appId, sizeof(appId));
333 if (ret != AUL_R_OK) {
334 USB_LOG("FAIL: aul_app_get_appid_bypid()");
338 USB_LOG("appId: %s", appId);
341 return strdup(appId);
344 /* Get an element from a string which has all information of an accessory */
345 static bool get_acc_element(char **totalInfo, char **info)
351 if (!totalInfo || !(*totalInfo))
359 if (*finder != '|' && *finder != '\0') {
365 *info = strdup(*totalInfo);
366 USB_LOG("Info: %s", *info);
367 *totalInfo = ++finder;
376 /* Get all element separated from a string which has all information of an accessory */
377 static int get_acc_info(char *totalInfo, struct usb_accessory_s **accessory)
387 if (!accessory || !(*accessory))
390 /* Check whether or not the format of the accessory info is correct to parse */
393 while(*tmpInfo != '\0') {
398 if (numSepBar != NUM_ACC_INFO_SEPARATOR) {
399 USB_LOG("FAIL: Format of string (%s) is improper", totalInfo);
405 ret = get_acc_element(&tmpInfo, &((*accessory)->manufacturer));
409 ret = get_acc_element(&tmpInfo, &((*accessory)->model));
411 goto out_release_manufacturer;
413 ret = get_acc_element(&tmpInfo, &((*accessory)->description));
415 goto out_release_model;
417 ret = get_acc_element(&tmpInfo, &((*accessory)->version));
419 goto out_release_description;
421 ret = get_acc_element(&tmpInfo, &((*accessory)->uri));
423 goto out_release_version;
425 ret = get_acc_element(&tmpInfo, &((*accessory)->serial));
427 goto out_release_uri;
429 (*accessory)->accPermission = false;
435 FREE((*accessory)->uri);
437 FREE((*accessory)->version);
438 out_release_description:
439 FREE((*accessory)->description);
441 FREE((*accessory)->model);
442 out_release_manufacturer:
443 FREE((*accessory)->manufacturer);
449 /* This function finds a list which contain all accessories attached
450 * Currently, Tizen usb accessory is designed for just one accessory */
451 bool get_acc_list(struct usb_accessory_list **accList)
455 struct usb_accessory_s *accessory;
458 char buf[SOCK_STR_LEN];
460 if (!accList || !(*accList))
463 sock_remote = ipc_request_client_init();
464 if (sock_remote < 0) {
465 USB_LOG("FAIL: ipc_request_client_init()");
469 ret = request_to_usb_server(sock_remote, GET_ACC_INFO, NULL, buf, sizeof(buf));
471 USB_LOG("FAIL: request_to_usb_server(GET_ACC_INFO)");
475 USB_LOG("GET_ACC_INFO: %s", buf);
479 accessory = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
481 USB_LOG("FAIL: malloc()");
485 ret = get_acc_info(buf, &accessory);
487 USB_LOG("FAIL: get_acc_info()");
491 (*accList)->next = NULL;
492 (*accList)->accessory = accessory;
494 show_acc_info((*accList)->accessory);
500 /* This function find an accessory attached just now
501 * Currently This function supports just one accessory */
502 static int get_changed_acc (struct usb_accessory_s *attAcc)
506 struct usb_accessory_list *accList;
512 accList = (struct usb_accessory_list *)malloc(sizeof(struct usb_accessory_list));
514 USB_LOG("FAIL: malloc()");
518 ret = get_acc_list(&accList);
520 USB_LOG("FAIL: get_acc_list()");
521 free_acc_list(accList);
525 if (!(accList->accessory)) {
526 USB_LOG("FAIL: accList->accessory == NULL");
527 free_acc_list(accList);
531 attAcc->manufacturer = strdup(accList->accessory->manufacturer);
532 attAcc->model = strdup(accList->accessory->model);
533 attAcc->description = strdup(accList->accessory->description);
534 attAcc->version = strdup(accList->accessory->version);
535 attAcc->uri = strdup(accList->accessory->uri);
536 attAcc->serial = strdup(accList->accessory->serial);
538 free_acc_list(accList);
544 /* Callback function which is called when accessory vconf key is changed */
545 void accessory_status_changed_cb(keynode_t *key, void* data)
549 struct AccCbData *conCbData;
550 struct usb_accessory_s *changedAcc;
557 conCbData = (struct AccCbData *)data;
559 ret = vconf_get_int(VCONFKEY_USB_ACCESSORY_STATUS, &val);
561 USB_LOG("FAIL: vconf_get_int()");
566 case VCONFKEY_USB_ACCESSORY_STATUS_DISCONNECTED:
567 conCbData->connection_cb_func(NULL, false, conCbData->user_data);
570 case VCONFKEY_USB_ACCESSORY_STATUS_CONNECTED:
571 changedAcc = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
573 USB_LOG("FAIL: malloc()");
577 ret = get_changed_acc(changedAcc);
579 USB_LOG("FAIL: get_changed_acc()");
580 free_accessory(changedAcc);
584 conCbData->connection_cb_func(changedAcc, true, conCbData->user_data);
586 free_accessory(changedAcc);
590 USB_LOG("ERROR: The value of VCONFKEY_USB_ACCESSORY_STATUS is invalid");
607 USB_LOG("Machine name: %s", name.machine);
608 if (strcasestr(name.machine, "emul")) {