/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2014 Instituto Nokia de Tecnologia - INdT * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gdbus/gdbus.h" #include "src/error.h" #include "wifi_util_wrapper.h" #define GATT_MGR_IFACE "org.bluez.GattManager1" #define GATT_SERVICE_IFACE "org.bluez.GattService1" #define GATT_CHR_IFACE "org.bluez.GattCharacteristic1" #define GATT_DESCRIPTOR_IFACE "org.bluez.GattDescriptor1" /* Immediate wifi Service UUID */ #define WIFI_SERVICES_UUID "1B7E8251-2877-41C3-B46E-CF057C562023" #define SECURITY_CHAR_UUID "CAC2ABA4-EDBB-4C4A-BBAF-0A84A5CD93A1" #define HIDE_CHAR_UUID "CAC2ABA4-EDBB-4C4A-BBAF-0A84A5CD26C7" #define SSID_CHAR_UUID "ACA0EF7C-EEAA-48AD-9508-19A6CEF6B356" #define PASSWORD_CHAR_UUID "40B7DE33-93E4-4C8B-A876-D833B415A6CE" #define CHECKDATA_CHAR_UUID "40B7DE33-93E4-4C8B-A876-D833B415C759" #define NOTIFY_CHAR_UUID "8AC32D3f-5CB9-4D44-BEC2-EE689169F626" #define NOTIFY_DESC_UUID "00002902-0000-1000-8000-00805f9b34fb" #define WIFILIST_CHAR_UUID "8AC32D3f-5CB9-4D44-BEC2-EE689169F627" #define DEVICECONTEXT_CHAR_UUID "8AC32D3f-5CB9-4D44-BEC2-EE689169F628" #define BT_NAME "Yami" static char reconnect_path[66]; #ifdef DUEROS #define DUEROS_WIFI_SERVICES_UUID "00001111-0000-1000-8000-00805f9b34fb" #define DUEROS_CHARACTERISTIC_UUID "00002222-0000-1000-8000-00805f9b34fb" #define DUEROS_SOCKET_RECV_LEN 20 static pthread_t dueros_tid = 0; static int dueros_socket_done = 0; static int dueros_socket_fd = -1; static char dueros_socket_path[] = "/data/bluez5_utils/socket_dueros"; struct characteristic *dueros_chr; typedef struct{ int server_sockfd; int client_sockfd; int server_len; int client_len; struct sockaddr_un server_address; struct sockaddr_un client_address; char sock_path[512]; } tAPP_SOCKET; #define CMD_ADV "hcitool -i hci0 cmd 0x08 0x0008 15 02 01 06 11 07 fb 34 9b 5f 80 00 00 80 00 10 00 00 11 11 00 00" #else #define SERVICES_UUID "23 20 56 7c 05 cf 6e b4 c3 41 77 28 51 82 7e 1b" #endif #define CMD_PARA "hcitool -i hci0 cmd 0x08 0x0006 A0 00 A0 00 00 02 00 00 00 00 00 00 00 07 00" #define CMD_EN "hcitool -i hci0 cmd 0x08 0x000a 1" #define ADV_IRK "\x69\x30\xde\xc3\x8f\x84\x74\x14" \ const char *WIFI_CONFIG_FORMAT = "ctrl_interface=/var/run/wpa_supplicant\nap_scan=1\nupdate_config=1\n\n"; const char *WIFI_CONFIG_FORMAT_PSK = "network={\n ssid=\"%s\"\n" " key_mgmt=%s\n psk=\"%s\"\n scan_ssid=%s\n" " priority=%d\n}\n\n"; const char *WIFI_CONFIG_FORMAT_NONE = "network={\n ssid=\"%s\"\n" " key_mgmt=%s\n scan_ssid=%s\n" " priority=%d\n}\n\n"; const char *WIFI_CONFIG_FORMAT_WEP = "network={\n ssid=\"%s\"\n" " key_mgmt=%s\n wep_key0=\"%s\"\n scan_ssid=%s\n" " priority=%d\n}\n\n"; static GMainLoop *main_loop; static GSList *services; static DBusConnection *connection; static pthread_t wificonfig_tid = 0; char wifi_ssid[256]; char wifi_ssid_bk[256]; char wifi_password[256]; char wifi_password_bk[256]; char wifi_security[256]; char wifi_hide[256]; char check_data[256]; int priority = 0; struct characteristic *temp_chr; struct characteristic { char *service; char *uuid; char *path; uint8_t *value; int vlen; const char **props; }; struct descriptor { struct characteristic *chr; char *uuid; char *path; uint8_t *value; int vlen; const char **props; }; /* * Supported properties are defined at doc/gatt-api.txt. See "Flags" * property of the GattCharacteristic1. */ static const char *ias_alert_level_props[] = { "read", "write", NULL }; static const char *chr_props[] = { "read", "write", "notify", NULL }; static const char *desc_props[] = { "read", "write", NULL }; static void chr_write(struct characteristic *chr, const uint8_t *value, int len); static void chr_iface_destroy(gpointer user_data); #ifdef DUEROS /********************SERVER API***************************/ static int setup_socket_server(tAPP_SOCKET *app_socket) { unlink (app_socket->sock_path); if ((app_socket->server_sockfd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) { printf("fail to create socket\n"); perror("socket"); return -1; } app_socket->server_address.sun_family = AF_UNIX; strcpy (app_socket->server_address.sun_path, app_socket->sock_path); app_socket->server_len = sizeof (app_socket->server_address); app_socket->client_len = sizeof (app_socket->client_address); if ((bind (app_socket->server_sockfd, (struct sockaddr *)&app_socket->server_address, app_socket->server_len)) < 0) { perror("bind"); return -1; } if (listen (app_socket->server_sockfd, 10) < 0) { perror("listen"); return -1; } printf ("Server is ready for client connect...\n"); return 0; } static int accpet_client(tAPP_SOCKET *app_socket) { app_socket->client_sockfd = accept (app_socket->server_sockfd, (struct sockaddr *)&app_socket->server_address, (socklen_t *)&app_socket->client_len); if (app_socket->client_sockfd == -1) { perror ("accept"); return -1; } return 0; } static void teardown_socket_server(tAPP_SOCKET *app_socket) { unlink (app_socket->sock_path); app_socket->server_sockfd = 0; app_socket->client_sockfd = 0; } /********************CLIENT API***************************/ static int setup_socket_client(char *socket_path) { struct sockaddr_un address; int sockfd, len; if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { printf("%s: can not creat socket\n", __func__); return -1; } address.sun_family = AF_UNIX; strcpy (address.sun_path, socket_path); len = sizeof (address); if (connect (sockfd, (struct sockaddr *)&address, len) == -1) { printf("%s: can not connect to socket\n", __func__);; return -1; } return sockfd; } static void teardown_socket_client(int sockfd) { close(sockfd); } /********************COMMON API***************************/ static int socket_send(int sockfd, char *msg, int len) { int bytes; if (sockfd < 0) { printf("%s: invalid sockfd\n",__func__); return -1; } if ((bytes = send(sockfd, msg, len, 0)) < 0) { perror ("send"); } return bytes; } static int socket_recieve(int sockfd, char *msg, int len) { int bytes; if (sockfd < 0) { printf("%s: invalid sockfd\n",__func__); return -1; } if ((bytes = recv(sockfd, msg, len, 0)) < 0) { perror ("recv"); } return bytes; } static int dueros_socket_send(char *msg, int len) { return socket_send(dueros_socket_fd, msg, len); } static void *dueros_socket_recieve(void *arg) { int bytes = 0; char data[DUEROS_SOCKET_RECV_LEN]; dueros_socket_fd = setup_socket_client(dueros_socket_path); if (dueros_socket_fd < 0) { printf("Fail to connect server socket\n"); goto exit; } while (dueros_socket_done) { memset(data, 0, sizeof(data)); bytes = socket_recieve(dueros_socket_fd, data, sizeof(data)); if (bytes <= 0) { printf("Server leaved, break\n"); break; } printf("dueros_socket_recieve, len: %d\n", bytes); for(int i = 0; i < bytes; i++) printf("%02x ", data[i]); printf("\n\n"); //send to apk chr_write(dueros_chr, (uint8_t *) data, bytes); usleep(1000000); //sleep 1s } exit: printf("Exit dueros socket thread\n"); pthread_exit(0); } static int dueros_socket_thread_create(void) { dueros_socket_done = 1; if (pthread_create(&dueros_tid, NULL, dueros_socket_recieve, NULL)) { printf("Create dueros socket thread failed\n"); return -1; } return 0; } static void dueros_socket_thread_delete(void) { dueros_socket_done = 0; teardown_socket_client(dueros_socket_fd); if (dueros_tid) { pthread_join(dueros_tid, NULL); dueros_tid = 0; } } #endif static bool saveCheckdata(int flag, char * info) { FILE *fp; int fd; if (flag == 0) fp = fopen("/data/cfg/check_data", "w"); else if (flag == 1) fp = fopen("/data/cfg/bt_status", "w"); else if (flag == 2) fp = fopen("/data/cfg/wifi_ssid", "w"); if (fp == NULL) { return -1; } fputs(info, fp); fflush(fp); fd = fileno(fp); if (fd >= 0) { fsync(fd); printf("save check_data sucecees.\n"); } fclose(fp); return 0; } static gboolean desc_get_uuid(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { struct descriptor *desc = user_data; dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &desc->uuid); return TRUE; } static gboolean desc_get_characteristic(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { struct descriptor *desc = user_data; dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &desc->chr->path); return TRUE; } static bool desc_read(struct descriptor *desc, DBusMessageIter *iter) { DBusMessageIter array; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &array); if (desc->vlen && desc->value) dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE, &desc->value, desc->vlen); dbus_message_iter_close_container(iter, &array); return true; } static gboolean desc_get_value(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { struct descriptor *desc = user_data; printf("Descriptor(%s): Get(\"Value\")\n", desc->uuid); return desc_read(desc, iter); } static void desc_write(struct descriptor *desc, const uint8_t *value, int len) { g_free(desc->value); desc->value = g_memdup(value, len); desc->vlen = len; g_dbus_emit_property_changed(connection, desc->path, GATT_DESCRIPTOR_IFACE, "Value"); } static int parse_value(DBusMessageIter *iter, const uint8_t **value, int *len) { DBusMessageIter array; if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) return -EINVAL; dbus_message_iter_recurse(iter, &array); dbus_message_iter_get_fixed_array(&array, value, len); return 0; } static void desc_set_value(const GDBusPropertyTable *property, DBusMessageIter *iter, GDBusPendingPropertySet id, void *user_data) { struct descriptor *desc = user_data; const uint8_t *value; int len; printf("Descriptor(%s): Set(\"Value\", ...)\n", desc->uuid); if (parse_value(iter, &value, &len)) { printf("Invalid value for Set('Value'...)\n"); g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments", "Invalid arguments in method call"); return; } desc_write(desc, value, len); g_dbus_pending_property_success(id); } static gboolean desc_get_props(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { struct descriptor *desc = data; DBusMessageIter array; int i; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array); for (i = 0; desc->props[i]; i++) dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &desc->props[i]); dbus_message_iter_close_container(iter, &array); return TRUE; } static const GDBusPropertyTable desc_properties[] = { { "UUID", "s", desc_get_uuid }, { "Characteristic", "o", desc_get_characteristic }, { "Value", "ay", desc_get_value, desc_set_value, NULL }, { "Flags", "as", desc_get_props, NULL, NULL }, { } }; static gboolean chr_get_uuid(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { struct characteristic *chr = user_data; dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &chr->uuid); return TRUE; } static gboolean chr_get_service(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { struct characteristic *chr = user_data; dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &chr->service); return TRUE; } static bool chr_read(struct characteristic *chr, DBusMessageIter *iter) { DBusMessageIter array; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &array); dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE, &chr->value, chr->vlen); dbus_message_iter_close_container(iter, &array); return true; } static gboolean chr_get_value(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { struct characteristic *chr = user_data; printf("Characteristic(%s): Get(\"Value\")\n", chr->uuid); return chr_read(chr, iter); } static gboolean chr_get_props(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { struct characteristic *chr = data; DBusMessageIter array; int i; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array); for (i = 0; chr->props[i]; i++) dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &chr->props[i]); dbus_message_iter_close_container(iter, &array); return TRUE; } static void chr_write(struct characteristic *chr, const uint8_t *value, int len) { g_free(chr->value); chr->value = g_memdup(value, len); chr->vlen = len; g_dbus_emit_property_changed(connection, chr->path, GATT_CHR_IFACE, "Value"); } static void chr_set_value(const GDBusPropertyTable *property, DBusMessageIter *iter, GDBusPendingPropertySet id, void *user_data) { struct characteristic *chr = user_data; const uint8_t *value; int len; printf("Characteristic(%s): Set('Value', ...)\n", chr->uuid); if (!parse_value(iter, &value, &len)) { printf("Invalid value for Set('Value'...)\n"); g_dbus_pending_property_error(id, ERROR_INTERFACE ".InvalidArguments", "Invalid arguments in method call"); return; } chr_write(chr, value, len); g_dbus_pending_property_success(id); } static const GDBusPropertyTable chr_properties[] = { { "UUID", "s", chr_get_uuid }, { "Service", "o", chr_get_service }, { "Value", "ay", chr_get_value, chr_set_value, NULL }, { "Flags", "as", chr_get_props, NULL, NULL }, { } }; static gboolean service_get_primary(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { dbus_bool_t primary = TRUE; printf("Get Primary: %s\n", primary ? "True" : "False"); dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &primary); return TRUE; } static gboolean service_get_uuid(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { const char *uuid = user_data; printf("Get UUID: %s\n", uuid); dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid); return TRUE; } static gboolean service_get_includes(const GDBusPropertyTable *property, DBusMessageIter *iter, void *user_data) { const char *uuid = user_data; char service_path[100] = {0,}; DBusMessageIter array; char *p = NULL; snprintf(service_path, 100, "/service3"); printf("Get Includes: %s\n", uuid); p = service_path; printf("Includes path: %s\n", p); dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH_AS_STRING, &array); dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH, &p); snprintf(service_path, 100, "/service2"); p = service_path; printf("Get Includes: %s\n", p); dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH, &p); dbus_message_iter_close_container(iter, &array); return TRUE; } static gboolean service_exist_includes(const GDBusPropertyTable *property, void *user_data) { const char *uuid = user_data; printf("Exist Includes: %s\n", uuid); #ifdef DUEROS if (strncmp(uuid, "00001111", 8) == 0) return TRUE; #else if (strncmp(uuid, "1B7E8251", 8) == 0) return TRUE; #endif return FALSE; } static const GDBusPropertyTable service_properties[] = { { "Primary", "b", service_get_primary }, { "UUID", "s", service_get_uuid }, { "Includes", "ao", service_get_includes, NULL, service_exist_includes }, { } }; static void chr_iface_destroy(gpointer user_data) { struct characteristic *chr = user_data; g_free(chr->uuid); g_free(chr->service); g_free(chr->value); g_free(chr->path); g_free(chr); } static void desc_iface_destroy(gpointer user_data) { struct descriptor *desc = user_data; g_free(desc->uuid); g_free(desc->value); g_free(desc->path); g_free(desc); } static int parse_options(DBusMessageIter *iter, const char **device) { DBusMessageIter dict; if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) return -EINVAL; dbus_message_iter_recurse(iter, &dict); while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { const char *key; DBusMessageIter value, entry; int var; dbus_message_iter_recurse(&dict, &entry); dbus_message_iter_get_basic(&entry, &key); dbus_message_iter_next(&entry); dbus_message_iter_recurse(&entry, &value); var = dbus_message_iter_get_arg_type(&value); if (strcasecmp(key, "device") == 0) { if (var != DBUS_TYPE_OBJECT_PATH) return -EINVAL; dbus_message_iter_get_basic(&value, device); printf("Device: %s\n", *device); } dbus_message_iter_next(&dict); } return 0; } void check_wifiinfo(int flag, char * info) { char temp[1024]; char buff[256] = {0}; char cmdline[256] = {0}; int j = 0; if (flag == 0) { for (int i = 0; i < strlen(info); i++) { sprintf(temp+2*i, "%02x", info[i]); } temp[strlen(info)*2] = '\0'; strcpy(info, temp); printf("check_wifiinfo ssid: %s\n", info); } else if (flag == 1){ memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -iwlan0 scan_result | grep %s", wifi_ssid_bk); execute("wpa_cli -iwlan0 scan", buff); execute(cmdline, buff); if (strstr(buff, "WPA") != NULL) strcpy(wifi_security, "WPA-PSK"); else if (strstr(buff, "ESS") != NULL && strstr(buff, "WPA") == NULL) strcpy(wifi_security, "NONE"); printf("check_wifiinfo security: %s\n", wifi_security); } else if (flag == 2) { for(int i = 0; i < strlen(info); i++) { temp[j++] = '\\'; temp[j++] = info[i]; } temp[j] = '\0'; strcpy(info, temp); printf("check_wifiinfo password: %s\n", info); } } void execute(const char cmdline[],char recv_buff[]){ printf("consule_run: %s\n",cmdline); FILE *stream = NULL; char buff[1024]; memset(recv_buff, 0, sizeof(recv_buff)); if((stream = popen(cmdline,"r"))!=NULL){ while(fgets(buff,1024,stream)){ strcat(recv_buff,buff); } } pclose(stream); } //wpa_supplicant static int wpa_supplicant_config_wifi() { FILE *fp = NULL; if ((fp = fopen("/data/cfg/wpa_supplicant.conf", "w+")) == NULL) { printf("open cfg wpa_supplicant.conf failed"); return -1; } fprintf(fp, "%s\n", "ctrl_interface=/var/run/wpa_supplicant"); fprintf(fp, "%s\n", "ap_scan=1"); fprintf(fp, "%s\n", "network={"); fprintf(fp, "%s%s%s\n", "ssid=\"", wifi_ssid, "\""); fprintf(fp, "%s%s%s\n", "psk=\"", wifi_password, "\""); fprintf(fp, "%s\n", "key_mgmt=WPA-PSK"); fprintf(fp, "%s\n", "}"); fclose(fp); if (-1 == system("killall wpa_supplicant; dhcpcd -k wlan0; killall dhcpcd;" "ifconfig wlan0 0.0.0.0")) { printf("killall wpa_supplicant dhcpcd failed"); return -1; } if (-1 == system("wpa_supplicant -Dnl80211 -i wlan0 " "-c /data/cfg/wpa_supplicant.conf &")) { printf("start wpa_supplicant failed"); return -1; } if (-1 == system("dhcpcd wlan0 -t 0 &")) { printf("dhcpcd failed"); return -1; } return 0; } //wpa_cli static gboolean config_wifi() { printf("start config_wifi\n"); char buff[256] = {0}; char cmdline[256] = {0}; int id = -1; bool execute_result = false; execute("wpa_cli -iwlan0 disconnect",buff); usleep(500000); // 1. add network execute("wpa_cli -iwlan0 add_network",buff); id = atoi(buff); if(id < 0){ perror("add_network failed.\n"); return FALSE; } priority = id + 1; // 2. setNetWorkSSID if (wifi_ssid != NULL && strlen(wifi_ssid) != 0) check_wifiinfo(0, wifi_ssid); memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -iwlan0 set_network %d ssid %s",id, wifi_ssid); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result){ perror("setNetWorkSSID failed.\n"); return FALSE; } // 3. setNetWorkSECURe check_wifiinfo(1, wifi_security); memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -iwlan0 set_network %d key_mgmt %s", id,wifi_security); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result){ perror("setNetWorkSECURe failed.\n"); return FALSE; } // 4. setNetWorkPWD if (wifi_password != NULL && strlen(wifi_password) != 0) check_wifiinfo(2, wifi_password); if (strcmp(wifi_security, "NONE")) { memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -iwlan0 set_network %d psk \\\"%s\\\"", id,wifi_password); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result){ perror("setNetWorkPWD failed.\n"); return FALSE; } } else if (strcmp(wifi_security, "NONE") == 0) { printf("wifi_security is NONE! ignore the password\n"); } else { if (wifi_password_bk != NULL && strlen(wifi_password_bk) != 0) { memset(cmdline, 0, sizeof(cmdline)); if(strlen(wifi_password_bk) == 10 || strlen(wifi_password_bk) == 26) sprintf(cmdline,"wpa_cli -iwlan0 set_network %d wep_key0 %s", id,wifi_password); else sprintf(cmdline,"wpa_cli -iwlan0 set_network %d wep_key0 \\\"%s\\\"", id,wifi_password); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result) { perror("setNetWorkPWD failed.\n"); return FALSE; } } } // 5. setNetWorkHIDE memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -iwlan0 set_network %d scan_ssid %s", id,wifi_hide); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result){ perror("setNetWorkHIDE failed.\n"); return FALSE; } // 6. setNetWorkPriority memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -iwlan0 set_network %d priority %d", id, id + 1); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result){ perror("setNetWorkPriority failed.\n"); return FALSE; } // 7. enableNetWork memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -iwlan0 enable_network %d", id); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result){ perror("enableNetWork failed.\n"); return FALSE; } //execute("wpa_cli save_config", buff); //execute("wpa_cli reconfig", buff); memset(cmdline, 0, sizeof(cmdline)); sprintf(cmdline,"wpa_cli -i wlan0 select_network %d", id); memset(reconnect_path, 0, 66); strcpy(reconnect_path, cmdline); printf("repath: %s.\n", reconnect_path); printf("%s\n", cmdline); execute(cmdline,buff); execute_result = !strncmp(buff,"OK",2); if(!execute_result){ perror("select_network failed.\n"); return FALSE; } return TRUE; } static bool save_wifi_config(int mode) { char buff[256] = {0}; char cmdline[256] = {0}; //7. save config if (mode == 1) { execute("wpa_cli save_config", buff); execute("wpa_cli reconfigure", buff); } else { execute("wpa_cli flush", buff); usleep(600000); execute("wpa_cli reconfigure", buff); execute("wpa_cli reconnect", buff); } return 0; /* if (mode == 1){ FILE *fp; char body[256]; int fd; int isFileExit = 0; if((access("/data/cfg/wpa_supplicant.conf",F_OK))!=-1) isFileExit = 1; else isFileExit = 0; fp = fopen("/data/cfg/wpa_supplicant.conf", "a+"); if (fp == NULL) return -1; if (isFileExit == 0){ snprintf(body, sizeof(body), WIFI_CONFIG_FORMAT); fputs(body, fp); } if (strcmp(wifi_security, "NONE")) snprintf(body, sizeof(body), WIFI_CONFIG_FORMAT_PSK, wifi_ssid_bk, wifi_security, wifi_password_bk, wifi_hide, priority); if (!strcmp(wifi_security, "NONE") && strlen(wifi_password_bk) > 0) snprintf(body, sizeof(body), WIFI_CONFIG_FORMAT_WEP, wifi_ssid_bk, wifi_security, wifi_password_bk, wifi_hide, priority); if (strlen(wifi_password_bk) == 0) snprintf(body, sizeof(body), WIFI_CONFIG_FORMAT_NONE, wifi_ssid_bk, wifi_security, wifi_hide, priority); fputs(body, fp); fflush(fp); fd = fileno(fp); if (fd >= 0) { fsync(fd); printf("save wpa_supplicant.conf sucecees.\n"); } fclose(fp); execute("wpa_cli reconfig", buff); } else { execute("wpa_cli flush", buff); } return 0; */ } static gboolean check_wifi_isconnected() { printf("check_wifi_isconnected\n"); char ret_buff[256] = {0}; char temp_buff[256] = {0}; gboolean isWifiConnected = FALSE; int retry = 1; char *str = NULL; char *str1 = NULL; reconnect: for(int i = 0; i < 20; i++) { printf("check wifi ...\n"); usleep(500000); execute("wpa_cli -iwlan0 status | grep wpa_state", ret_buff); strncpy(temp_buff, ret_buff+10, strlen(ret_buff) - 11); printf("wpa_cli status %s\n", temp_buff); if (strncmp(temp_buff, "COMPLETED", 9) == 0) { usleep(500000); execute("wpa_cli -iwlan0 status | grep ip_address", ret_buff); if (strlen(ret_buff) > 0) { strncpy(temp_buff, ret_buff+11, strlen(ret_buff) - 12); printf("wpa_cli ip_address %s\n", temp_buff); if ((strncmp(temp_buff, "127.0.0.1", 9) != 0) && (strncmp(temp_buff, "169", 3) != 0)) { //if (strncmp(temp_buff, "127.0.0.1", 9) != 0) { memset(ret_buff, 0, 256); memset(temp_buff, 0, 256); execute("wpa_cli -iwlan0 status | grep ssid", ret_buff); if ((str = strstr(ret_buff, "bssid"))) { str1 = strstr(str+5, "ssid"); strncpy(temp_buff, str1+5, strlen(wifi_ssid_bk)); printf("wpa_cli ssid %s %d\n", temp_buff, strlen(wifi_ssid_bk)); if (strncmp(temp_buff, wifi_ssid_bk, strlen(wifi_ssid_bk)) != 0) return FALSE; } isWifiConnected = TRUE; printf("wifi is connected.\n"); break; } } } if (strncmp(temp_buff, "DISCONNECTED", 12) == 0) execute(reconnect_path, temp_buff); } if ((!isWifiConnected) && (retry-- > 0)) { execute(reconnect_path, ret_buff); goto reconnect; } if (!isWifiConnected) printf("wifi is not connected.\n"); return isWifiConnected; } static void *config_wifi_thread(void) { printf("config_wifi_thread\n"); uint8_t level = 1; saveCheckdata(0, check_data); if (!config_wifi()) { printf("### config_wifi failed sleep !!! ###\n"); save_wifi_config(0); level = 2; printf("### confs to notify level 2 ###\n"); chr_write(temp_chr, &level, sizeof(level)); //return; goto clean; } if (check_wifi_isconnected()) { save_wifi_config(1); level = 1; printf("### cons to notify level 1 ###\n"); chr_write(temp_chr, &level, sizeof(level)); g_main_loop_quit(main_loop); } else { save_wifi_config(0); level = 2; printf("### conf to notify level 2 ###\n"); chr_write(temp_chr, &level, sizeof(level)); } clean: memset(wifi_ssid, 0, 256); memset(wifi_ssid_bk, 0, 256); memset(wifi_password, 0, 256); memset(wifi_password_bk, 0, 256); memset(wifi_security, 0, 256); memset(wifi_hide, 0, 256); } static int wifi_config_thread_create(void) { if (pthread_create(&wificonfig_tid, NULL, config_wifi_thread, NULL)) { printf("Create wifi config thread failed\n"); return -1; } return 0; } static int wifi_config_thread_cancel(void) { if (pthread_cancel(&wificonfig_tid)) { printf("Cancle wifi config thread failed\n"); return -1; } return 0; } #define BLE_SEND_MAX_LEN (134) //(20) //(512) static DBusMessage *chr_read_value(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct characteristic *chr = user_data; DBusMessage *reply; DBusMessageIter iter; const char *device; static char *slist = NULL; static char *devicesn = NULL; char str[512]; if (!dbus_message_iter_init(msg, &iter)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); if (parse_options(&iter, &device)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); reply = dbus_message_new_method_return(msg); if (!reply) return g_dbus_create_error(msg, DBUS_ERROR_NO_MEMORY, "No Memory"); dbus_message_iter_init_append(reply, &iter); if (!strcmp(WIFILIST_CHAR_UUID, chr->uuid)) { if (!slist) { slist = get_wifi_list(); printf("%s: wifi total list is %s, len=%d\n", __func__, slist, strlen(slist)); } int len; char *tmp = slist; len = strlen(slist); chr_write(chr, slist, (len > BLE_SEND_MAX_LEN) ? BLE_SEND_MAX_LEN : len); if (len > BLE_SEND_MAX_LEN) { slist = strdup(slist + BLE_SEND_MAX_LEN); free(tmp); } else { free(slist); slist = NULL; } } if (!strcmp(DEVICECONTEXT_CHAR_UUID, chr->uuid)) { if (!devicesn) { devicesn = get_device_context(); printf("%s device context: %s\n", __func__, devicesn); } int len; char *tmp = devicesn; len = strlen(devicesn); chr_write(chr, devicesn, (len > BLE_SEND_MAX_LEN) ? BLE_SEND_MAX_LEN : len); if (len > BLE_SEND_MAX_LEN) { devicesn = strdup(devicesn + BLE_SEND_MAX_LEN); free(tmp); } else { free(devicesn); devicesn = NULL; } } chr_read(chr, &iter); strncpy(str, chr->value, chr->vlen); str[chr->vlen] = '\0'; printf("chr_read_value[%d]: %s\n", chr->vlen, str); return reply; } static DBusMessage *chr_write_value(DBusConnection *conn, DBusMessage *msg, void *user_data) { printf("chr_write_value v0.3\n"); struct characteristic *chr = user_data; DBusMessageIter iter; const uint8_t *value; int len; const char *device; char str[120]; memset(str, 0, 120); dbus_message_iter_init(msg, &iter); if (parse_value(&iter, &value, &len)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); if (parse_options(&iter, &device)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); //chr_write(chr, value, len); #ifdef DUEROS printf("chr_write_value, len: %d\n", len); for(int i = 0; i < len; i++) printf("%02x ", value[i]); printf("\n\n"); if (!strcmp(DUEROS_CHARACTERISTIC_UUID, chr->uuid)) { dueros_socket_send((char *) value, len); } //chr_write(chr, "1111111111", 10); #else if (((int)(chr->value) & 0x3) || chr->value == NULL) { printf("######chr_write chr->value: %p, value: %s, len: %d\n", chr->value, value, len); //return dbus_message_new_method_return(msg); } chr_write(chr, value, len); if(len == 0 || chr->value == NULL) { printf("chr_write_value is null\n"); strcpy(wifi_password, ""); return dbus_message_new_method_return(msg); } //chr->value[len] = '\0'; strncpy(str, chr->value, len); str[len] = '\0'; printf("chr_write_value %p, %d\n", chr->value, len); if (!strcmp(SSID_CHAR_UUID, chr->uuid)){ strcpy(wifi_ssid, str); strcpy(wifi_ssid_bk, str); saveCheckdata(2, wifi_ssid_bk); printf("wifi ssid is %s, bk: %s\n", wifi_ssid, wifi_ssid_bk); } if (!strcmp(PASSWORD_CHAR_UUID, chr->uuid)){ strcpy(wifi_password, str); strcpy(wifi_password_bk, str); printf("wifi pwd is %s\n", wifi_password); } if (!strcmp(HIDE_CHAR_UUID, chr->uuid)){ strcpy(wifi_hide, str); printf("wifi hide is %s\n", wifi_hide); } if (!strcmp(SECURITY_CHAR_UUID, chr->uuid)){ strcpy(wifi_security, str); printf("wifi sec is %s\n", wifi_security); } if (!strcmp(CHECKDATA_CHAR_UUID, chr->uuid)){ strncpy(check_data, str, len); printf("check_data is %s\n", check_data); #if 0 wpa_cli_config_wifi(); save_wifi_config(wifi_ssid, wifi_password); #else wifi_config_thread_create(); #endif } #endif return dbus_message_new_method_return(msg); } static DBusMessage *chr_start_notify(DBusConnection *conn, DBusMessage *msg, void *user_data) { return g_dbus_create_error(msg, DBUS_ERROR_NOT_SUPPORTED, "Not Supported"); } static DBusMessage *chr_stop_notify(DBusConnection *conn, DBusMessage *msg, void *user_data) { return g_dbus_create_error(msg, DBUS_ERROR_NOT_SUPPORTED, "Not Supported"); } static const GDBusMethodTable chr_methods[] = { { GDBUS_ASYNC_METHOD("ReadValue", GDBUS_ARGS({ "options", "a{sv}" }), GDBUS_ARGS({ "value", "ay" }), chr_read_value) }, { GDBUS_ASYNC_METHOD("WriteValue", GDBUS_ARGS({ "value", "ay" }, { "options", "a{sv}" }), NULL, chr_write_value) }, { GDBUS_ASYNC_METHOD("StartNotify", NULL, NULL, chr_start_notify) }, { GDBUS_METHOD("StopNotify", NULL, NULL, chr_stop_notify) }, { } }; static DBusMessage *desc_read_value(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct descriptor *desc = user_data; DBusMessage *reply; DBusMessageIter iter; const char *device; if (!dbus_message_iter_init(msg, &iter)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); if (parse_options(&iter, &device)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); reply = dbus_message_new_method_return(msg); if (!reply) return g_dbus_create_error(msg, DBUS_ERROR_NO_MEMORY, "No Memory"); dbus_message_iter_init_append(reply, &iter); desc_read(desc, &iter); return reply; } static DBusMessage *desc_write_value(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct descriptor *desc = user_data; DBusMessageIter iter; const char *device; const uint8_t *value; int len; if (!dbus_message_iter_init(msg, &iter)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); if (parse_value(&iter, &value, &len)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); if (parse_options(&iter, &device)) return g_dbus_create_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid arguments"); desc_write(desc, value, len); return dbus_message_new_method_return(msg); } static const GDBusMethodTable desc_methods[] = { { GDBUS_ASYNC_METHOD("ReadValue", GDBUS_ARGS({ "options", "a{sv}" }), GDBUS_ARGS({ "value", "ay" }), desc_read_value) }, { GDBUS_ASYNC_METHOD("WriteValue", GDBUS_ARGS({ "value", "ay" }, { "options", "a{sv}" }), NULL, desc_write_value) }, { } }; static gboolean register_characteristic(const char *chr_uuid, const uint8_t *value, int vlen, const char **props, const char *desc_uuid, const char **desc_props, const char *service_path) { struct characteristic *chr; struct descriptor *desc; static int id = 1; chr = g_new0(struct characteristic, 1); chr->uuid = g_strdup(chr_uuid); chr->value = g_memdup(value, vlen); chr->vlen = vlen; chr->props = props; chr->service = g_strdup(service_path); chr->path = g_strdup_printf("%s/characteristic%d", service_path, id++); if (!g_dbus_register_interface(connection, chr->path, GATT_CHR_IFACE, chr_methods, NULL, chr_properties, chr, chr_iface_destroy)) { printf("Couldn't register characteristic interface\n"); chr_iface_destroy(chr); return FALSE; } if (strcmp(chr_uuid, NOTIFY_CHAR_UUID) == 0) { printf("save temp characteristic\n"); temp_chr = chr; } if (!desc_uuid) return TRUE; desc = g_new0(struct descriptor, 1); desc->uuid = g_strdup(desc_uuid); desc->chr = chr; desc->props = desc_props; desc->path = g_strdup_printf("%s/descriptor%d", chr->path, id++); if (!g_dbus_register_interface(connection, desc->path, GATT_DESCRIPTOR_IFACE, desc_methods, NULL, desc_properties, desc, desc_iface_destroy)) { printf("Couldn't register descriptor interface\n"); g_dbus_unregister_interface(connection, chr->path, GATT_CHR_IFACE); desc_iface_destroy(desc); return FALSE; } #ifdef DUEROS if (strcmp(chr_uuid, DUEROS_CHARACTERISTIC_UUID) == 0) { printf("save dueros characteristic\n"); dueros_chr = chr; } #endif return TRUE; } static char *register_service(const char *uuid) { static int id = 1; char *path; path = g_strdup_printf("/service%d", id++); if (!g_dbus_register_interface(connection, path, GATT_SERVICE_IFACE, NULL, NULL, service_properties, g_strdup(uuid), g_free)) { printf("Couldn't register service interface\n"); g_free(path); return NULL; } return path; } #ifdef DUEROS static void create_wifi_services(void) { char *service_path; uint8_t level = ' '; service_path = register_service(DUEROS_WIFI_SERVICES_UUID); if (!service_path) return; gboolean mSsidPassword = register_characteristic(DUEROS_CHARACTERISTIC_UUID, &level, sizeof(level), chr_props, CONFIG_UUID, /*NULL*/ desc_props, service_path); /* Add Wifi Config Characteristic to Immediate Wifi Config Service */ if (!mSsidPassword) { printf("Couldn't register wifi config characteristic (IAS)\n"); g_dbus_unregister_interface(connection, service_path, GATT_SERVICE_IFACE); g_free(service_path); return; } services = g_slist_prepend(services, service_path); printf("Registered service: %s\n", service_path); } #else static void create_wifi_services(void) { char *service_path; uint8_t level = ' '; service_path = register_service(WIFI_SERVICES_UUID); if (!service_path) return; gboolean mSecure = register_characteristic(SECURITY_CHAR_UUID, &level, sizeof(level), ias_alert_level_props, NULL, desc_props, service_path); gboolean mHide = register_characteristic(HIDE_CHAR_UUID, &level, sizeof(level), ias_alert_level_props, NULL, desc_props, service_path); gboolean mSsid = register_characteristic(SSID_CHAR_UUID, &level, sizeof(level), ias_alert_level_props, NULL, desc_props, service_path); gboolean mPassword = register_characteristic(PASSWORD_CHAR_UUID, &level, sizeof(level), ias_alert_level_props, NULL, desc_props, service_path); gboolean mCheckdata = register_characteristic(CHECKDATA_CHAR_UUID, &level, sizeof(level), ias_alert_level_props, NULL, desc_props, service_path); gboolean mConfigCharNotify = register_characteristic(NOTIFY_CHAR_UUID, &level, sizeof(level), chr_props, NULL, desc_props, service_path); gboolean mWifiListNotify = register_characteristic(WIFILIST_CHAR_UUID, &level, sizeof(level), chr_props, NULL, desc_props, service_path); gboolean mDeviceContextNotify = register_characteristic(DEVICECONTEXT_CHAR_UUID, &level, sizeof(level), ias_alert_level_props, NULL, desc_props, service_path); /* Add Alert Level Characteristic to Immediate Alert Service */ if (!mSecure || !mHide || !mSsid || !mPassword || !mCheckdata || !mConfigCharNotify || !mWifiListNotify || !mDeviceContextNotify) { printf("Couldn't register Alert Level characteristic (IAS)\n"); g_dbus_unregister_interface(connection, service_path, GATT_SERVICE_IFACE); g_free(service_path); return; } services = g_slist_prepend(services, service_path); printf("Registered service: %s\n", service_path); } #endif static void send_advertise(){ printf("send_advertise\n"); char buff[256] = {0}; char addr[6]; char CMD_RA[256] = "hcitool -i hci0 cmd 0x08 0x0005"; char CMD_ADV_DATA[256] = "hcitool -i hci0 cmd 0x08 0x0008 "; char temp[256]; int len = 21; //3 + 18 flag+uuid //creat random address int i; srand(time(NULL)); for(i = 0; i < 6;i++) addr[i]=rand()&0xFF; addr[0] &= 0x3f; /* Clear two most significant bits */ addr[0] |= 0x40; /* Set second most significant bit */ for(i = 0; i < 6;i++) { sprintf(temp,"%02x", addr[i]); strcat(CMD_RA, " "); strcat(CMD_RA, temp); } printf ("%s\n", CMD_RA); //LE Set Random Address Command execute(CMD_RA, buff); sleep(1); //LE SET PARAMETERS //execute(CMD_PARA, buff); // LE Set Advertising Data Command //len = len + strlen(BT_NAME) +2; sprintf(temp,"%02x", len); strcat(CMD_ADV_DATA, temp); //add len strcat(CMD_ADV_DATA, " 02 01 06 11 07 "); //add flag strcat(CMD_ADV_DATA, SERVICES_UUID); //add uuid /* sprintf(temp,"%02x", strlen(BT_NAME) + 1); strcat(CMD_ADV_DATA, " "); strcat(CMD_ADV_DATA, temp); strcat(CMD_ADV_DATA, " 09"); for (i = 0; i < strlen(BT_NAME); i++) { strcat(CMD_ADV_DATA, " "); sprintf(temp,"%02x", BT_NAME[i]); strcat(CMD_ADV_DATA, temp); } */ execute(CMD_ADV_DATA, buff); sleep(1); // LE Set Advertise Enable Command execute(CMD_EN, buff); } static void register_app_reply(DBusMessage *reply, void *user_data) { printf("register_app_reply\n"); DBusError derr; dbus_error_init(&derr); dbus_set_error_from_message(&derr, reply); if (dbus_error_is_set(&derr)) printf("RegisterApplication: %s\n", derr.message); else printf("RegisterApplication: OK\n"); send_advertise(); dbus_error_free(&derr); } static void register_app_setup(DBusMessageIter *iter, void *user_data) { const char *path = "/"; DBusMessageIter dict; dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &dict); /* TODO: Add options dictionary */ dbus_message_iter_close_container(iter, &dict); } static void register_app(GDBusProxy *proxy) { if (!g_dbus_proxy_method_call(proxy, "RegisterApplication", register_app_setup, register_app_reply, NULL, NULL)) { printf("Unable to call RegisterApplication\n"); return; } } struct adapter { GDBusProxy *proxy; GDBusProxy *ad_proxy; GList *devices; }; static struct adapter *default_ctrl; static GList *ctrl_list; static GDBusProxy *default_dev; static GDBusProxy *default_attr; #undef bt_shell_printf #define bt_shell_printf printf static gboolean device_is_child(GDBusProxy *device, GDBusProxy *master) { DBusMessageIter iter; const char *adapter, *path; if (!master) return FALSE; if (g_dbus_proxy_get_property(device, "Adapter", &iter) == FALSE) return FALSE; dbus_message_iter_get_basic(&iter, &adapter); path = g_dbus_proxy_get_path(master); if (!strcmp(path, adapter)) return TRUE; return FALSE; } static struct adapter *find_ctrl(GList *source, const char *path) { GList *list; for (list = g_list_first(source); list; list = g_list_next(list)) { struct adapter *adapter = list->data; if (!strcasecmp(g_dbus_proxy_get_path(adapter->proxy), path)) return adapter; } return NULL; } static void set_default_device(GDBusProxy *proxy, const char *attribute) { char *desc = NULL; DBusMessageIter iter; const char *path; default_dev = proxy; if (proxy == NULL) { default_attr = NULL; goto done; } if (!g_dbus_proxy_get_property(proxy, "Alias", &iter)) { if (!g_dbus_proxy_get_property(proxy, "Address", &iter)) goto done; } path = g_dbus_proxy_get_path(proxy); dbus_message_iter_get_basic(&iter, &desc); desc = g_strdup_printf("[%s%s%s]# ", desc, attribute ? ":" : "", attribute ? attribute + strlen(path) : ""); done: g_free(desc); } static struct adapter *adapter_new(GDBusProxy *proxy) { struct adapter *adapter = g_malloc0(sizeof(struct adapter)); ctrl_list = g_list_append(ctrl_list, adapter); if (!default_ctrl) default_ctrl = adapter; return adapter; } static void proxy_added_cb(GDBusProxy *proxy, void *user_data) { const char *iface; iface = g_dbus_proxy_get_interface(proxy); if (!strcmp(iface, "org.bluez.Adapter1")) { printf(" new org.bluez.Adapter1\n"); { struct adapter *adapter; adapter = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy)); if (!adapter) adapter = adapter_new(proxy); adapter->proxy = proxy; //print_adapter(proxy, COLORED_NEW); //bt_shell_set_env(g_dbus_proxy_get_path(proxy), proxy); } } if (g_strcmp0(iface, GATT_MGR_IFACE)) return; register_app(proxy); } static void print_fixed_iter(const char *label, const char *name, DBusMessageIter *iter) { dbus_bool_t *valbool; dbus_uint32_t *valu32; dbus_uint16_t *valu16; dbus_int16_t *vals16; unsigned char *byte; int len; switch (dbus_message_iter_get_arg_type(iter)) { case DBUS_TYPE_BOOLEAN: dbus_message_iter_get_fixed_array(iter, &valbool, &len); if (len <= 0) return; bt_shell_printf("%s%s:\n", label, name); //bt_shell_hexdump((void *)valbool, len * sizeof(*valbool)); break; case DBUS_TYPE_UINT32: dbus_message_iter_get_fixed_array(iter, &valu32, &len); if (len <= 0) return; bt_shell_printf("%s%s:\n", label, name); //bt_shell_hexdump((void *)valu32, len * sizeof(*valu32)); break; case DBUS_TYPE_UINT16: dbus_message_iter_get_fixed_array(iter, &valu16, &len); if (len <= 0) return; bt_shell_printf("%s%s:\n", label, name); //bt_shell_hexdump((void *)valu16, len * sizeof(*valu16)); break; case DBUS_TYPE_INT16: dbus_message_iter_get_fixed_array(iter, &vals16, &len); if (len <= 0) return; bt_shell_printf("%s%s:\n", label, name); //bt_shell_hexdump((void *)vals16, len * sizeof(*vals16)); break; case DBUS_TYPE_BYTE: dbus_message_iter_get_fixed_array(iter, &byte, &len); if (len <= 0) return; bt_shell_printf("%s%s:\n", label, name); //bt_shell_hexdump((void *)byte, len * sizeof(*byte)); break; default: return; }; } static void print_iter(const char *label, const char *name, DBusMessageIter *iter) { dbus_bool_t valbool; dbus_uint32_t valu32; dbus_uint16_t valu16; dbus_int16_t vals16; unsigned char byte; const char *valstr; DBusMessageIter subiter; char *entry; if (iter == NULL) { bt_shell_printf("%s%s is nil\n", label, name); return; } switch (dbus_message_iter_get_arg_type(iter)) { case DBUS_TYPE_INVALID: bt_shell_printf("%s%s is invalid\n", label, name); break; case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: dbus_message_iter_get_basic(iter, &valstr); bt_shell_printf("%s%s: %s\n", label, name, valstr); break; case DBUS_TYPE_BOOLEAN: dbus_message_iter_get_basic(iter, &valbool); bt_shell_printf("%s%s: %s\n", label, name, valbool == TRUE ? "yes" : "no"); if(!strcmp(name, "ServicesResolved")){ if (valbool != TRUE) { send_advertise(); saveCheckdata(1, "0"); } else { saveCheckdata(1, "1"); } } break; case DBUS_TYPE_UINT32: dbus_message_iter_get_basic(iter, &valu32); bt_shell_printf("%s%s: 0x%08x\n", label, name, valu32); break; case DBUS_TYPE_UINT16: dbus_message_iter_get_basic(iter, &valu16); bt_shell_printf("%s%s: 0x%04x\n", label, name, valu16); break; case DBUS_TYPE_INT16: dbus_message_iter_get_basic(iter, &vals16); bt_shell_printf("%s%s: %d\n", label, name, vals16); break; case DBUS_TYPE_BYTE: dbus_message_iter_get_basic(iter, &byte); bt_shell_printf("%s%s: 0x%02x\n", label, name, byte); break; case DBUS_TYPE_VARIANT: dbus_message_iter_recurse(iter, &subiter); print_iter(label, name, &subiter); break; case DBUS_TYPE_ARRAY: dbus_message_iter_recurse(iter, &subiter); if (dbus_type_is_fixed( dbus_message_iter_get_arg_type(&subiter))) { print_fixed_iter(label, name, &subiter); break; } while (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_INVALID) { print_iter(label, name, &subiter); dbus_message_iter_next(&subiter); } break; case DBUS_TYPE_DICT_ENTRY: dbus_message_iter_recurse(iter, &subiter); entry = g_strconcat(name, " Key", NULL); print_iter(label, entry, &subiter); g_free(entry); entry = g_strconcat(name, " Value", NULL); dbus_message_iter_next(&subiter); print_iter(label, entry, &subiter); g_free(entry); break; default: bt_shell_printf("%s%s has unsupported type\n", label, name); break; } } static void property_changed(GDBusProxy *proxy, const char *name, DBusMessageIter *iter, void *user_data) { const char *interface; struct adapter *ctrl; interface = g_dbus_proxy_get_interface(proxy); printf("xxxh : property_changed: %s\n", interface); if (!strcmp(interface, "org.bluez.Device1")) { if (default_ctrl != NULL) printf("xxxh : default_ctrl is not null\n"); if (default_ctrl && device_is_child(proxy, default_ctrl->proxy) == TRUE) { DBusMessageIter addr_iter; char *str; if (g_dbus_proxy_get_property(proxy, "Address", &addr_iter) == TRUE) { const char *address; dbus_message_iter_get_basic(&addr_iter,&address); str = g_strdup_printf("[CHG] Device: %s ", address); } else str = g_strdup(""); if (strcmp(name, "Connected") == 0) { dbus_bool_t connected; dbus_message_iter_get_basic(iter, &connected); if (connected && default_dev == NULL) { set_default_device(proxy, NULL); } else if (!connected && default_dev == proxy) { set_default_device(NULL, NULL); } } print_iter(str, name, iter); g_free(str); } } else if (!strcmp(interface, "org.bluez.Adapter1")) { DBusMessageIter addr_iter; char *str; if (g_dbus_proxy_get_property(proxy, "Address", &addr_iter) == TRUE) { const char *address; dbus_message_iter_get_basic(&addr_iter, &address); str = g_strdup_printf("[CHG] Controller %s ", address); } else str = g_strdup(""); print_iter(str, name, iter); g_free(str); } else if (!strcmp(interface, "org.bluez.LEAdvertisingManager1")) { DBusMessageIter addr_iter; char *str; ctrl = find_ctrl(ctrl_list, g_dbus_proxy_get_path(proxy)); if (!ctrl) return; if (g_dbus_proxy_get_property(ctrl->proxy, "Address", &addr_iter) == TRUE) { const char *address; dbus_message_iter_get_basic(&addr_iter, &address); str = g_strdup_printf("[CHG] Controller %s ", address); } else str = g_strdup(""); print_iter(str, name, iter); g_free(str); } else if (proxy == default_attr) { char *str; str = g_strdup_printf("[CHG] Attribute %s ", g_dbus_proxy_get_path(proxy)); print_iter(str, name, iter); g_free(str); } } static gboolean signal_handler(GIOChannel *channel, GIOCondition cond, gpointer user_data) { static bool __terminated = false; struct signalfd_siginfo si; ssize_t result; int fd; if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) return FALSE; fd = g_io_channel_unix_get_fd(channel); result = read(fd, &si, sizeof(si)); if (result != sizeof(si)) return FALSE; switch (si.ssi_signo) { case SIGINT: case SIGTERM: if (!__terminated) { printf("Terminating\n"); g_main_loop_quit(main_loop); } __terminated = true; break; } return TRUE; } static guint setup_signalfd(void) { GIOChannel *channel; guint source; sigset_t mask; int fd; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) { perror("Failed to set signal mask"); return 0; } fd = signalfd(-1, &mask, 0); if (fd < 0) { perror("Failed to create signal descriptor"); return 0; } channel = g_io_channel_unix_new(fd); g_io_channel_set_close_on_unref(channel, TRUE); g_io_channel_set_encoding(channel, NULL, NULL); g_io_channel_set_buffered(channel, FALSE); source = g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, signal_handler, NULL); g_io_channel_unref(channel); return source; } int main(int argc, char *argv[]) { GDBusClient *client; guint signal; signal = setup_signalfd(); if (signal == 0) return -errno; connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL); main_loop = g_main_loop_new(NULL, FALSE); g_dbus_attach_object_manager(connection); printf("gatt-service unique name: %s\n", dbus_bus_get_unique_name(connection)); #ifdef DUEROS dueros_socket_thread_create(); #endif create_wifi_services(); client = g_dbus_client_new(connection, "org.bluez", "/"); g_dbus_client_set_proxy_handlers(client, proxy_added_cb, NULL, property_changed, NULL); g_main_loop_run(main_loop); #ifdef DUEROS dueros_socket_thread_delete(); #endif g_dbus_client_unref(client); g_source_remove(signal); g_slist_free_full(services, g_free); dbus_connection_unref(connection); return 0; }