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 #include <tzplatform_config.h>
22 #define NUM_ACC_INFO_SEPARATOR 5
24 static void show_acc_info(struct usb_accessory_s *accessory)
30 USB_LOG("*******************************");
31 USB_LOG("** Acc manufacturer: %s", accessory->manufacturer);
32 USB_LOG("** Acc model : %s", accessory->model);
33 USB_LOG("** Acc description : %s", accessory->description);
34 USB_LOG("** Acc version : %s", accessory->version);
35 USB_LOG("** Acc uri : %s", accessory->uri);
36 USB_LOG("** Acc serial : %s", accessory->serial);
37 USB_LOG("*******************************");
41 void free_accessory(struct usb_accessory_s *accessory)
46 FREE(accessory->manufacturer);
47 FREE(accessory->model);
48 FREE(accessory->description);
49 FREE(accessory->version);
51 FREE(accessory->serial);
57 /* Release memory of accessory list */
58 void free_acc_list(struct usb_accessory_list *accList)
62 struct usb_accessory_list *tmpList;
63 struct usb_accessory_s *accessory;
70 accList = accList->next;
71 accessory = tmpList->accessory;
73 free_accessory(accessory);
80 /* This function initializes socket for ipc with usb-server */
81 int ipc_request_client_init()
86 struct sockaddr_un remote;
88 if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
89 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)");
93 remote.sun_family = AF_UNIX;
94 strncpy(remote.sun_path, SOCK_PATH, sizeof(remote.sun_path));
96 if (connect(sock, (struct sockaddr *)&remote, sizeof(remote)) == -1) {
97 USB_LOG("FAIL: connect(sock, (struct sockaddr *)&remote, len)");
106 /* This function requests something to usb-server by ipc with socket and gets the results */
107 int request_to_usb_server(int sockRemote, int request, void *data, char *answer, int answerLen)
112 char str[SOCK_STR_LEN];
119 case REQ_ACC_PERMISSION:
120 case HAS_ACC_PERMISSION:
121 pkgName = (char *)data;
122 USB_LOG("request: %d, pkgName: %s", request, pkgName);
123 snprintf(str, sizeof(str), "%d|%s", request, pkgName);
126 USB_LOG("request: %d", request);
127 snprintf(str, sizeof(str), "%d|", request);
131 if (send (sockRemote, str, strlen(str)+1, 0) == -1) {
132 USB_LOG("FAIL: send (sock_remote, str, strlen(str)+1, 0)");
136 if ((t = recv(sockRemote, answer, answerLen, 0)) > 0) {
139 } else { /* t == answerLen */
140 answer[answerLen-1] = '\0';
142 USB_LOG("[CLIENT] Received value: %s", answer);
148 USB_LOG("FAIL: recv(sock_remote, str, answerLen, 0)");
154 static int handle_input_to_server(void *data, char *buf)
158 struct AccCbData *permCbData;
166 permCbData = (struct AccCbData *)data;
168 USB_LOG("Input: %d", input);
171 case REQ_ACC_PERM_NOTI_YES_BTN:
172 permCbData->accessory->accPermission = true;
173 permCbData->request_perm_cb_func(
174 (struct usb_accessory_s*)(permCbData->user_data), true);
176 case REQ_ACC_PERM_NOTI_NO_BTN:
177 permCbData->accessory->accPermission = false;
178 permCbData->request_perm_cb_func(
179 (struct usb_accessory_s*)(permCbData->user_data), false);
182 USB_LOG("FAIL: buf (%s) is improper", buf);
189 static int read_message(int fd, char *str, int len)
198 ret = read(fd, str, len);
204 if (EINTR == errno) {
205 USB_LOG("Re-read for error(EINTR)");
209 USB_LOG("FAIL: read(fd, str, len)");
214 int ipc_noti_client_init(void)
219 struct sockaddr_un serveraddr;
221 sock_local = socket(AF_UNIX, SOCK_STREAM, 0);
222 if (sock_local < 0) {
223 USB_LOG("FAIL: socket(AF_UNIX, SOCK_STREAM, 0)");
227 serveraddr.sun_family = AF_UNIX;
228 strncpy(serveraddr.sun_path, ACC_SOCK_PATH, strlen(ACC_SOCK_PATH)+1);
229 USB_LOG("socket file name: %s", serveraddr.sun_path);
231 unlink(serveraddr.sun_path);
233 if (bind (sock_local, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
234 USB_LOG("FAIL: bind (sock_local, (struct sockaddr_un *)serveraddr)");
239 ret = chown(ACC_SOCK_PATH,tzplatform_getuid(TZ_USER_NAME),tzplatform_getgid(TZ_USER_NAME));
241 USB_LOG("FAIL: chown(ACC_SOCK_PATH, tzplatform_getuid(TZ_USER_NAME),tzplatform_getgid(TZ_USER_NAME))");
246 ret = chmod(ACC_SOCK_PATH, 0777);
248 USB_LOG("FAIL: chmod(ACC_SOCK_PATH, 0777);");
253 if (listen (sock_local, 5) == -1) {
254 USB_LOG("FAIL: listen (sock_local, 5)");
263 gboolean ipc_noti_client_cb(GIOChannel *gioCh, GIOCondition condition, gpointer data)
270 struct sockaddr_un clientaddr;
272 char inbuf[SOCK_STR_LEN];
273 char outbuf[SOCK_STR_LEN];
282 fd = g_io_channel_unix_get_fd(gioCh);
284 USB_LOG("FAIL: g_io_channel_unix_get_fd()");
288 clientlen = sizeof(clientaddr);
289 sockfd = accept(fd, (struct sockaddr *)&clientaddr, (socklen_t *)&clientlen);
291 USB_LOG("FAIL: accept()");
295 if(read_message(sockfd, inbuf, sizeof(inbuf)) < 0) {
296 USB_LOG("FAIL: read_message()");
297 snprintf(outbuf, sizeof(outbuf), "%d", IPC_FAIL);
298 if (0 > write(sockfd, &outbuf, sizeof(outbuf)))
299 USB_LOG("FAIL: write()");
303 USB_LOG("read(): %s", inbuf);
304 snprintf(outbuf, sizeof(outbuf), "%d", IPC_SUCCESS);
305 ret = write(sockfd, &outbuf, sizeof(outbuf));
307 USB_LOG("FAIL: write()");
309 ret = handle_input_to_server((void *)data, inbuf);
311 USB_LOG("FAIL: handle_input_to_server()");
316 gret = g_io_channel_shutdown(gioCh, TRUE, &err);
317 if (G_IO_STATUS_ERROR == gret)
318 USB_LOG("ERROR: g_io_channel_shutdown(gioCh)");
319 g_io_channel_unref(gioCh);
325 /* This function returns the app id.
326 * After calling this function, the memory space should be freed */
332 char appId[APP_ID_LEN];
334 ret = aul_app_get_appid_bypid(getpid(), appId, sizeof(appId));
335 if (ret != AUL_R_OK) {
336 USB_LOG("FAIL: aul_app_get_appid_bypid()");
340 USB_LOG("appId: %s", appId);
343 return strdup(appId);
346 /* Get an element from a string which has all information of an accessory */
347 static bool get_acc_element(char **totalInfo, char **info)
353 if (!totalInfo || !(*totalInfo))
361 if (*finder != '|' && *finder != '\0') {
367 *info = strdup(*totalInfo);
368 USB_LOG("Info: %s", *info);
369 *totalInfo = ++finder;
378 /* Get all element separated from a string which has all information of an accessory */
379 static int get_acc_info(char *totalInfo, struct usb_accessory_s **accessory)
389 if (!accessory || !(*accessory))
392 /* Check whether or not the format of the accessory info is correct to parse */
395 while(*tmpInfo != '\0') {
400 if (numSepBar != NUM_ACC_INFO_SEPARATOR) {
401 USB_LOG("FAIL: Format of string (%s) is improper", totalInfo);
407 ret = get_acc_element(&tmpInfo, &((*accessory)->manufacturer));
411 ret = get_acc_element(&tmpInfo, &((*accessory)->model));
413 goto out_release_manufacturer;
415 ret = get_acc_element(&tmpInfo, &((*accessory)->description));
417 goto out_release_model;
419 ret = get_acc_element(&tmpInfo, &((*accessory)->version));
421 goto out_release_description;
423 ret = get_acc_element(&tmpInfo, &((*accessory)->uri));
425 goto out_release_version;
427 ret = get_acc_element(&tmpInfo, &((*accessory)->serial));
429 goto out_release_uri;
431 (*accessory)->accPermission = false;
437 FREE((*accessory)->uri);
439 FREE((*accessory)->version);
440 out_release_description:
441 FREE((*accessory)->description);
443 FREE((*accessory)->model);
444 out_release_manufacturer:
445 FREE((*accessory)->manufacturer);
451 /* This function finds a list which contain all accessories attached
452 * Currently, Tizen usb accessory is designed for just one accessory */
453 bool get_acc_list(struct usb_accessory_list **accList)
457 struct usb_accessory_s *accessory;
460 char buf[SOCK_STR_LEN];
462 if (!accList || !(*accList))
465 sock_remote = ipc_request_client_init();
466 if (sock_remote < 0) {
467 USB_LOG("FAIL: ipc_request_client_init()");
471 ret = request_to_usb_server(sock_remote, GET_ACC_INFO, NULL, buf, sizeof(buf));
473 USB_LOG("FAIL: request_to_usb_server(GET_ACC_INFO)");
477 USB_LOG("GET_ACC_INFO: %s", buf);
481 accessory = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
483 USB_LOG("FAIL: malloc()");
487 ret = get_acc_info(buf, &accessory);
489 USB_LOG("FAIL: get_acc_info()");
493 (*accList)->next = NULL;
494 (*accList)->accessory = accessory;
496 show_acc_info((*accList)->accessory);
502 /* This function find an accessory attached just now
503 * Currently This function supports just one accessory */
504 static int get_changed_acc (struct usb_accessory_s *attAcc)
508 struct usb_accessory_list *accList;
514 accList = (struct usb_accessory_list *)malloc(sizeof(struct usb_accessory_list));
516 USB_LOG("FAIL: malloc()");
520 ret = get_acc_list(&accList);
522 USB_LOG("FAIL: get_acc_list()");
523 free_acc_list(accList);
527 if (!(accList->accessory)) {
528 USB_LOG("FAIL: accList->accessory == NULL");
529 free_acc_list(accList);
533 attAcc->manufacturer = strdup(accList->accessory->manufacturer);
534 attAcc->model = strdup(accList->accessory->model);
535 attAcc->description = strdup(accList->accessory->description);
536 attAcc->version = strdup(accList->accessory->version);
537 attAcc->uri = strdup(accList->accessory->uri);
538 attAcc->serial = strdup(accList->accessory->serial);
540 free_acc_list(accList);
546 /* Callback function which is called when accessory vconf key is changed */
547 void accessory_status_changed_cb(keynode_t *key, void* data)
551 struct AccCbData *conCbData;
552 struct usb_accessory_s *changedAcc;
559 conCbData = (struct AccCbData *)data;
561 ret = vconf_get_int(VCONFKEY_USB_ACCESSORY_STATUS, &val);
563 USB_LOG("FAIL: vconf_get_int()");
568 case VCONFKEY_USB_ACCESSORY_STATUS_DISCONNECTED:
569 conCbData->connection_cb_func(NULL, false, conCbData->user_data);
572 case VCONFKEY_USB_ACCESSORY_STATUS_CONNECTED:
573 changedAcc = (struct usb_accessory_s *)malloc(sizeof(struct usb_accessory_s));
575 USB_LOG("FAIL: malloc()");
579 ret = get_changed_acc(changedAcc);
581 USB_LOG("FAIL: get_changed_acc()");
582 free_accessory(changedAcc);
586 conCbData->connection_cb_func(changedAcc, true, conCbData->user_data);
588 free_accessory(changedAcc);
592 USB_LOG("ERROR: The value of VCONFKEY_USB_ACCESSORY_STATUS is invalid");
609 USB_LOG("Machine name: %s", name.machine);
610 if (strcasestr(name.machine, "emul")) {