blob: 80cf984b8ab90d3285cffe1df1474548760aae72 [file] [log] [blame]
Amit Pundird477f822020-02-07 22:26:08 +05301#include <err.h>
2#include <errno.h>
3#include <libgen.h>
4#include <linux/qrtr.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/types.h>
9#include <sys/socket.h>
10#include <sys/time.h>
11#include <unistd.h>
12
13#include "libqrtr.h"
14#include "logging.h"
15#include "ns.h"
16#include "util.h"
17
18#define DIAG_SERVICE 4097
19
20static const struct {
21 unsigned int service;
22 unsigned int ifilter;
23 const char *name;
24} common_names[] = {
25 { 0, 0, "Control service" },
26 { 1, 0, "Wireless Data Service" },
27 { 2, 0, "Device Management Service" },
28 { 3, 0, "Network Access Service" },
29 { 4, 0, "Quality Of Service service" },
30 { 5, 0, "Wireless Messaging Service" },
31 { 6, 0, "Position Determination Service" },
32 { 7, 0, "Authentication service" },
33 { 8, 0, "AT service" },
34 { 9, 0, "Voice service" },
35 { 10, 0, "Card Application Toolkit service (v2)" },
36 { 11, 0, "User Identity Module service" },
37 { 12, 0, "Phonebook Management service" },
38 { 13, 0, "QCHAT service" },
39 { 14, 0, "Remote file system service" },
40 { 15, 0, "Test service" },
41 { 16, 0, "Location service (~ PDS v2)" },
42 { 17, 0, "Specific absorption rate service" },
43 { 18, 0, "IMS settings service" },
44 { 19, 0, "Analog to digital converter driver service" },
45 { 20, 0, "Core sound driver service" },
46 { 21, 0, "Modem embedded file system service" },
47 { 22, 0, "Time service" },
48 { 23, 0, "Thermal sensors service" },
49 { 24, 0, "Thermal mitigation device service" },
50 { 25, 0, "Service access proxy service" },
51 { 26, 0, "Wireless data administrative service" },
52 { 27, 0, "TSYNC control service" },
53 { 28, 0, "Remote file system access service" },
54 { 29, 0, "Circuit switched videotelephony service" },
55 { 30, 0, "Qualcomm mobile access point service" },
56 { 31, 0, "IMS presence service" },
57 { 32, 0, "IMS videotelephony service" },
58 { 33, 0, "IMS application service" },
59 { 34, 0, "Coexistence service" },
60 { 36, 0, "Persistent device configuration service" },
61 { 38, 0, "Simultaneous transmit service" },
62 { 39, 0, "Bearer independent transport service" },
63 { 40, 0, "IMS RTP service" },
64 { 41, 0, "RF radiated performance enhancement service" },
65 { 42, 0, "Data system determination service" },
66 { 43, 0, "Subsystem control service" },
Amit Pundir53c12872022-10-27 21:55:51 +053067 { 47, 0, "Data Port Mapper service" },
Amit Pundird477f822020-02-07 22:26:08 +053068 { 49, 0, "IPA control service" },
69 { 51, 0, "CoreSight remote tracing service" },
70 { 52, 0, "Dynamic Heap Memory Sharing" },
71 { 64, 0, "Service registry locator service" },
72 { 66, 0, "Service registry notification service" },
73 { 69, 0, "ATH10k WLAN firmware service" },
74 { 224, 0, "Card Application Toolkit service (v1)" },
75 { 225, 0, "Remote Management Service" },
76 { 226, 0, "Open Mobile Alliance device management service" },
77 { 312, 0, "QBT1000 Ultrasonic Fingerprint Sensor service" },
78 { 769, 0, "SLIMbus control service" },
79 { 771, 0, "Peripheral Access Control Manager service" },
Amit Pundir53c12872022-10-27 21:55:51 +053080 { 4096, 0, "TFTP" },
Amit Pundird477f822020-02-07 22:26:08 +053081 { DIAG_SERVICE, 0, "DIAG service" },
82};
83
84static const char *diag_instance_base_str(unsigned int instance_base)
85{
86 switch (instance_base) {
87 case 0: return "MODEM";
88 case 1: return "LPASS";
89 case 2: return "WCNSS";
90 case 3: return "SENSORS";
91 case 4: return "CDSP";
92 case 5: return "WDSP";
93 default: return "<unk>";
94 }
95}
96
97static const char *diag_instance_str(unsigned int instance)
98{
99 switch (instance) {
100 case 0: return "CNTL";
101 case 1: return "CMD";
102 case 2: return "DATA";
103 case 3: return "DCI_CMD";
104 case 4: return "DCI";
105 default: return "<unk>";
106 }
107}
108
109static int get_diag_instance_info(char *str, size_t size, unsigned int instance)
110{
111 return snprintf(str, size, "%s:%s",
112 diag_instance_base_str(instance >> 6),
113 diag_instance_str(instance & 0x3f));
114}
115
116static unsigned int read_num_le(const char *str, int *rcp)
117{
118 unsigned int ret;
119 char *e;
120
121 if (*rcp)
122 return 0;
123
124 errno = 0;
125 ret = strtoul(str, &e, 0);
126 *rcp = -(errno || *e);
127
128 return cpu_to_le32(ret);
129}
130
131int main(int argc, char **argv)
132{
133 struct qrtr_ctrl_pkt pkt;
134 struct sockaddr_qrtr sq;
135 unsigned int instance;
136 unsigned int service;
137 unsigned int version;
138 unsigned int node;
139 unsigned int port;
140 socklen_t sl = sizeof(sq);
141 struct timeval tv;
142 int sock;
143 int len;
144 int rc;
145 const char *progname = basename(argv[0]);
146
147 qlog_setup(progname, false);
148
149 rc = 0;
150 memset(&pkt, 0, sizeof(pkt));
151
152 switch (argc) {
153 default:
154 rc = -1;
155 break;
156 case 3: pkt.server.instance = read_num_le(argv[2], &rc);
157 case 2: pkt.server.service = read_num_le(argv[1], &rc);
158 case 1: break;
159 }
160 if (rc) {
161 fprintf(stderr, "Usage: %s [<service> [<instance> [<filter>]]]\n", progname);
162 exit(1);
163 }
164
165 sock = socket(AF_QIPCRTR, SOCK_DGRAM, 0);
166 if (sock < 0)
167 PLOGE_AND_EXIT("sock(AF_QIPCRTR)");
168
169 rc = getsockname(sock, (void *)&sq, &sl);
170 if (rc || sq.sq_family != AF_QIPCRTR || sl != sizeof(sq))
171 PLOGE_AND_EXIT("getsockname()");
172
173 sq.sq_port = QRTR_PORT_CTRL;
174
175 tv.tv_sec = 1;
176 tv.tv_usec = 0;
177
178 pkt.cmd = cpu_to_le32(QRTR_TYPE_NEW_LOOKUP);
179
180 rc = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
181 if (rc)
182 PLOGE_AND_EXIT("setsockopt(SO_RCVTIMEO)");
183
184 rc = sendto(sock, &pkt, sizeof(pkt), 0, (void *)&sq, sizeof(sq));
185 if (rc < 0)
186 PLOGE_AND_EXIT("sendto()");
187
188 printf(" Service Version Instance Node Port\n");
189
190 while ((len = recv(sock, &pkt, sizeof(pkt), 0)) > 0) {
191 unsigned int type = le32_to_cpu(pkt.cmd);
192 const char *name = NULL;
193 unsigned int i;
194
195 if (len < sizeof(pkt) || type != QRTR_TYPE_NEW_SERVER) {
196 PLOGW("invalid/short packet");
197 continue;
198 }
199
200 if (!pkt.server.service && !pkt.server.instance &&
201 !pkt.server.node && !pkt.server.port)
202 break;
203
204 service = le32_to_cpu(pkt.server.service);
205 version = le32_to_cpu(pkt.server.instance) & 0xff;
206 instance = le32_to_cpu(pkt.server.instance) >> 8;
207 node = le32_to_cpu(pkt.server.node);
208 port = le32_to_cpu(pkt.server.port);
209
210 for (i = 0; i < sizeof(common_names)/sizeof(common_names[0]); ++i) {
211 if (service != common_names[i].service)
212 continue;
213 if (instance &&
214 (instance & common_names[i].ifilter) != common_names[i].ifilter)
215 continue;
216 name = common_names[i].name;
217 }
218 if (!name)
219 name = "<unknown>";
220
221 if (service == DIAG_SERVICE) {
222 char buf[24];
223 instance = le32_to_cpu(pkt.server.instance);
224 get_diag_instance_info(buf, sizeof(buf), instance);
225 printf("%9d %7s %8d %4d %5d %s (%s)\n",
226 service, "N/A", instance, node, port, name, buf);
227 } else {
228 printf("%9d %7d %8d %4d %5d %s\n",
229 service, version, instance, node, port, name);
230 }
231 }
232
233 if (len < 0)
234 PLOGE_AND_EXIT("recv()");
235
236 close(sock);
237
238 return 0;
239}