1*4882a593Smuzhiyun
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun /**
4*4882a593Smuzhiyun * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
5*4882a593Smuzhiyun * author: WuQiang <xianlee.wu@rock-chips.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This software is licensed under the terms of the GNU General Public
8*4882a593Smuzhiyun * License version 2, as published by the Free Software Foundation, and
9*4882a593Smuzhiyun * may be copied, distributed, and modified under those terms.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful,
12*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*4882a593Smuzhiyun * GNU General Public License for more details.
15*4882a593Smuzhiyun */
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include "stdio.h"
18*4882a593Smuzhiyun #include "stdlib.h"
19*4882a593Smuzhiyun #include "stdint.h"
20*4882a593Smuzhiyun #include "string.h"
21*4882a593Smuzhiyun #include "fcntl.h"
22*4882a593Smuzhiyun #include "sys/file.h"
23*4882a593Smuzhiyun #include "sys/ioctl.h"
24*4882a593Smuzhiyun #include "time.h"
25*4882a593Smuzhiyun #include "malloc.h"
26*4882a593Smuzhiyun #include "unistd.h"
27*4882a593Smuzhiyun #include "net/if.h"
28*4882a593Smuzhiyun #include "arpa/inet.h"
29*4882a593Smuzhiyun #include "sys/socket.h"
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun // vendor parameter
32*4882a593Smuzhiyun #define VENDOR_REQ_TAG 0x56524551
33*4882a593Smuzhiyun #define VENDOR_READ_IO _IOW('v', 0x01, unsigned int)
34*4882a593Smuzhiyun #define VENDOR_WRITE_IO _IOW('v', 0x02, unsigned int)
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define VENDOR_SN_ID 1
37*4882a593Smuzhiyun #define VENDOR_WIFI_MAC_ID 2
38*4882a593Smuzhiyun #define VENDOR_LAN_MAC_ID 3
39*4882a593Smuzhiyun #define VENDOR_BLUETOOTH_ID 4
40*4882a593Smuzhiyun #define VENDOR_STREAM_ID 14
41*4882a593Smuzhiyun #define VENDOR_PROTOCOL_ID 15
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define UDPPORT 18888
44*4882a593Smuzhiyun #define FWK_MSG_UID_LEN 20
45*4882a593Smuzhiyun #define FWK_MSG_CMD_LEN 128
46*4882a593Smuzhiyun #define FWK_MSG_IP_MAX_LEN 16
47*4882a593Smuzhiyun #define FWK_MSG_MAC_MAX_LEN 18
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /* Storage parameter */
50*4882a593Smuzhiyun #define VENDOR_PARAMETER_ID 5
51*4882a593Smuzhiyun /* Change the id when flash firmware */
52*4882a593Smuzhiyun #define VENDOR_FW_UPDATE_ID 6
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define VENDOR_DATA_SIZE (3 * 1024) // 3k
55*4882a593Smuzhiyun #define VENDOR_DATA_PROTOCOL_SIZE (384) /* 64*6=384 byte */
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun #define VERDOR_DEVICE "/dev/vendor_storage"
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun typedef struct _RK_VERDOR_REQ {
60*4882a593Smuzhiyun uint32_t tag;
61*4882a593Smuzhiyun uint16_t id;
62*4882a593Smuzhiyun uint16_t len;
63*4882a593Smuzhiyun uint8_t data[VENDOR_DATA_SIZE];
64*4882a593Smuzhiyun } RK_VERDOR_REQ;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun typedef struct _RK_VERDOR_PROTOCOL_REQ {
67*4882a593Smuzhiyun uint32_t tag;
68*4882a593Smuzhiyun uint16_t id;
69*4882a593Smuzhiyun uint16_t len;
70*4882a593Smuzhiyun uint8_t data[VENDOR_DATA_PROTOCOL_SIZE];
71*4882a593Smuzhiyun } RK_VERDOR_PROTOCOL_REQ;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun static int rk_parameter_read_uid(int sys_fd, char *iotc_uid, int len);
74*4882a593Smuzhiyun static int parameter_read_protocol_uid(char iotc_uid[FWK_MSG_UID_LEN+1]);
75*4882a593Smuzhiyun static void broadcast_service();
76*4882a593Smuzhiyun
main()77*4882a593Smuzhiyun int main()
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun printf("starting device discovery service!\n");
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun broadcast_service();
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun printf("discovery service crashed!\n");
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun return 0;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
rk_parameter_read_uid(int sys_fd,char * iotc_uid,int len)88*4882a593Smuzhiyun int rk_parameter_read_uid(int sys_fd, char *iotc_uid, int len)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun RK_VERDOR_PROTOCOL_REQ req;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun if (sys_fd < 0) {
93*4882a593Smuzhiyun printf("_read_uid: error with sys_fd < 0\n");
94*4882a593Smuzhiyun return -1;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun req.tag = VENDOR_REQ_TAG;
97*4882a593Smuzhiyun req.id = VENDOR_SN_ID;
98*4882a593Smuzhiyun req.len = 512;
99*4882a593Smuzhiyun if (ioctl(sys_fd, VENDOR_READ_IO, &req)) {
100*4882a593Smuzhiyun printf("_read_uid:VENDOR_SN_ID fail\n");
101*4882a593Smuzhiyun return -1;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun /* rknand_print_hex_data("vendor read:", (uint32_t*)&req, req.len + 8); **/
104*4882a593Smuzhiyun if (req.len > len) {
105*4882a593Smuzhiyun printf("_read_uid:%d force to %d\n", req.len, len);
106*4882a593Smuzhiyun req.len = len;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun memcpy(iotc_uid, req.data, req.len);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun return req.len;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
parameter_read_protocol_uid(char iotc_uid[FWK_MSG_UID_LEN+1])113*4882a593Smuzhiyun int parameter_read_protocol_uid(char iotc_uid[FWK_MSG_UID_LEN+1])
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun int sys_fd = -1;
116*4882a593Smuzhiyun int ret = -1;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun printf("read_uid: enter...\n");
119*4882a593Smuzhiyun sys_fd = open(VERDOR_DEVICE, O_RDWR, 0);
120*4882a593Smuzhiyun if (sys_fd < 0) {
121*4882a593Smuzhiyun printf("read_uid: error with sys_fd < 0\n");
122*4882a593Smuzhiyun return ret;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun memset(iotc_uid, 0, FWK_MSG_UID_LEN + 1);
125*4882a593Smuzhiyun ret = rk_parameter_read_uid(sys_fd, &iotc_uid[0], FWK_MSG_UID_LEN);
126*4882a593Smuzhiyun close(sys_fd);
127*4882a593Smuzhiyun printf("read_uid: success with uid=%s\n", iotc_uid);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun return ret;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun
broadcast_service()133*4882a593Smuzhiyun static void broadcast_service()
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun socklen_t addr_len = 0;
136*4882a593Smuzhiyun struct sockaddr_in server_addr;
137*4882a593Smuzhiyun struct ifreq ifr;
138*4882a593Smuzhiyun char buf[64];
139*4882a593Smuzhiyun char local_addr[FWK_MSG_IP_MAX_LEN];
140*4882a593Smuzhiyun char local_mac[FWK_MSG_MAC_MAX_LEN];
141*4882a593Smuzhiyun char cmd_info[FWK_MSG_CMD_LEN];
142*4882a593Smuzhiyun char uid[FWK_MSG_UID_LEN + 1];
143*4882a593Smuzhiyun int broadcast_fd = -1;
144*4882a593Smuzhiyun int opt = -1;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun broadcast_fd = socket(AF_INET, SOCK_DGRAM, 0);
147*4882a593Smuzhiyun if (broadcast_fd < 0) {
148*4882a593Smuzhiyun perror("broadcast_thread : socket");
149*4882a593Smuzhiyun goto stop_broadcast;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun printf("broadcast_thread socketfd = %d\n", broadcast_fd);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun strcpy(ifr.ifr_name, "rndis0");
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun memset(local_addr, 0, FWK_MSG_IP_MAX_LEN);
156*4882a593Smuzhiyun memset(local_mac, 0, FWK_MSG_MAC_MAX_LEN);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun // get rndis ethernet interface ip address
159*4882a593Smuzhiyun while (ioctl(broadcast_fd, SIOCGIFADDR, &ifr) < 0) {
160*4882a593Smuzhiyun sleep(1);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun snprintf(local_addr, FWK_MSG_IP_MAX_LEN, "%s",
163*4882a593Smuzhiyun inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr));
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun // get rndis ethernet interface mac address
166*4882a593Smuzhiyun while (ioctl(broadcast_fd, SIOCGIFHWADDR, &ifr) < 0) {
167*4882a593Smuzhiyun sleep(1);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun snprintf(local_mac, FWK_MSG_MAC_MAX_LEN, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
170*4882a593Smuzhiyun (unsigned char)ifr.ifr_hwaddr.sa_data[0],
171*4882a593Smuzhiyun (unsigned char)ifr.ifr_hwaddr.sa_data[1],
172*4882a593Smuzhiyun (unsigned char)ifr.ifr_hwaddr.sa_data[2],
173*4882a593Smuzhiyun (unsigned char)ifr.ifr_hwaddr.sa_data[3],
174*4882a593Smuzhiyun (unsigned char)ifr.ifr_hwaddr.sa_data[4],
175*4882a593Smuzhiyun (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun printf("Discovery:got device net info!\n");
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun memset(&server_addr, 0, sizeof(server_addr));
180*4882a593Smuzhiyun server_addr.sin_family = AF_INET;
181*4882a593Smuzhiyun server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
182*4882a593Smuzhiyun server_addr.sin_port = htons(UDPPORT);
183*4882a593Smuzhiyun addr_len = sizeof(server_addr);
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if (setsockopt(broadcast_fd, SOL_SOCKET, SO_BROADCAST, (char *)&opt,
186*4882a593Smuzhiyun sizeof(opt)) < 0) {
187*4882a593Smuzhiyun perror("broadcast setsockopt SO_BROADCAST");
188*4882a593Smuzhiyun goto stop_broadcast;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun if (setsockopt(broadcast_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
191*4882a593Smuzhiyun sizeof(opt)) < 0) {
192*4882a593Smuzhiyun perror("broadcast setsockopt SO_REUSEADDR");
193*4882a593Smuzhiyun goto stop_broadcast;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (bind(broadcast_fd, (struct sockaddr *)&server_addr, addr_len) < 0) {
197*4882a593Smuzhiyun perror("broadcast bind");
198*4882a593Smuzhiyun goto stop_broadcast;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun while (1) {
202*4882a593Smuzhiyun memset(buf, 0, sizeof(buf));
203*4882a593Smuzhiyun memset(uid, 0, sizeof(uid));
204*4882a593Smuzhiyun memset(cmd_info, 0, sizeof(cmd_info));
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun fprintf(stderr,"=========function is: %s line is : %d=============\n",__func__,__LINE__);
208*4882a593Smuzhiyun if (recvfrom(broadcast_fd, buf, 64, 0,
209*4882a593Smuzhiyun (struct sockaddr *)&server_addr, &addr_len) < 0) {
210*4882a593Smuzhiyun perror("broadcast recvfrom");
211*4882a593Smuzhiyun continue;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun printf("broadcast: from: %s port: %d > %s\n",
215*4882a593Smuzhiyun inet_ntoa(server_addr.sin_addr),
216*4882a593Smuzhiyun ntohs(server_addr.sin_port), buf);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (strcmp("CMD_DISCOVER", buf) == 0) {
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if ((parameter_read_protocol_uid(uid)) < 0) {
221*4882a593Smuzhiyun printf("Discover:read uid failed!\n");
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun uid[FWK_MSG_UID_LEN] = '\0';
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun snprintf(cmd_info, FWK_MSG_CMD_LEN,
227*4882a593Smuzhiyun "{\"UID\":\"%s\","
228*4882a593Smuzhiyun "\"IP\":\"%s\","
229*4882a593Smuzhiyun "\"MAC\":\"%s\","
230*4882a593Smuzhiyun "\"DEVICENAME\":\"%s\"}",
231*4882a593Smuzhiyun uid,
232*4882a593Smuzhiyun local_addr,
233*4882a593Smuzhiyun local_mac,
234*4882a593Smuzhiyun "ECHO");
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun printf("sendto: %s port: %d > %s\n",
237*4882a593Smuzhiyun inet_ntoa(server_addr.sin_addr),
238*4882a593Smuzhiyun ntohs(server_addr.sin_port), cmd_info);
239*4882a593Smuzhiyun if (sendto(broadcast_fd, cmd_info, strlen(cmd_info),
240*4882a593Smuzhiyun 0, (struct sockaddr *)&server_addr, addr_len) < 0) {
241*4882a593Smuzhiyun perror("broadcast_thread recvfrom");
242*4882a593Smuzhiyun goto stop_broadcast;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun stop_broadcast:
248*4882a593Smuzhiyun printf("stop broadcast !\n");
249*4882a593Smuzhiyun if (broadcast_fd >= 0) {
250*4882a593Smuzhiyun shutdown(broadcast_fd, 2);
251*4882a593Smuzhiyun close(broadcast_fd);
252*4882a593Smuzhiyun broadcast_fd = -1;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun }
255