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#include <linux/string.h>
32#include <linux/socket.h>
33#include <linux/fs.h>
34#include <linux/seq_file.h>
35#include <linux/slab.h>
36#include <linux/export.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
116
117
118
119
120
121 if (log == NULL) {
122
123 return;
124 }
125
126
127
128
129
130
131 discovery = (discovery_t *) hashbin_remove_first(log);
132 while (discovery != NULL) {
133 irlmp_add_discovery(cachelog, discovery);
134
135 discovery = (discovery_t *) hashbin_remove_first(log);
136 }
137
138
139 hashbin_delete(log, (FREE_FUNC) kfree);
140}
141
142
143
144
145
146
147
148
149
150void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force)
151{
152 discovery_t * discovery;
153 discovery_t * curr;
154 unsigned long flags;
155 discinfo_t * buffer = NULL;
156 int n;
157 int i = 0;
158
159 IRDA_ASSERT(log != NULL, return;);
160 spin_lock_irqsave(&log->hb_spinlock, flags);
161
162 discovery = (discovery_t *) hashbin_get_first(log);
163 while (discovery != NULL) {
164
165 curr = discovery;
166 discovery = (discovery_t *) hashbin_get_next(log);
167
168
169 if ((curr->data.saddr == saddr) &&
170 (force ||
171 ((jiffies - curr->timestamp) > DISCOVERY_EXPIRE_TIMEOUT)))
172 {
173
174
175
176
177
178 if(buffer == NULL) {
179
180 n = HASHBIN_GET_SIZE(log);
181 buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
182 if (buffer == NULL) {
183 spin_unlock_irqrestore(&log->hb_spinlock, flags);
184 return;
185 }
186
187 }
188
189
190 memcpy(&(buffer[i]), &(curr->data),
191 sizeof(discinfo_t));
192 i++;
193
194
195 curr = hashbin_remove_this(log, (irda_queue_t *) curr);
196 kfree(curr);
197 }
198 }
199
200
201
202
203
204 spin_unlock_irqrestore(&log->hb_spinlock, flags);
205
206 if(buffer == NULL)
207 return;
208
209
210 irlmp_discovery_expiry(buffer, i);
211
212
213 kfree(buffer);
214}
215
216#if 0
217
218
219
220
221
222
223void irlmp_dump_discoveries(hashbin_t *log)
224{
225 discovery_t *discovery;
226
227 IRDA_ASSERT(log != NULL, return;);
228
229 discovery = (discovery_t *) hashbin_get_first(log);
230 while (discovery != NULL) {
231 pr_debug("Discovery:\n");
232 pr_debug(" daddr=%08x\n", discovery->data.daddr);
233 pr_debug(" saddr=%08x\n", discovery->data.saddr);
234 pr_debug(" nickname=%s\n", discovery->data.info);
235
236 discovery = (discovery_t *) hashbin_get_next(log);
237 }
238}
239#endif
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn,
262 __u16 mask, int old_entries)
263{
264 discovery_t * discovery;
265 unsigned long flags;
266 discinfo_t * buffer = NULL;
267 int j_timeout = (sysctl_discovery_timeout * HZ);
268 int n;
269 int i = 0;
270
271 IRDA_ASSERT(pn != NULL, return NULL;);
272 IRDA_ASSERT(log != NULL, return NULL;);
273
274
275 spin_lock_irqsave(&log->hb_spinlock, flags);
276
277 discovery = (discovery_t *) hashbin_get_first(log);
278 while (discovery != NULL) {
279
280
281
282 if ((get_unaligned((__u16 *)discovery->data.hints) & mask) &&
283 ((old_entries) ||
284 ((jiffies - discovery->firststamp) < j_timeout))) {
285
286
287
288
289
290 if(buffer == NULL) {
291
292 n = HASHBIN_GET_SIZE(log);
293 buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC);
294 if (buffer == NULL) {
295 spin_unlock_irqrestore(&log->hb_spinlock, flags);
296 return NULL;
297 }
298
299 }
300
301
302 memcpy(&(buffer[i]), &(discovery->data),
303 sizeof(discinfo_t));
304 i++;
305 }
306 discovery = (discovery_t *) hashbin_get_next(log);
307 }
308
309 spin_unlock_irqrestore(&log->hb_spinlock, flags);
310
311
312 *pn = i;
313 return buffer;
314}
315
316#ifdef CONFIG_PROC_FS
317static inline discovery_t *discovery_seq_idx(loff_t pos)
318
319{
320 discovery_t *discovery;
321
322 for (discovery = (discovery_t *) hashbin_get_first(irlmp->cachelog);
323 discovery != NULL;
324 discovery = (discovery_t *) hashbin_get_next(irlmp->cachelog)) {
325 if (pos-- == 0)
326 break;
327 }
328
329 return discovery;
330}
331
332static void *discovery_seq_start(struct seq_file *seq, loff_t *pos)
333{
334 spin_lock_irq(&irlmp->cachelog->hb_spinlock);
335 return *pos ? discovery_seq_idx(*pos - 1) : SEQ_START_TOKEN;
336}
337
338static void *discovery_seq_next(struct seq_file *seq, void *v, loff_t *pos)
339{
340 ++*pos;
341 return (v == SEQ_START_TOKEN)
342 ? (void *) hashbin_get_first(irlmp->cachelog)
343 : (void *) hashbin_get_next(irlmp->cachelog);
344}
345
346static void discovery_seq_stop(struct seq_file *seq, void *v)
347{
348 spin_unlock_irq(&irlmp->cachelog->hb_spinlock);
349}
350
351static int discovery_seq_show(struct seq_file *seq, void *v)
352{
353 if (v == SEQ_START_TOKEN)
354 seq_puts(seq, "IrLMP: Discovery log:\n\n");
355 else {
356 const discovery_t *discovery = v;
357
358 seq_printf(seq, "nickname: %s, hint: 0x%02x%02x",
359 discovery->data.info,
360 discovery->data.hints[0],
361 discovery->data.hints[1]);
362#if 0
363 if ( discovery->data.hints[0] & HINT_PNP)
364 seq_puts(seq, "PnP Compatible ");
365 if ( discovery->data.hints[0] & HINT_PDA)
366 seq_puts(seq, "PDA/Palmtop ");
367 if ( discovery->data.hints[0] & HINT_COMPUTER)
368 seq_puts(seq, "Computer ");
369 if ( discovery->data.hints[0] & HINT_PRINTER)
370 seq_puts(seq, "Printer ");
371 if ( discovery->data.hints[0] & HINT_MODEM)
372 seq_puts(seq, "Modem ");
373 if ( discovery->data.hints[0] & HINT_FAX)
374 seq_puts(seq, "Fax ");
375 if ( discovery->data.hints[0] & HINT_LAN)
376 seq_puts(seq, "LAN Access ");
377
378 if ( discovery->data.hints[1] & HINT_TELEPHONY)
379 seq_puts(seq, "Telephony ");
380 if ( discovery->data.hints[1] & HINT_FILE_SERVER)
381 seq_puts(seq, "File Server ");
382 if ( discovery->data.hints[1] & HINT_COMM)
383 seq_puts(seq, "IrCOMM ");
384 if ( discovery->data.hints[1] & HINT_OBEX)
385 seq_puts(seq, "IrOBEX ");
386#endif
387 seq_printf(seq,", saddr: 0x%08x, daddr: 0x%08x\n\n",
388 discovery->data.saddr,
389 discovery->data.daddr);
390
391 seq_putc(seq, '\n');
392 }
393 return 0;
394}
395
396static const struct seq_operations discovery_seq_ops = {
397 .start = discovery_seq_start,
398 .next = discovery_seq_next,
399 .stop = discovery_seq_stop,
400 .show = discovery_seq_show,
401};
402
403static int discovery_seq_open(struct inode *inode, struct file *file)
404{
405 IRDA_ASSERT(irlmp != NULL, return -EINVAL;);
406
407 return seq_open(file, &discovery_seq_ops);
408}
409
410const struct file_operations discovery_seq_fops = {
411 .owner = THIS_MODULE,
412 .open = discovery_seq_open,
413 .read = seq_read,
414 .llseek = seq_lseek,
415 .release = seq_release,
416};
417#endif
418