Last Updated on : 2023-09-06 10:41:15download
This topic describes pairing over Bluetooth to enable a gateway to connect to the Tuya ecosystem.
The SDK comes with the implementation of the business logic of the pairing process. It defines a set of TuyaOS Kernel Layer (TKL) that shields differences in hardware and system. The underlying hardware is controlled by the TKL interfaces that need to be implemented by you. This topic guides you through developing the TKL interfaces.
After the gateway receives the pairing information (that is, the SSID and password of the router’s wireless network) from the mobile phone over Bluetooth, it performs the pairing process until pairing is finished.
Pairing over Bluetooth applies to:
The gateway regularly broadcasts its encrypted device information over Bluetooth. A mobile phone with Bluetooth enabled can receive the advertising packets. If the mobile phone detects a packet carrying Tuya-specific data, it will initiate a scan request for further information from the gateway. After the gateway answers with the additional data, the mobile app displays the gateway on the page of Auto Discovery.
After users tap the Add button on the app, the app sends the pairing information to the gateway over a Bluetooth connection. The gateway performs the activation on receiving the information until the pairing is finished.
Pairing over Bluetooth uses the proprietary Tuya-specific service and data. The SDK parses and packages all the data, so you can directly pass the raw data to the SDK.
The following figure shows the process of pairing over Bluetooth.
tkl_ble_stack_init
OPERATE_RET tkl_ble_stack_init(UCHAR_T role);
The SDK calls this interface on initialization. Your application can implement Bluetooth stack initialization in this interface. If you do not need such initialization, you should make an empty implementation for this interface.
tkl_ble_gap_callback_register
OPERATE_RET tkl_ble_gap_callback_register(CONST TKL_BLE_GAP_EVT_FUNC_CB gap_evt);
Register Bluetooth Low Energy (LE) Generic Access Profile (GAP) event callbacks. The application should save the pointer to the gap_evt
to the global variable. When the application receives Bluetooth LE GAP data, it passes the data to the SDK for processing through the function pointer.
During pairing over Bluetooth, take care of the TKL_BLE_GAP_EVT_CONNECT
event. When the application detects that the mobile phone establishes a Bluetooth connection with the gateway, it passes the GAP data to the SDK through the function pointer.
tkl_ble_gatt_callback_register
OPERATE_RET tkl_ble_gatt_callback_register(CONST TKL_BLE_GATT_EVT_FUNC_CB gatt_evt);
Register Bluetooth Low Energy (LE) Bluetooth Generic Attribute Profile (GATT) event callbacks. The application should save the pointer to the gatt_evt
to the global variable. When the application receives Bluetooth LE GATT data, it passes the data to the SDK for processing through the function pointer.
During pairing over Bluetooth, take care of the TKL_BLE_GATT_EVT_WRITE_REQ
event. When the application receives a Write Request with the Service UUID = 0x1910
, it passes the GATT data to the SDK through the function pointer.
tkl_ble_gap_adv_rsp_data_set
OPERATE_RET tkl_ble_gap_addr_set(TKL_BLE_GAP_ADDR_T CONST *p_peer_addr);
The SDK sets advertising and scan response. The application should cache the advertising and scan response data in this interface. Advertising data is used to broadcast information. Scan response data is sent upon the reception of scanning requests.
tkl_ble_gap_adv_start
OPERATE_RET tkl_ble_gap_adv_start(TKL_BLE_GAP_ADV_PARAMS_T CONST *p_adv_params);
The SDK notifies the application of turning on Bluetooth LE advertising. The application should be able to turn on advertising in this interface accordingly, with the advertising and scan response data set by tkl_ble_gap_adv_rsp_data_set
.
tkl_ble_gap_adv_stop
OPERATE_RET tkl_ble_gap_adv_stop(VOID);
The SDK notifies the application of turning off Bluetooth LE advertising. The application should be able to turn off advertising accordingly.
tkl_ble_gatts_value_notify
OPERATE_RET tkl_ble_gatts_value_notify(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length);
The SDK calls this interface to send Bluetooth LE GATT data to the mobile phone. The application should send GATT data to the mobile phone over Bluetooth.
Bluetooth advertising and scan response data format:
Bluetooth advertising and scan response comply with Bluetooth specifications. The SDK packages the data into AD Structures, which the application can directly pass without parsing.
Bluetooth packet format:
With a Bluetooth connection established, the mobile app and the gateway transmit data over the Attribute Protocol (ATT). The data packaged and parsed by the SDK is placed into the ATT payload.
Service and Characteristic are defined as follows:
Service UUID: 0x1910
Characteristic | UUID | Attribute | Description |
---|---|---|---|
Write Characteristic | 0x2B11 | Write Without Response | The mobile app sends data to the Bluetooth LE device. |
Notify Characteristic | 0x2B10 | Notify | The Bluetooth LE device sends a Notify message to the mobile app. |
This section demonstrates the implementation of TKL interfaces for generic Linux.
#include <unistd.h>
#include "uni_log.h"
#include "base_os_adapter.h"
#include "tuya_iot_base_api.h"
#include "tuya_iot_com_api.h"
#include "tuya_iot_sdk_api.h"
#include "tuya_iot_sdk_defs.h"
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
#include "tuya_os_adapt_bt.h"
#endif
#define PID "fljmamufiym5fktz" // Replace the example value with your own PID.
#define UUID "tuya461dbc63aeeb991f" // Replace the example value with your own UUID
#define AUTHKEY "c8X4PR4wx1gMFaQlaZu5dfgVvVRwB8Ug" // Replace the example value with your own AUTHKEY
STATIC VOID __gw_reset_cb(GW_RESET_TYPE_E type)
{
PR_DEBUG("gw reset callback, type: %d", type);
if (GW_RESET_DATA_FACTORY != type) {
exit(0);
}
return;
}
STATIC VOID __gw_upgrade_cb(CONST FW_UG_S *fw)
{
PR_DEBUG("gw upgrade callback");
if (fw == NULL) {
PR_ERR("invalid param");
return;
}
PR_DEBUG(" tp: %d", fw->tp);
PR_DEBUG(" fw_url: %s", fw->fw_url);
PR_DEBUG(" sw_ver: %s", fw->sw_ver);
PR_DEBUG(" fw_hmac: %s", fw->fw_hmac);
PR_DEBUG(" file_size: %u", fw->file_size);
return;
}
STATIC VOID __gw_active_stat_cb(GW_STATUS_E status)
{
PR_DEBUG("gw active stat callback, status: %d", status);
return;
}
STATIC VOID __gw_reboot_cb(VOID)
{
PR_DEBUG("gw reboot callback");
exit(0);
return;
}
STATIC VOID __nw_stat_cb(IN CONST SDK_NW_STAT_T stat)
{
PR_DEBUG("network stat: %d", stat);
return;
}
STATIC VOID __wired_stat_cb(IN CONST SDK_WIRED_NW_STAT_T stat)
{
PR_DEBUG("wired stat: %d", stat);
return;
}
int main(int argc, char **argv)
{
OPERATE_RET rt = OPRT_OK;
GW_PROD_INFO_S prod_info = {0};
/* gw base callback */
TY_GW_INFRA_CBS_S gw_cbs = {
.gw_reset_cb = __gw_reset_cb,
.gw_upgrade_cb = __gw_upgrade_cb,
.gw_active_stat_cb = __gw_active_stat_cb,
.gw_reboot_cb = __gw_reboot_cb,
};
#if defined(TY_BT_MOD) && (TY_BT_MOD == 1)
tuya_os_adapt_reg_bt_intf();
#endif
/* initiate os-layer service*/
tuya_os_intf_init();
/* initiate iot-layer service */
TUYA_CALL_ERR_RETURN(tuya_iot_init("./"));
/* set the logging level to debug */
SET_PR_DEBUG_LEVEL(TY_LOG_LEVEL_DEBUG);
PR_DEBUG("SDK INFO: %s", tuya_iot_get_sdk_info());
/* set uuid and authkey */
prod_info.uuid = UUID;
prod_info.auth_key = AUTHKEY;
TUYA_CALL_ERR_RETURN(tuya_iot_set_gw_prod_info(&prod_info));
/* pre-initiate sdk service */
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_pre_init(TRUE));
/* initiate application service, more service in here */
TUYA_CALL_ERR_RETURN(tuya_user_svc_init(&gw_cbs));
/* initiate sdk service */
#if defined(GW_SUPPORT_WIRED_WIFI) && (GW_SUPPORT_WIRED_WIFI==1)
TUYA_CALL_ERR_RETURN(tuya_iot_wr_wf_sdk_init(IOT_GW_NET_WIRED_WIFI, GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#elif defined(WIFI_GW) && (WIFI_GW==1)
TUYA_CALL_ERR_RETURN(tuya_iot_wf_sdk_init(GWCM_OLD, WF_START_AP_ONLY, PID, USER_SW_VER, NULL, 0));
#else
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_init(PID, USER_SW_VER, NULL, 0));
return OPRT_COM_ERROR;
#endif
/* register net stat notification callback */
TUYA_CALL_ERR_RETURN(tuya_iot_sdk_reg_netstat_cb(__nw_stat_cb, __wired_stat_cb, NULL));
/* start application service, more service in here */
TUYA_CALL_ERR_RETURN(tuya_user_svc_start(NULL));
while (1) {
sleep(10);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <net/if.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include "uni_log.h"
#include "tkl_wired.h"
#define WIRED_NAME "eth0"
TKL_WIRED_STATUS_CHANGE_CB g_link_status_change_cb;
STATIC VOID *link_status_thread(VOID *arg)
{
INT_T old_status = -1;
TKL_WIRED_STAT_E new_status;
while (1) {
tkl_wired_get_status(&new_status);
if (old_status != new_status) {
g_link_status_change_cb(new_status);
old_status = new_status;
}
sleep(1);
}
}
/**
* Get the IP address of the network interface.
*/
OPERATE_RET tkl_wired_get_ip(OUT NW_IP_S *ip)
{
int sock = 0;
char ipaddr[50] = {0};
struct sockaddr_in *sin;
struct ifreq ifr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
PR_ERR("socket create failed");
return OPRT_COM_ERROR;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, WIRED_NAME, sizeof(ifr.ifr_name) - 1);
if (ioctl(sock, SIOCGIFADDR, &ifr) < 0 ) {
PR_ERR("ioctl failed");
close(sock);
return OPRT_COM_ERROR;
}
sin = (struct sockaddr_in *)&ifr.ifr_addr;
strcpy(ip->ip, inet_ntoa(sin->sin_addr));
close(sock);
return OPRT_OK;
}
/**
* Get the wired connection status.
*/
OPERATE_RET tkl_wired_get_status(TKL_WIRED_STAT_E *status)
{
int sock;
struct sockaddr_in *sin;
struct ifreq ifr;
NW_IP_S ip;
*status = TKL_WIRED_LINK_DOWN;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
PR_ERR("socket failed");
return OPRT_COM_ERROR;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, WIRED_NAME, sizeof(ifr.ifr_name) - 1);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
PR_ERR("ioctl failed");
close(sock);
return OPRT_COM_ERROR;
}
close(sock);
if ((ifr.ifr_flags & IFF_UP) == 0) {
return OPRT_OK;
}
if (tkl_wired_get_ip(&ip) != OPRT_OK) {
return OPRT_OK;
}
*status = TKL_WIRED_LINK_UP;
return OPRT_OK;
}
/* Set the callback invoked when the wired connection status changes. */
OPERATE_RET tkl_wired_set_status_cb(TKL_WIRED_STATUS_CHANGE_CB cb)
{
pthread_t tid;
g_link_status_change_cb = cb;
return pthread_create(&tid, NULL, link_status_thread, NULL);
}
OPERATE_RET tkl_wired_get_mac(NW_MAC_S *mac)
{
int i;
int sock = -1;
struct ifreq ifr;
struct sockaddr *addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
PR_ERR("socket failed");
return OPRT_SOCK_ERR;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, WIRED_NAME, sizeof(ifr.ifr_name) - 1);
addr = (struct sockaddr *)&ifr.ifr_hwaddr;
addr->sa_family = 1;
/* get mac addr */
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
PR_ERR("ioctl failed");
close(sock);
return OPRT_COM_ERROR;
}
memcpy(mac->mac, addr->sa_data, MAC_ADDR_LEN);
close(sock);
return OPRT_OK;
}
/* Implementation is not needed */
OPERATE_RET tkl_wired_set_mac(CONST NW_MAC_S *mac)
{
return OPRT_OK;
}
#include "tuya_iot_config.h"
#if defined(WIFI_GW) && (WIFI_GW==1)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/if.h>
#include "tuya_os_adapter.h"
#include "tkl_wifi.h"
#include "tkl_system.h"
#include "uni_log.h"
#define WLAN_DEV "wlan0"
#define UDHCPD_CONF "/etc/udhcpd.conf"
#define HOSTAPD_CONF "/etc/hostapd/hostapd.conf"
#define WPA_SUPPLICANT_CONF "/etc/wpa_supplicant/wpa_supplicant.conf"
STATIC NW_IP_S g_ap_ip = {0};
STATIC WF_WK_MD_E g_wifi_mode = WWM_STATION;
STATIC WIFI_EVENT_CB __wifi_event_cb = NULL;
STATIC OPERATE_RET save_conf(CONST CHAR_T *filename, VOID *data, UINT32_T len)
{
OPERATE_RET wbyte = 0;
FILE *fp = NULL;
fp = fopen(filename, "w");
if (fp == NULL) {
PR_ERR("open %s failed", filename);
return OPRT_OPEN_FILE_FAILED;
}
wbyte = fwrite(data, 1, len, fp);
if (wbyte != len) {
PR_ERR("write error");
fclose(fp);
return OPRT_WRITE_FILE_FAILED;
}
fflush(fp);
fsync(fileno(fp));
fclose(fp);
return OPRT_OK;
}
STATIC OPERATE_RET exec_command(CONST CHAR_T *cmd, CHAR_T *data, INT_T len)
{
FILE *fp = NULL;
fp = popen(cmd, "r");
if (fp == NULL) {
return OPRT_COM_ERROR;
}
if (data != NULL) {
memset(data, 0, len);
fread(data, len, 1, fp);
len = strlen(data);
if (data[len - 1] == '\n') {
data[len - 1] = '\0';
}
}
pclose(fp);
return OPRT_OK;
}
STATIC BOOL_T __wifi_status(VOID)
{
FILE *fp = NULL;
CHAR_T buf[512] = {0};
WF_STATION_STAT_E stat = 0;
fp = popen("wpa_cli -i " WLAN_DEV " status", "r");
if (fp == NULL) {
return FALSE;
}
while (fgets(buf, SIZEOF(buf), fp)) {
if (!strstr(buf, "wpa_state"))
continue;
char *k = strtok(buf, "=");
char *v = strtok(NULL, "=");
if (v && !strncmp(v, "COMPLETED", strlen("COMPLETED"))) {
tkl_wifi_station_get_status(&stat);
if (stat == WSS_GOT_IP) {
return TRUE;
}
}
}
pclose(fp);
return FALSE;
}
STATIC VOID *__wifi_status_thread(VOID *arg)
{
BOOL_T cur_status = FALSE, lst_status = FALSE;
while (1) {
if (g_wifi_mode != WWM_STATION) {
tkl_system_sleep(500);
continue;
}
cur_status = __wifi_status();
if (cur_status != lst_status) {
PR_DEBUG("wifi connection status changed, %d -> %d", lst_status, cur_status);
if (__wifi_event_cb) {
__wifi_event_cb(cur_status ? WFE_CONNECTED : WFE_DISCONNECTED, NULL);
}
lst_status = cur_status;
}
tkl_system_sleep(1000);
}
}
OPERATE_RET tkl_wifi_init(WIFI_EVENT_CB cb)
{
pthread_t tid;
__wifi_event_cb = cb;
pthread_create(&tid, NULL, __wifi_status_thread, NULL);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_get_ip(CONST WF_IF_E wf, NW_IP_S *ip)
{
struct ifreq ifr;
int sock = 0;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
PR_ERR("create socket failed");
return OPRT_COM_ERROR;
}
strncpy(ifr.ifr_name, WLAN_DEV, strlen(WLAN_DEV) + 1);
if (ioctl(sock, SIOCGIFADDR, &ifr) == 0)
strncpy(ip->ip, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr), sizeof(ip->ip));
if (ioctl(sock, SIOCGIFBRDADDR, &ifr) == 0)
strncpy(ip->gw, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr), sizeof(ip->gw));
if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0)
strncpy(ip->mask, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr), sizeof(ip->mask));
close(sock);
PR_DEBUG("WiFi ip->ip: %s", ip->ip);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_station_get_status(WF_STATION_STAT_E *stat)
{
OPERATE_RET op_ret = OPRT_OK;
NW_IP_S ip = {0};
*stat = WSS_IDLE;
op_ret = tkl_wifi_get_ip(WF_STATION, &ip);
if (op_ret != OPRT_OK) {
return op_ret;
}
if ((strlen(ip.ip) > 0) && (strncmp(g_ap_ip.ip, ip.ip, strlen(ip.ip)) != 0)) {
*stat = WSS_GOT_IP;
}
return OPRT_OK;
}
OPERATE_RET tkl_wifi_get_mac(CONST WF_IF_E wf, NW_MAC_S *mac)
{
int i;
int fd = -1;
struct ifreq ifr;
struct sockaddr *addr;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) {
PR_ERR("socket failed");
return OPRT_SOCK_ERR;
}
memset(&ifr, 0, SIZEOF(ifr));
strncpy(ifr.ifr_name, WLAN_DEV, SIZEOF(ifr.ifr_name) - 1);
addr = (struct sockaddr *)&ifr.ifr_hwaddr;
addr->sa_family = 1;
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
PR_ERR("ioctl failed");
close(fd);
return OPRT_COM_ERROR;
}
memcpy(mac->mac, addr->sa_data, MAC_ADDR_LEN);
PR_DEBUG("WiFi mac->mac: %02X-%02X-%02X-%02X-%02X-%02X", mac->mac[0], mac->mac[1], mac->mac[2], \
mac->mac[3],mac->mac[4],mac->mac[5]);
close(fd);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_set_work_mode(CONST WF_WK_MD_E mode)
{
PR_DEBUG("WiFi set mode: %d", mode);
g_wifi_mode = mode;
switch (mode) {
case WWM_STATION:
exec_command("iwconfig " WLAN_DEV " mode managed", NULL, 0);
break;
case WWM_SOFTAP:
// exec_command("iwconfig " WLAN_DEV " mode master", NULL, 0);
break;
default:
break;
}
return OPRT_OK;
}
OPERATE_RET tkl_wifi_get_work_mode(WF_WK_MD_E *mode)
{
#if 0
CHAR_T buf[256] = {0};
CHAR_T *pstart = NULL;
CHAR_T mode_buf[16] = {0};
FILE *fp = NULL;
fp = popen("iwconfig " WLAN_DEV, "r");
if (fp == NULL) {
return OPRT_COM_ERROR;
}
while (fgets(buf, SIZEOF(buf), fp) != NULL) {
pstart = strstr(buf, "Mode:");
if (pstart != NULL) {
sscanf(pstart + strlen("Mode:"), "%s ", mode_buf);
break;
}
}
pclose(fp);
if (!strncasecmp(mode_buf, "Managed", strlen("Managed"))) {
*mode = WWM_STATION;
} else if (!strncasecmp(mode_buf, "Master", strlen("Master"))) {
*mode = WWM_SOFTAP;
}
#endif
*mode = g_wifi_mode;
PR_DEBUG("WiFi got mode: %d", *mode);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_start_ap(CONST WF_AP_CFG_IF_S *cfg)
{
OPERATE_RET op_ret = OPRT_OK;
INT_T len = 0;
CHAR_T buf[512] = {0};
CHAR_T cmd[128] = {0};
CHAR_T *ap_conf_fmt =
"interface=%s\n"
"ssid=%s\n"
"country_code=CN\n"
"channel=%d\n"
"beacon_int=100\n"
"max_num_sta=%d\n"
"auth_algs=3\n"
"wpa=%d\n"
"wpa_key_mgmt=WPA-PSK\n"
"wpa_pairwise=TKIP CCMP\n"
"rsn_pairwise=CCMP\n";
CHAR_T *udhcpd_conf_fmt =
"interface %s\n"
"start %s.100\n"
"end %s.200\n"
"opt subnet %s\n"
"opt lease 28800\n"
"opt router %s\n"
"opt dns %s\n"
"opt domain SmartLift\n";
INT_T seg1 = 0, seg2 = 0, seg3 = 0, seg4 = 0;
CHAR_T ip_prefix[12] = {0};
tkl_wifi_station_disconnect();
PR_DEBUG("start ap, ssid: %s, ip: %s", cfg->ssid, cfg->ip.ip);
memcpy(&g_ap_ip, &(cfg->ip), SIZEOF(NW_IP_S));
sscanf(cfg->ip.ip, "%d.%d.%d.%d", &seg1, &seg2, &seg3, &seg4);
snprintf(ip_prefix, SIZEOF(ip_prefix), "%d.%d.%d", seg1, seg2, seg3);
if (cfg->p_len > 0) {
len = snprintf(buf, SIZEOF(buf), ap_conf_fmt, WLAN_DEV, cfg->ssid, cfg->chan, cfg->max_conn, 2);
len += snprintf(buf + len, SIZEOF(buf) - len, "wpa_passphrase=%s\n", cfg->passwd);
} else {
len = snprintf(buf, SIZEOF(buf), ap_conf_fmt, WLAN_DEV, cfg->ssid, cfg->chan, cfg->max_conn, 0);
}
op_ret = save_conf(HOSTAPD_CONF, buf, len);
if (op_ret != OPRT_OK) {
PR_ERR("fail to write %s", HOSTAPD_CONF);
}
len = snprintf(buf, SIZEOF(buf), udhcpd_conf_fmt, WLAN_DEV, ip_prefix, ip_prefix, cfg->ip.mask, cfg->ip.gw, cfg->ip.gw);
op_ret = save_conf(UDHCPD_CONF, buf, len);
if (op_ret != OPRT_OK) {
PR_ERR("fail to write %s", UDHCPD_CONF);
}
snprintf(cmd, SIZEOF(cmd), "ifconfig %s %s netmask %s", WLAN_DEV, cfg->ip.ip, cfg->ip.mask);
exec_command(cmd, NULL, 0);
exec_command("ifconfig " WLAN_DEV " up", NULL, 0);
tkl_system_sleep(1000);
exec_command("hostapd -B -P /run/hostapd.pid " HOSTAPD_CONF, NULL, 0);
exec_command("killall udhcpd", NULL, 0);
exec_command("udhcpd " UDHCPD_CONF, NULL, 0);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_stop_ap(VOID_T)
{
exec_command("killall udhcpd", NULL, 0);
exec_command("killall hostapd", NULL, 0);
exec_command("ifconfig " WLAN_DEV " down", NULL, 0);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_station_connect(CONST SCHAR_T *ssid, CONST SCHAR_T *passwd)
{
OPERATE_RET op_ret = OPRT_OK;
INT_T len = 0;
CHAR_T buf[512] = {0};
CHAR_T *wpa_conf_fmt =
"ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n"
"update_config=1\n"
"country=CN\n"
"\n"
"network={\n"
"\tssid=\"%s\"\n"
"\tpairwise=CCMP TKIP\n"
"\tkey_mgmt=WPA-PSK\n"
"\tgroup=CCMP TKIP\n"
"\tpsk=\"%s\"\n"
"}\n";
if (!ssid || !passwd) {
PR_WARN("ssid or passwd is null");
return OPRT_INVALID_PARM;
}
tkl_wifi_stop_ap();
PR_DEBUG("ssid: %s, passwd: %s", ssid, passwd);
len = snprintf(buf, SIZEOF(buf), wpa_conf_fmt, ssid, passwd);
op_ret = save_conf(WPA_SUPPLICANT_CONF, buf, len);
if (op_ret != OPRT_OK) {
PR_ERR("fail to write %s", UDHCPD_CONF);
}
exec_command("wpa_supplicant -B -Dnl80211 -i" WLAN_DEV " -c" WPA_SUPPLICANT_CONF, NULL, 0);
exec_command("udhcpc -i " WLAN_DEV " -s /etc/udhcpc/default.script -p /run/udhcpc_wlan0.pid -b", NULL, 0);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_station_disconnect(VOID_T)
{
exec_command("wpa_cli -i " WLAN_DEV " terminate", NULL, 0);
exec_command("[ -f /run/udhcpc_wlan0.pid ] && (cat /run/udhcpc_wlan0.pid | xargs sudo kill)", NULL, 0);
exec_command("ifconfig " WLAN_DEV " down", NULL, 0);
return OPRT_OK;
}
OPERATE_RET tkl_wifi_set_mac(CONST WF_IF_E wf, CONST NW_MAC_S *mac)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_scan_ap(CONST SCHAR_T *ssid, AP_IF_S **aps, UINT_T *num)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_release_ap(AP_IF_S *ap)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_set_cur_channel(CONST UCHAR_T chan)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_get_cur_channel(UCHAR_T *chan)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_set_sniffer(CONST BOOL_T en, CONST SNIFFER_CALLBACK cb)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_station_get_conn_ap_rssi(SCHAR_T *rssi)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_get_bssid(UCHAR_T *mac)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_set_country_code(CONST COUNTRY_CODE_E ccode)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_send_mgnt(CONST UCHAR_T *buf, CONST UINT_T len)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_register_recv_mgnt_callback(CONST BOOL_T enable, CONST WIFI_REV_MGNT_CB recv_cb)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_set_lp_mode(CONST BOOL_T enable, CONST UCHAR_T dtim)
{
return OPRT_OK;
}
OPERATE_RET tkl_wifi_get_connected_ap_info(FAST_WF_CONNECTED_AP_INFO_T **fast_ap_info)
{
return OPRT_COM_ERROR;
}
OPERATE_RET tkl_wifi_station_fast_connect(CONST FAST_WF_CONNECTED_AP_INFO_T *fast_ap_info)
{
return OPRT_COM_ERROR;
}
OPERATE_RET tkl_wifi_set_rf_calibrated(VOID_T)
{
return OPRT_OK;
}
OPERATE_RET tkl_hostap_ioctl_inet(INT_T dev, INT_T vif_index, UINT_T cmd, ULONG_T arg)
{
return OPRT_OK;
}
#endif
#include "tkl_bluetooth.h"
OPERATE_RET tkl_ble_stack_init(UCHAR_T role)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_stack_deinit(UCHAR_T role)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_callback_register(CONST TKL_BLE_GAP_EVT_FUNC_CB gap_evt)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gatt_callback_register(CONST TKL_BLE_GATT_EVT_FUNC_CB gatt_evt)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_adv_start(TKL_BLE_GAP_ADV_PARAMS_T CONST *p_adv_params)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_adv_stop(VOID)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_adv_rsp_data_set(TKL_BLE_DATA_T CONST *p_adv, TKL_BLE_DATA_T CONST *p_scan_rsp)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_adv_rsp_data_update(TKL_BLE_DATA_T CONST *p_adv, TKL_BLE_DATA_T CONST *p_scan_rsp)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gatts_value_notify(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_stack_gatt_link(USHORT_T *p_link)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_addr_set(TKL_BLE_GAP_ADDR_T CONST *p_peer_addr)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_address_get(TKL_BLE_GAP_ADDR_T *p_peer_addr)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_scan_start(TKL_BLE_GAP_SCAN_PARAMS_T CONST *p_scan_params)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_scan_stop(VOID)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_connect(TKL_BLE_GAP_ADDR_T CONST *p_peer_addr, TKL_BLE_GAP_SCAN_PARAMS_T CONST *p_scan_params, TKL_BLE_GAP_CONN_PARAMS_T CONST *p_conn_params)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_disconnect(USHORT_T conn_handle, UCHAR_T hci_reason)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_conn_param_update(USHORT_T conn_handle, TKL_BLE_GAP_CONN_PARAMS_T CONST *p_conn_params)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_tx_power_set(UCHAR_T role, INT_T tx_power)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gap_rssi_get(USHORT_T conn_handle)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gatts_service_add(TKL_BLE_GATTS_PARAMS_T *p_service)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gatts_value_set(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gatts_value_get(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gatts_value_indicate(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gatts_exchange_mtu_reply(USHORT_T conn_handle, USHORT_T server_rx_mtu)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gattc_all_service_discovery(USHORT_T conn_handle)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gattc_all_char_discovery(USHORT_T conn_handle, USHORT_T start_handle, USHORT_T end_handle)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gattc_char_desc_discovery(USHORT_T conn_handle, USHORT_T start_handle, USHORT_T end_handle)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gattc_write_without_rsp(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gattc_write(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gattc_read(USHORT_T conn_handle, USHORT_T char_handle)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_gattc_exchange_mtu_request(USHORT_T conn_handle, USHORT_T client_rx_mtu)
{
return OPRT_OK;
}
OPERATE_RET tkl_ble_vendor_command_control(USHORT_T opcode, VOID_T *user_data, USHORT_T data_len)
{
return OPRT_NOT_SUPPORTED;
}
Do not block TKL interfaces. It is recommended to process time-consuming tasks asynchronously.
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback