|   | 
|   | 
| /** | 
|  * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd | 
|  * author: WuQiang <xianlee.wu@rock-chips.com> | 
|  * | 
|  * This software is licensed under the terms of the GNU General Public | 
|  * License version 2, as published by the Free Software Foundation, and | 
|  * may be copied, distributed, and modified under those terms. | 
|  * | 
|  * 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. | 
|  */ | 
|   | 
| #include "stdio.h" | 
| #include "stdlib.h" | 
| #include "stdint.h" | 
| #include "string.h" | 
| #include "fcntl.h" | 
| #include "sys/file.h" | 
| #include "sys/ioctl.h" | 
| #include "time.h" | 
| #include "malloc.h" | 
| #include "unistd.h" | 
| #include "net/if.h" | 
| #include "arpa/inet.h" | 
| #include "sys/socket.h" | 
|   | 
| // vendor parameter | 
| #define VENDOR_REQ_TAG 0x56524551 | 
| #define VENDOR_READ_IO _IOW('v', 0x01, unsigned int) | 
| #define VENDOR_WRITE_IO _IOW('v', 0x02, unsigned int) | 
|   | 
| #define VENDOR_SN_ID 1 | 
| #define VENDOR_WIFI_MAC_ID 2 | 
| #define VENDOR_LAN_MAC_ID 3 | 
| #define VENDOR_BLUETOOTH_ID 4 | 
| #define VENDOR_STREAM_ID 14 | 
| #define VENDOR_PROTOCOL_ID  15 | 
|   | 
| #define UDPPORT 18888 | 
| #define FWK_MSG_UID_LEN 20 | 
| #define FWK_MSG_CMD_LEN 128 | 
| #define FWK_MSG_IP_MAX_LEN 16 | 
| #define FWK_MSG_MAC_MAX_LEN 18 | 
|   | 
| /* Storage parameter */ | 
| #define VENDOR_PARAMETER_ID 5 | 
| /* Change the id when flash firmware */ | 
| #define VENDOR_FW_UPDATE_ID 6 | 
|   | 
| #define VENDOR_DATA_SIZE (3 * 1024)  // 3k | 
| #define VENDOR_DATA_PROTOCOL_SIZE (384)  /* 64*6=384 byte */ | 
|   | 
| #define VERDOR_DEVICE "/dev/vendor_storage" | 
|   | 
| typedef struct _RK_VERDOR_REQ { | 
|   uint32_t tag; | 
|   uint16_t id; | 
|   uint16_t len; | 
|   uint8_t data[VENDOR_DATA_SIZE]; | 
| } RK_VERDOR_REQ; | 
|   | 
| typedef struct _RK_VERDOR_PROTOCOL_REQ { | 
|   uint32_t tag; | 
|   uint16_t id; | 
|   uint16_t len; | 
|   uint8_t data[VENDOR_DATA_PROTOCOL_SIZE]; | 
| } RK_VERDOR_PROTOCOL_REQ; | 
|   | 
| static int rk_parameter_read_uid(int sys_fd, char *iotc_uid, int len); | 
| static int parameter_read_protocol_uid(char iotc_uid[FWK_MSG_UID_LEN+1]); | 
| static void broadcast_service(); | 
|   | 
| int main() | 
| { | 
|     printf("starting device discovery service!\n"); | 
|   | 
|     broadcast_service(); | 
|   | 
|     printf("discovery service crashed!\n"); | 
|   | 
|     return 0; | 
| } | 
|   | 
| int rk_parameter_read_uid(int sys_fd, char *iotc_uid, int len) | 
| { | 
|     RK_VERDOR_PROTOCOL_REQ req; | 
|   | 
|     if (sys_fd < 0) { | 
|         printf("_read_uid: error with sys_fd < 0\n"); | 
|         return -1; | 
|     } | 
|     req.tag = VENDOR_REQ_TAG; | 
|     req.id = VENDOR_SN_ID; | 
|     req.len = 512; | 
|     if (ioctl(sys_fd, VENDOR_READ_IO, &req)) { | 
|         printf("_read_uid:VENDOR_SN_ID fail\n"); | 
|         return -1; | 
|     } | 
|     /* rknand_print_hex_data("vendor read:", (uint32_t*)&req, req.len + 8); **/ | 
|     if (req.len > len) { | 
|         printf("_read_uid:%d force to %d\n", req.len, len); | 
|         req.len = len; | 
|     } | 
|     memcpy(iotc_uid, req.data, req.len); | 
|   | 
|     return req.len; | 
| } | 
|   | 
| int parameter_read_protocol_uid(char iotc_uid[FWK_MSG_UID_LEN+1]) | 
| { | 
|     int sys_fd = -1; | 
|     int ret = -1; | 
|   | 
|     printf("read_uid: enter...\n"); | 
|     sys_fd = open(VERDOR_DEVICE, O_RDWR, 0); | 
|     if (sys_fd < 0) { | 
|         printf("read_uid: error with sys_fd < 0\n"); | 
|         return ret; | 
|     } | 
|     memset(iotc_uid, 0, FWK_MSG_UID_LEN + 1); | 
|     ret = rk_parameter_read_uid(sys_fd, &iotc_uid[0], FWK_MSG_UID_LEN); | 
|     close(sys_fd); | 
|     printf("read_uid: success with uid=%s\n", iotc_uid); | 
|   | 
|     return ret; | 
| } | 
|   | 
|   | 
| static void broadcast_service() | 
| { | 
|     socklen_t addr_len = 0; | 
|     struct sockaddr_in server_addr; | 
|     struct ifreq ifr; | 
|     char buf[64]; | 
|     char local_addr[FWK_MSG_IP_MAX_LEN]; | 
|     char local_mac[FWK_MSG_MAC_MAX_LEN]; | 
|     char cmd_info[FWK_MSG_CMD_LEN]; | 
|     char uid[FWK_MSG_UID_LEN + 1]; | 
|     int broadcast_fd = -1; | 
|     int opt = -1; | 
|   | 
|     broadcast_fd = socket(AF_INET, SOCK_DGRAM, 0); | 
|     if (broadcast_fd < 0) { | 
|         perror("broadcast_thread : socket"); | 
|         goto stop_broadcast; | 
|     } | 
|     printf("broadcast_thread socketfd = %d\n", broadcast_fd); | 
|   | 
|     strcpy(ifr.ifr_name, "rndis0"); | 
|   | 
|     memset(local_addr, 0, FWK_MSG_IP_MAX_LEN); | 
|     memset(local_mac, 0, FWK_MSG_MAC_MAX_LEN); | 
|   | 
|     // get rndis ethernet interface ip address | 
|     while (ioctl(broadcast_fd, SIOCGIFADDR, &ifr) < 0) { | 
|         sleep(1); | 
|     } | 
|     snprintf(local_addr, FWK_MSG_IP_MAX_LEN, "%s", | 
|             inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr)); | 
|   | 
|     // get rndis ethernet interface mac address | 
|     while (ioctl(broadcast_fd, SIOCGIFHWADDR, &ifr) < 0) { | 
|         sleep(1); | 
|     } | 
|     snprintf(local_mac, FWK_MSG_MAC_MAX_LEN, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", | 
|             (unsigned char)ifr.ifr_hwaddr.sa_data[0], | 
|             (unsigned char)ifr.ifr_hwaddr.sa_data[1], | 
|             (unsigned char)ifr.ifr_hwaddr.sa_data[2], | 
|             (unsigned char)ifr.ifr_hwaddr.sa_data[3], | 
|             (unsigned char)ifr.ifr_hwaddr.sa_data[4], | 
|             (unsigned char)ifr.ifr_hwaddr.sa_data[5]); | 
|   | 
|     printf("Discovery:got device net info!\n"); | 
|   | 
|     memset(&server_addr, 0, sizeof(server_addr)); | 
|     server_addr.sin_family = AF_INET; | 
|     server_addr.sin_addr.s_addr = htonl(INADDR_ANY); | 
|     server_addr.sin_port = htons(UDPPORT); | 
|     addr_len = sizeof(server_addr); | 
|   | 
|     if (setsockopt(broadcast_fd, SOL_SOCKET, SO_BROADCAST, (char *)&opt, | 
|                sizeof(opt)) < 0) { | 
|         perror("broadcast setsockopt SO_BROADCAST"); | 
|         goto stop_broadcast; | 
|     } | 
|     if (setsockopt(broadcast_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, | 
|                sizeof(opt)) < 0) { | 
|         perror("broadcast setsockopt SO_REUSEADDR"); | 
|         goto stop_broadcast; | 
|     } | 
|   | 
|     if (bind(broadcast_fd, (struct sockaddr *)&server_addr, addr_len) < 0) { | 
|         perror("broadcast bind"); | 
|         goto stop_broadcast; | 
|     } | 
|   | 
|     while (1) { | 
|         memset(buf, 0, sizeof(buf)); | 
|         memset(uid, 0, sizeof(uid)); | 
|         memset(cmd_info, 0, sizeof(cmd_info)); | 
|   | 
|   | 
|         fprintf(stderr,"=========function is: %s line is : %d=============\n",__func__,__LINE__); | 
|         if (recvfrom(broadcast_fd, buf, 64, 0, | 
|             (struct sockaddr *)&server_addr, &addr_len) < 0) { | 
|             perror("broadcast recvfrom"); | 
|             continue; | 
|         } | 
|   | 
|         printf("broadcast: from: %s port: %d > %s\n", | 
|                inet_ntoa(server_addr.sin_addr), | 
|                ntohs(server_addr.sin_port), buf); | 
|   | 
|         if (strcmp("CMD_DISCOVER", buf) == 0) { | 
|   | 
|             if ((parameter_read_protocol_uid(uid)) < 0) { | 
|                 printf("Discover:read uid failed!\n"); | 
|             } | 
|   | 
|             uid[FWK_MSG_UID_LEN] = '\0'; | 
|   | 
|             snprintf(cmd_info, FWK_MSG_CMD_LEN, | 
|                     "{\"UID\":\"%s\"," | 
|                     "\"IP\":\"%s\"," | 
|                     "\"MAC\":\"%s\"," | 
|                     "\"DEVICENAME\":\"%s\"}", | 
|                     uid, | 
|                     local_addr, | 
|                     local_mac, | 
|                     "ECHO"); | 
|   | 
|             printf("sendto: %s port: %d > %s\n", | 
|                    inet_ntoa(server_addr.sin_addr), | 
|                    ntohs(server_addr.sin_port), cmd_info); | 
|             if (sendto(broadcast_fd, cmd_info, strlen(cmd_info), | 
|                 0, (struct sockaddr *)&server_addr, addr_len) < 0) { | 
|                 perror("broadcast_thread recvfrom"); | 
|                 goto stop_broadcast; | 
|             } | 
|         } | 
|     } | 
|   | 
| stop_broadcast: | 
|     printf("stop broadcast !\n"); | 
|     if (broadcast_fd >= 0) { | 
|         shutdown(broadcast_fd, 2); | 
|         close(broadcast_fd); | 
|         broadcast_fd = -1; | 
|     } | 
| } |