1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/string.h>
34#include <linux/socket.h>
35#include <linux/fs.h>
36#include <linux/seq_file.h>
37
38#include <net/irda/irda.h>
39#include <net/irda/irlmp.h>
40
41#include <net/irda/discovery.h>
42
43#include <asm/unaligned.h>
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new)
61{
62 discovery_t *discovery, *node;
63 unsigned long flags;
64
65
66 new->firststamp = new->timestamp;
67
68 spin_lock_irqsave(&cachelog->hb_spinlock, flags);
69
70
71
72
73
74
75
76 discovery = (discovery_t *) hashbin_get_first(cachelog);
77 while (discovery != NULL ) {
78 node = discovery;
79
80
81 discovery = (discovery_t *) hashbin_get_next(cachelog);
82
83 if ((node->data.saddr == new->data.saddr) &&
84 ((node->data.daddr == new->data.daddr) ||
85 (strcmp(node->data.info, new->data.info) == 0)))
86 {
87
88
89
90 hashbin_remove_this(cachelog, (irda_queue_t *) node);
91
92 if (get_unaligned((__u16 *)node->data.hints) == get_unaligned((__u16 *)new->data.hints))
93
94 new->firststamp = node->firststamp;
95 kfree(node);
96 }
97 }
98
99
100 hashbin_insert(cachelog, (irda_queue_t *) new, new->data.daddr, NULL);
101
102 spin_unlock_irqrestore(&cachelog->hb_spinlock, flags);
103}
104
105
106
107
108
109
110
111void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log)
112{
113 discovery_t *discovery;
114
115 IRDA_DEBUG(4, "%s()\n", __func__);
116
117
118
119
120
121
122
123 if (log == NULL) {
124
125 return;
126 }
127
128
129
130
131
132
133 discovery = (discovery_t *) hashbin_remove_first(log);
134 while (discovery != NULL) {
135 irlmp_add_discovery(cachelog, discovery);
136
137 discovery = (discovery_t *) hashbin_remove_first(log);
138 }
139
140
141 hashbin_delete(log, (FREE_FUNC) kfree);
142}
143
144
145
146
147
148
149
150
151
152void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
153{
154 discovery_t * discovery;
155 discovery_t * curr;
156 unsigned long flags;
157 discinfo_t * buffer = NULL;
158 int n;
159 int i = 0;
160
161 IRDA_ASSERT(log != NULL, return;);
162 IRDA_DEBUG(4, "%s()\n", __func__);
163
164 spin_lock_irqsave(&log->hb_spinlock, flags);
165
166 discovery = (discovery_t *) hashbin_get_first(log);
167 while (discovery != NULL) {
168
169 curr = discovery;
170 discovery = (discovery_t *) hashbin_get_next(log);
171
172
173 if ((curr->data.saddr == saddr) &&
174 (force ||
175 ((jiffies - curr->timestamp) > DISCOVERY_EXPIRE_TIMEOUT)))
176 {
177
178
179
180
181
182 if(buffer == NULL) {
183
184 n = HASHBIN_GET_SIZE(log);
185 buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
186 if (buffer == NULL) {
187 spin_unlock_irqrestore(&log->hb_spinlock, flags);
188 return;
189 }
190
191 }
192
193
194 memcpy(&(buffer[i]), &(curr->data),
195 sizeof(discinfo_t));
196 i++;
197
198
199 curr = hashbin_remove_this(log, (irda_queue_t *) curr);
200 kfree(curr);
201 }
202 }
203
204
205
206
207
208 spin_unlock_irqrestore(&log->hb_spinlock, flags);
209
210 if(buffer == NULL)
211 return;
212
213
214 irlmp_discovery_expiry(buffer, i);
215
216
217 kfree(buffer);
218}
219
220#if 0
221
222
223
224
225
226
227void irlmp_dump_discoveries(hashbin_t *log)
228{
229 discovery_t *discovery;
230
231 IRDA_ASSERT(log != NULL, return;);
232
233 discovery = (discovery_t *) hashbin_get_first(log);
234 while (discovery != NULL) {
235 IRDA_DEBUG(0, "Discovery:\n");
236 IRDA_DEBUG(0, " daddr=%08x\n", discovery->data.daddr);
237 IRDA_DEBUG(0, " saddr=%08x\n", discovery->data.saddr);
238 IRDA_DEBUG(0, " nickname=%s\n", discovery->data.info);
239
240 discovery = (discovery_t *) hashbin_get_next(log);
241 }
242}
243#endif
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn,
266 __u16 mask, int old_entries)
267{
268 discovery_t * discovery;
269 unsigned long flags;
270 discinfo_t * buffer = NULL;
271 int j_timeout = (sysctl_discovery_timeout * HZ);
272 int n;
273 int i = 0;
274
275 IRDA_ASSERT(pn != NULL, return NULL;);
276 IRDA_ASSERT(log != NULL, return NULL;);
277
278
279 spin_lock_irqsave(&log->hb_spinlock, flags);
280
281 discovery = (discovery_t *) hashbin_get_first(log);
282 while (discovery != NULL) {
283
284
285
286 if ((get_unaligned((__u16 *)discovery->data.hints) & mask) &&
287 ((old_entries) ||
288 ((jiffies - discovery->firststamp) < j_timeout))) {
289
290
291
292
293
294 if(buffer == NULL) {
295
296 n = HASHBIN_GET_SIZE(log);
297 buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
298 if (buffer == NULL) {
299 spin_unlock_irqrestore(&log->hb_spinlock, flags);
300 return NULL;
301 }
302
303 }
304
305
306 memcpy(&(buffer[i]), &(discovery->data),
307 sizeof(discinfo_t));
308 i++;
309 }
310 discovery = (discovery_t *) hashbin_get_next(log);
311 }
312
313 spin_unlock_irqrestore(&log->hb_spinlock, flags);
314
315
316 *pn = i;
317 return(buffer);
318}
319
320#ifdef CONFIG_PROC_FS
321static inline discovery_t *discovery_seq_idx(loff_t pos)
322
323{
324 discovery_t *discovery;
325
326 for (discovery = (discovery_t *) hashbin_get_first(irlmp->cachelog);
327 discovery != NULL;
328 discovery = (discovery_t *) hashbin_get_next(irlmp->cachelog)) {
329 if (pos-- == 0)
330 break;
331 }
332
333 return discovery;
334}
335
336static void *discovery_seq_start(struct seq_file *seq, loff_t *pos)
337{
338 spin_lock_irq(&irlmp->cachelog->hb_spinlock);
339 return *pos ? discovery_seq_idx(*pos - 1) : SEQ_START_TOKEN;
340}
341
342static void *discovery_seq_next(struct seq_file *seq, void *v, loff_t *pos)
343{
344 ++*pos;
345 return (v == SEQ_START_TOKEN)
346 ? (void *) hashbin_get_first(irlmp->cachelog)
347 : (void *) hashbin_get_next(irlmp->cachelog);
348}
349
350static void discovery_seq_stop(struct seq_file *seq, void *v)
351{
352 spin_unlock_irq(&irlmp->cachelog->hb_spinlock);
353}
354
355static int discovery_seq_show(struct seq_file *seq, void *v)
356{
357 if (v == SEQ_START_TOKEN)
358 seq_puts(seq, "IrLMP: Discovery log:\n\n");
359 else {
360 const discovery_t *discovery = v;
361
362 seq_printf(seq, "nickname: %s, hint: 0x%02x%02x",
363 discovery->data.info,
364 discovery->data.hints[0],
365 discovery->data.hints[1]);
366#if 0
367 if ( discovery->data.hints[0] & HINT_PNP)
368 seq_puts(seq, "PnP Compatible ");
369 if ( discovery->data.hints[0] & HINT_PDA)
370 seq_puts(seq, "PDA/Palmtop ");
371 if ( discovery->data.hints[0] & HINT_COMPUTER)
372 seq_puts(seq, "Computer ");
373 if ( discovery->data.hints[0] & HINT_PRINTER)
374 seq_puts(seq, "Printer ");
375 if ( discovery->data.hints[0] & HINT_MODEM)
376 seq_puts(seq, "Modem ");
377 if ( discovery->data.hints[0] & HINT_FAX)
378 seq_puts(seq, "Fax ");
379 if ( discovery->data.hints[0] & HINT_LAN)
380 seq_puts(seq, "LAN Access ");
381
382 if ( discovery->data.hints[1] & HINT_TELEPHONY)
383 seq_puts(seq, "Telephony ");
384 if ( discovery->data.hints[1] & HINT_FILE_SERVER)
385 seq_puts(seq, "File Server ");
386 if ( discovery->data.hints[1] & HINT_COMM)
387 seq_puts(seq, "IrCOMM ");
388 if ( discovery->data.hints[1] & HINT_OBEX)
389 seq_puts(seq, "IrOBEX ");
390#endif
391 seq_printf(seq,", saddr: 0x%08x, daddr: 0x%08x\n\n",
392 discovery->data.saddr,
393 discovery->data.daddr);
394
395 seq_putc(seq, '\n');
396 }
397 return 0;
398}
399
400static const struct seq_operations discovery_seq_ops = {
401 .start = discovery_seq_start,
402 .next = discovery_seq_next,
403 .stop = discovery_seq_stop,
404 .show = discovery_seq_show,
405};
406
407static int discovery_seq_open(struct inode *inode, struct file *file)
408{
409 IRDA_ASSERT(irlmp != NULL, return -EINVAL;);
410
411 return seq_open(file, &discovery_seq_ops);
412}
413
414const struct file_operations discovery_seq_fops = {
415 .owner = THIS_MODULE,
416 .open = discovery_seq_open,
417 .read = seq_read,
418 .llseek = seq_lseek,
419 .release = seq_release,
420};
421#endif
422