blob: 0dbcb419cb7917b5182998183d4fa55e120e4b89 [file] [log] [blame]
developer22c7ab62022-01-24 11:13:32 +08001/* Copyright (C) 2021-2022 Mediatek Inc. */
2
3#include <signal.h>
4#include <sys/select.h>
5#include <sys/wait.h>
6#include "atenl.h"
7
8static const char *progname;
9bool atenl_enable;
10
11void sig_handler(int signum)
12{
13 atenl_enable = false;
14}
15
16void atenl_init_signals()
17{
18 if (signal(SIGINT, sig_handler) == SIG_ERR)
19 goto out;
20 if (signal(SIGTERM, sig_handler) == SIG_ERR)
21 goto out;
22 if (signal(SIGABRT, sig_handler) == SIG_ERR)
23 goto out;
24 if (signal(SIGUSR1, sig_handler) == SIG_ERR)
25 goto out;
26 if (signal(SIGUSR2, sig_handler) == SIG_ERR)
27 goto out;
28
29 return;
30out:
31 perror("signal");
32}
33
34static int phy_lookup_idx(const char *name)
35{
36 char buf[128];
37 FILE *f;
38 size_t len;
39 int ret;
40
41 ret = snprintf(buf, sizeof(buf), "/sys/class/ieee80211/%s/index", name);
42 if (snprintf_error(sizeof(buf), ret))
43 return -1;
44
45 f = fopen(buf, "r");
46 if (!f)
47 return -1;
48
49 len = fread(buf, 1, sizeof(buf) - 1, f);
50 fclose(f);
51
52 if (!len)
53 return -1;
54
55 buf[len] = 0;
56 return atoi(buf);
57}
58
developer543811b2022-10-07 15:54:07 +080059static int get_default_bridge_name(struct atenl *an)
60{
61 char buf[128];
62 FILE *f;
developer543811b2022-10-07 15:54:07 +080063 int ret;
64
65 ret = snprintf(buf, sizeof(buf), "/sbin/procd");
66 if (snprintf_error(sizeof(buf), ret))
67 return -1;
68
69 f = fopen(buf, "r");
70
71 /* This procd is openwrt only */
72 if (f) {
73 an->bridge_name = BRIDGE_NAME_OPENWRT;
74 fclose(f);
75 } else {
76 an->bridge_name = BRIDGE_NAME_RDKB;
77 }
78
79 return 0;
80}
81
developer22c7ab62022-01-24 11:13:32 +080082static void usage(void)
83{
developerf30d4472022-05-30 16:40:23 +080084 printf("Usage:\n");
developer22c7ab62022-01-24 11:13:32 +080085 printf(" %s [-u] [-i phyX]\n", progname);
86 printf("options:\n"
87 " -h = show help text\n"
88 " -i = phy name of driver interface, please use first phy for dbdc\n"
developer543811b2022-10-07 15:54:07 +080089 " -u = use unicast to respond to HQADLL\n"
developerf0677ad2024-11-15 19:28:25 +080090 " -b = specify your bridge name\n"
91 " -c = eeprom-related command\n"
92 " -p = specify the flash partition name and offset (<name>:<offs>)\n");
developer22c7ab62022-01-24 11:13:32 +080093 printf("examples:\n"
developer543811b2022-10-07 15:54:07 +080094 " %s -u -i phy0 -b br-lan\n", progname);
developer22c7ab62022-01-24 11:13:32 +080095
96 exit(EXIT_FAILURE);
97}
98
developerf30d4472022-05-30 16:40:23 +080099static void atenl_handler_run(struct atenl *an)
developer22c7ab62022-01-24 11:13:32 +0800100{
developerf30d4472022-05-30 16:40:23 +0800101 int count, sock_eth = an->sock_eth;
developer22c7ab62022-01-24 11:13:32 +0800102 fd_set readfds;
103
developerf30d4472022-05-30 16:40:23 +0800104 atenl_info("Start atenl HQA command handler\n");
developer22c7ab62022-01-24 11:13:32 +0800105
106 while (atenl_enable) {
107 FD_ZERO(&readfds);
108 FD_SET(sock_eth, &readfds);
109 count = select(sock_eth + 1, &readfds, NULL, NULL, NULL);
110
111 if (count < 0) {
112 atenl_err("%s: select failed, %s\n", __func__, strerror(errno));
developer22c7ab62022-01-24 11:13:32 +0800113 } else if (count == 0) {
114 usleep(1000);
developer22c7ab62022-01-24 11:13:32 +0800115 } else {
developerf30d4472022-05-30 16:40:23 +0800116 if (!FD_ISSET(sock_eth, &readfds))
117 continue;
118 atenl_hqa_proc_cmd(an);
developer22c7ab62022-01-24 11:13:32 +0800119 }
120 }
121
developerf30d4472022-05-30 16:40:23 +0800122 atenl_dbg("HQA command handler end\n");
developer22c7ab62022-01-24 11:13:32 +0800123}
124
developer22c7ab62022-01-24 11:13:32 +0800125int main(int argc, char **argv)
126{
127 int opt, phy_idx, ret = 0;
128 char *phy = "phy0", *cmd = NULL;
developerf0677ad2024-11-15 19:28:25 +0800129 char *token;
developer22c7ab62022-01-24 11:13:32 +0800130 struct atenl *an;
131
132 progname = argv[0];
133
134 an = calloc(1, sizeof(struct atenl));
135 if (!an)
136 return -ENOMEM;
137
138 while(1) {
developerf0677ad2024-11-15 19:28:25 +0800139 opt = getopt(argc, argv, "hi:uc:b:p:");
developer22c7ab62022-01-24 11:13:32 +0800140 if (opt == -1)
141 break;
142
143 switch (opt) {
144 case 'h':
145 usage();
developerf30d4472022-05-30 16:40:23 +0800146 goto out;
developer22c7ab62022-01-24 11:13:32 +0800147 case 'i':
148 phy = optarg;
149 break;
developer543811b2022-10-07 15:54:07 +0800150 case 'b':
151 an->bridge_name = optarg;
152 break;
developer22c7ab62022-01-24 11:13:32 +0800153 case 'u':
154 an->unicast = true;
155 printf("Opt: use unicast to send response\n");
156 break;
157 case 'c':
158 cmd = optarg;
159 break;
developerf0677ad2024-11-15 19:28:25 +0800160 case 'p':
161 token = strtok(optarg, ":");
162 if (!token)
163 break;
164 an->flash_part = token;
165 an->flash_offset = strtol(strtok(NULL, ":"), NULL, 0);
166 break;
developer22c7ab62022-01-24 11:13:32 +0800167 default:
developerf30d4472022-05-30 16:40:23 +0800168 atenl_err("Not supported option: %c\n", opt);
169 goto out;
developer22c7ab62022-01-24 11:13:32 +0800170 }
171 }
172
173 phy_idx = phy_lookup_idx(phy);
174 if (phy_idx < 0 || phy_idx > UCHAR_MAX) {
developerf30d4472022-05-30 16:40:23 +0800175 atenl_err("Could not find phy '%s'\n", phy);
176 goto out;
developer22c7ab62022-01-24 11:13:32 +0800177 }
178
179 if (cmd) {
180 atenl_eeprom_cmd_handler(an, phy_idx, cmd);
181 goto out;
182 }
183
184 atenl_enable = true;
185 atenl_init_signals();
186
developer543811b2022-10-07 15:54:07 +0800187 if (!an->bridge_name) {
188 ret = get_default_bridge_name(an);
189 if (ret) {
190 atenl_err("Get default bridge name failed\n");
191 goto out;
192 }
193
194 atenl_info("Bridge name is not specified, use default bridge name: %s\n", an->bridge_name);
195 } else {
196 atenl_info("Currently using bridge name: %s\n", an->bridge_name);
197 }
198
developer22c7ab62022-01-24 11:13:32 +0800199 /* background ourself */
200 if (!fork()) {
developer22c7ab62022-01-24 11:13:32 +0800201 ret = atenl_eeprom_init(an, phy_idx);
202 if (ret)
203 goto out;
204
205 ret = atenl_eth_init(an);
206 if (ret)
207 goto out;
208
developerf30d4472022-05-30 16:40:23 +0800209 atenl_handler_run(an);
developer22c7ab62022-01-24 11:13:32 +0800210 } else {
211 usleep(800000);
212 }
213
214 ret = 0;
215out:
216 if (an->sock_eth)
217 close(an->sock_eth);
218 if (an->eeprom_fd || an->eeprom_data)
219 atenl_eeprom_close(an);
220 free(an);
221
222 return ret;
223}