blob: 9667da3ef3c4e1baf8f4094451faa7df3f05bbce [file] [log] [blame]
developer3abe1ad2022-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
59static void usage(void)
60{
developer5698c9c2022-05-30 16:40:23 +080061 printf("Usage:\n");
developer3abe1ad2022-01-24 11:13:32 +080062 printf(" %s [-u] [-i phyX]\n", progname);
63 printf("options:\n"
64 " -h = show help text\n"
65 " -i = phy name of driver interface, please use first phy for dbdc\n"
66 " -u = use unicast to respond to HQADLL\n");
67 printf("examples:\n"
68 " %s -u -i phy0\n", progname);
69
70 exit(EXIT_FAILURE);
71}
72
developer5698c9c2022-05-30 16:40:23 +080073static void atenl_handler_run(struct atenl *an)
developer3abe1ad2022-01-24 11:13:32 +080074{
developer5698c9c2022-05-30 16:40:23 +080075 int count, sock_eth = an->sock_eth;
developer3abe1ad2022-01-24 11:13:32 +080076 fd_set readfds;
77
developer5698c9c2022-05-30 16:40:23 +080078 atenl_info("Start atenl HQA command handler\n");
developer3abe1ad2022-01-24 11:13:32 +080079
80 while (atenl_enable) {
81 FD_ZERO(&readfds);
82 FD_SET(sock_eth, &readfds);
83 count = select(sock_eth + 1, &readfds, NULL, NULL, NULL);
84
85 if (count < 0) {
86 atenl_err("%s: select failed, %s\n", __func__, strerror(errno));
developer3abe1ad2022-01-24 11:13:32 +080087 } else if (count == 0) {
88 usleep(1000);
developer3abe1ad2022-01-24 11:13:32 +080089 } else {
developer5698c9c2022-05-30 16:40:23 +080090 if (!FD_ISSET(sock_eth, &readfds))
91 continue;
92 atenl_hqa_proc_cmd(an);
developer3abe1ad2022-01-24 11:13:32 +080093 }
94 }
95
developer5698c9c2022-05-30 16:40:23 +080096 atenl_dbg("HQA command handler end\n");
developer3abe1ad2022-01-24 11:13:32 +080097}
98
developer3abe1ad2022-01-24 11:13:32 +080099int main(int argc, char **argv)
100{
101 int opt, phy_idx, ret = 0;
102 char *phy = "phy0", *cmd = NULL;
103 struct atenl *an;
104
105 progname = argv[0];
106
107 an = calloc(1, sizeof(struct atenl));
108 if (!an)
109 return -ENOMEM;
110
111 while(1) {
112 opt = getopt(argc, argv, "hi:uc:");
113 if (opt == -1)
114 break;
115
116 switch (opt) {
117 case 'h':
118 usage();
developer5698c9c2022-05-30 16:40:23 +0800119 goto out;
developer3abe1ad2022-01-24 11:13:32 +0800120 case 'i':
121 phy = optarg;
122 break;
123 case 'u':
124 an->unicast = true;
125 printf("Opt: use unicast to send response\n");
126 break;
127 case 'c':
128 cmd = optarg;
129 break;
130 default:
developer5698c9c2022-05-30 16:40:23 +0800131 atenl_err("Not supported option: %c\n", opt);
132 goto out;
developer3abe1ad2022-01-24 11:13:32 +0800133 }
134 }
135
136 phy_idx = phy_lookup_idx(phy);
137 if (phy_idx < 0 || phy_idx > UCHAR_MAX) {
developer5698c9c2022-05-30 16:40:23 +0800138 atenl_err("Could not find phy '%s'\n", phy);
139 goto out;
developer3abe1ad2022-01-24 11:13:32 +0800140 }
141
142 if (cmd) {
143 atenl_eeprom_cmd_handler(an, phy_idx, cmd);
144 goto out;
145 }
146
147 atenl_enable = true;
148 atenl_init_signals();
149
150 /* background ourself */
151 if (!fork()) {
developer3abe1ad2022-01-24 11:13:32 +0800152 ret = atenl_eeprom_init(an, phy_idx);
153 if (ret)
154 goto out;
155
156 ret = atenl_eth_init(an);
157 if (ret)
158 goto out;
159
developer5698c9c2022-05-30 16:40:23 +0800160 atenl_handler_run(an);
developer3abe1ad2022-01-24 11:13:32 +0800161 } else {
162 usleep(800000);
163 }
164
165 ret = 0;
166out:
167 if (an->sock_eth)
168 close(an->sock_eth);
169 if (an->eeprom_fd || an->eeprom_data)
170 atenl_eeprom_close(an);
171 free(an);
172
173 return ret;
174}