source: mainline/uspace/app/trace/ipcp.c@ 47e0a05b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 47e0a05b was 1643855, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

trace: Command-line options to select display mode. Skeleton 'protocol-level' mode (the default)

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2008 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup trace
30 * @{
31 */
32/** @file
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <libadt/hash_table.h>
38
39#include "ipc_desc.h"
40#include "proto.h"
41#include "trace.h"
42#include "ipcp.h"
43
44#define IPCP_CALLID_SYNC 0
45
46typedef struct {
47 int phone_hash;
48 ipc_call_t question;
49
50 int call_hash;
51
52 link_t link;
53} pending_call_t;
54
55typedef struct {
56 int server;
57 proto_t *proto;
58} connection_t;
59
60#define MAX_PHONE 64
61connection_t connections[MAX_PHONE];
62int have_conn[MAX_PHONE];
63
64#define PCALL_TABLE_CHAINS 32
65hash_table_t pending_calls;
66
67/*
68 * Pseudo-protocols
69 */
70proto_t *proto_system; /**< Protocol describing system IPC methods. */
71proto_t *proto_unknown; /**< Protocol with no known methods. */
72
73static hash_index_t pending_call_hash(unsigned long key[]);
74static int pending_call_compare(unsigned long key[], hash_count_t keys,
75 link_t *item);
76static void pending_call_remove_callback(link_t *item);
77
78hash_table_operations_t pending_call_ops = {
79 .hash = pending_call_hash,
80 .compare = pending_call_compare,
81 .remove_callback = pending_call_remove_callback
82};
83
84
85static hash_index_t pending_call_hash(unsigned long key[])
86{
87// printf("pending_call_hash\n");
88 return key[0] % PCALL_TABLE_CHAINS;
89}
90
91static int pending_call_compare(unsigned long key[], hash_count_t keys,
92 link_t *item)
93{
94 pending_call_t *hs;
95
96// printf("pending_call_compare\n");
97 hs = hash_table_get_instance(item, pending_call_t, link);
98
99 return key[0] == hs->call_hash;
100}
101
102static void pending_call_remove_callback(link_t *item)
103{
104// printf("pending_call_remove_callback\n");
105}
106
107
108void ipcp_connection_set(int phone, int server, proto_t *proto)
109{
110 if (phone <0 || phone >= MAX_PHONE) return;
111 connections[phone].server = server;
112 connections[phone].proto = proto;
113 have_conn[phone] = 1;
114}
115
116void ipcp_connection_clear(int phone)
117{
118 have_conn[phone] = 0;
119 connections[phone].server = 0;
120 connections[phone].proto = NULL;
121}
122
123static void ipc_m_print(proto_t *proto, ipcarg_t method)
124{
125 oper_t *oper;
126
127 /* Try system methods first */
128 oper = proto_get_oper(proto_system, method);
129
130 if (oper == NULL && proto != NULL) {
131 /* Not a system method, try the user protocol. */
132 oper = proto_get_oper(proto, method);
133 }
134
135 if (oper != NULL) {
136 printf("%s (%d)", oper->name, method);
137 return;
138 }
139
140 printf("%d", method);
141}
142
143void ipcp_init(void)
144{
145 ipc_m_desc_t *desc;
146 oper_t *oper;
147
148 /*
149 * Create a pseudo-protocol 'unknown' that has no known methods.
150 */
151 proto_unknown = proto_new("unknown");
152
153 /*
154 * Create a pseudo-protocol 'system' defining names of system IPC
155 * methods.
156 */
157 proto_system = proto_new("system");
158
159 desc = ipc_methods;
160 while (desc->number != 0) {
161 oper = oper_new(desc->name);
162 proto_add_oper(proto_system, desc->number, oper);
163
164 ++desc;
165 }
166
167 hash_table_create(&pending_calls, PCALL_TABLE_CHAINS, 1, &pending_call_ops);
168}
169
170void ipcp_cleanup(void)
171{
172 proto_delete(proto_system);
173 hash_table_destroy(&pending_calls);
174}
175
176void ipcp_call_out(int phone, ipc_call_t *call, ipc_callid_t hash)
177{
178 pending_call_t *pcall;
179 proto_t *proto;
180 unsigned long key[1];
181 oper_t *oper;
182
183 if (have_conn[phone]) proto = connections[phone].proto;
184 else proto = NULL;
185
186 if ((display_mask & DM_IPC) != 0) {
187 printf("Call ID: 0x%x, phone: %d, proto: %s, method: ", hash,
188 phone, (proto ? proto->name : "n/a"));
189 ipc_m_print(proto, IPC_GET_METHOD(*call));
190 printf(" args: (%u, %u, %u, %u, %u)\n",
191 IPC_GET_ARG1(*call),
192 IPC_GET_ARG2(*call),
193 IPC_GET_ARG3(*call),
194 IPC_GET_ARG4(*call),
195 IPC_GET_ARG5(*call)
196 );
197 }
198
199
200 if ((display_mask & DM_USER) != 0) {
201
202 if (proto != NULL) {
203 oper = proto_get_oper(proto, IPC_GET_METHOD(*call));
204 } else {
205 oper = NULL;
206 }
207
208 if (oper != NULL) {
209
210 printf("%s(%d).%s", (proto ? proto->name : "n/a"),
211 phone, (oper ? oper->name : "unknown"));
212
213 printf("(%u, %u, %u, %u, %u)\n",
214 IPC_GET_ARG1(*call),
215 IPC_GET_ARG2(*call),
216 IPC_GET_ARG3(*call),
217 IPC_GET_ARG4(*call),
218 IPC_GET_ARG5(*call)
219 );
220 }
221 }
222
223 /* Store call in hash table for response matching */
224
225 pcall = malloc(sizeof(pending_call_t));
226 pcall->phone_hash = phone;
227 pcall->question = *call;
228 pcall->call_hash = hash;
229
230 key[0] = hash;
231
232 hash_table_insert(&pending_calls, key, &pcall->link);
233}
234
235static void parse_answer(ipc_callid_t hash, pending_call_t *pcall,
236 ipc_call_t *answer)
237{
238 int phone;
239 ipcarg_t method;
240 ipcarg_t service;
241 int retval;
242 proto_t *proto;
243 int cphone;
244
245// printf("parse_answer\n");
246
247 phone = pcall->phone_hash;
248 method = IPC_GET_METHOD(pcall->question);
249 retval = IPC_GET_RETVAL(*answer);
250
251 if ((display_mask & DM_IPC) != 0) {
252 printf("Response to 0x%x: retval=%d, args = (%u, %u, %u, %u, %u)\n",
253 hash, retval, IPC_GET_ARG1(*answer),
254 IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
255 IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
256 }
257
258 if ((display_mask & DM_USER) != 0) {
259 printf("-> %d\n", retval);
260 }
261
262 if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
263 /* Connected to a service (through NS) */
264 service = IPC_GET_ARG1(pcall->question);
265 proto = proto_get_by_srv(service);
266 if (proto == NULL) proto = proto_unknown;
267
268 cphone = IPC_GET_ARG5(*answer);
269 if ((display_mask & DM_SYSTEM) != 0) {
270 printf("Registering connection (phone %d, protocol: %s)\n", cphone,
271 proto->name);
272 }
273 ipcp_connection_set(cphone, 0, proto);
274 }
275}
276
277void ipcp_call_in(ipc_call_t *call, ipc_callid_t hash)
278{
279 link_t *item;
280 pending_call_t *pcall;
281 unsigned long key[1];
282
283// printf("ipcp_call_in()\n");
284/* printf("phone: %d, method: ", call->in_phone_hash);
285 ipc_m_print(IPC_GET_METHOD(*call));
286 printf(" args: (%u, %u, %u, %u, %u)\n",
287 IPC_GET_ARG1(*call),
288 IPC_GET_ARG2(*call),
289 IPC_GET_ARG3(*call),
290 IPC_GET_ARG4(*call),
291 IPC_GET_ARG5(*call)
292 );*/
293
294 if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
295 /* Not a response */
296 if ((display_mask & DM_IPC) != 0) {
297 printf("Not a response (hash %d)\n", hash);
298 }
299 return;
300 }
301
302 hash = hash & ~IPC_CALLID_ANSWERED;
303 key[0] = hash;
304
305 item = hash_table_find(&pending_calls, key);
306 if (item == NULL) return; // No matching question found
307
308 /*
309 * Response matched to question.
310 */
311
312 pcall = hash_table_get_instance(item, pending_call_t, link);
313 hash_table_remove(&pending_calls, key, 1);
314
315 parse_answer(hash, pcall, call);
316 free(pcall);
317}
318
319void ipcp_call_sync(int phone, ipc_call_t *call, ipc_call_t *answer)
320{
321 ipcp_call_out(phone, call, IPCP_CALLID_SYNC);
322 ipcp_call_in(answer, IPCP_CALLID_SYNC);
323}
324
325void ipcp_hangup(int phone, int rc)
326{
327 if ((display_mask & DM_SYSTEM) != 0) {
328 printf("Hang phone %d up -> %d\n", phone, rc);
329 ipcp_connection_clear(phone);
330 }
331}
332
333/** @}
334 */
Note: See TracBrowser for help on using the repository browser.