xref: /OK3568_Linux_fs/external/rk_pcba_test/echo_discovery.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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