Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/irda/irlan/irlan_client.c
17548 views
1
/*********************************************************************
2
*
3
* Filename: irlan_client.c
4
* Version: 0.9
5
* Description: IrDA LAN Access Protocol (IrLAN) Client
6
* Status: Experimental.
7
* Author: Dag Brattli <[email protected]>
8
* Created at: Sun Aug 31 20:14:37 1997
9
* Modified at: Tue Dec 14 15:47:02 1999
10
* Modified by: Dag Brattli <[email protected]>
11
* Sources: skeleton.c by Donald Becker <[email protected]>
12
* slip.c by Laurence Culhane, <[email protected]>
13
* Fred N. van Kempen, <[email protected]>
14
*
15
* Copyright (c) 1998-1999 Dag Brattli <[email protected]>,
16
* All Rights Reserved.
17
*
18
* This program is free software; you can redistribute it and/or
19
* modify it under the terms of the GNU General Public License as
20
* published by the Free Software Foundation; either version 2 of
21
* the License, or (at your option) any later version.
22
*
23
* Neither Dag Brattli nor University of Tromsø admit liability nor
24
* provide warranty for any of this software. This material is
25
* provided "AS-IS" and at no charge.
26
*
27
********************************************************************/
28
29
#include <linux/kernel.h>
30
#include <linux/string.h>
31
#include <linux/slab.h>
32
#include <linux/errno.h>
33
#include <linux/init.h>
34
#include <linux/netdevice.h>
35
#include <linux/etherdevice.h>
36
#include <linux/if_arp.h>
37
#include <linux/bitops.h>
38
#include <net/arp.h>
39
40
#include <asm/system.h>
41
#include <asm/byteorder.h>
42
43
#include <net/irda/irda.h>
44
#include <net/irda/irttp.h>
45
#include <net/irda/irlmp.h>
46
#include <net/irda/irias_object.h>
47
#include <net/irda/iriap.h>
48
#include <net/irda/timer.h>
49
50
#include <net/irda/irlan_common.h>
51
#include <net/irda/irlan_event.h>
52
#include <net/irda/irlan_eth.h>
53
#include <net/irda/irlan_provider.h>
54
#include <net/irda/irlan_client.h>
55
56
#undef CONFIG_IRLAN_GRATUITOUS_ARP
57
58
static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
59
LM_REASON reason,
60
struct sk_buff *);
61
static int irlan_client_ctrl_data_indication(void *instance, void *sap,
62
struct sk_buff *skb);
63
static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
64
struct qos_info *qos,
65
__u32 max_sdu_size,
66
__u8 max_header_size,
67
struct sk_buff *);
68
static void irlan_check_response_param(struct irlan_cb *self, char *param,
69
char *value, int val_len);
70
static void irlan_client_open_ctrl_tsap(struct irlan_cb *self);
71
72
static void irlan_client_kick_timer_expired(void *data)
73
{
74
struct irlan_cb *self = (struct irlan_cb *) data;
75
76
IRDA_DEBUG(2, "%s()\n", __func__ );
77
78
IRDA_ASSERT(self != NULL, return;);
79
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
80
81
/*
82
* If we are in peer mode, the client may not have got the discovery
83
* indication it needs to make progress. If the client is still in
84
* IDLE state, we must kick it to, but only if the provider is not IDLE
85
*/
86
if ((self->provider.access_type == ACCESS_PEER) &&
87
(self->client.state == IRLAN_IDLE) &&
88
(self->provider.state != IRLAN_IDLE)) {
89
irlan_client_wakeup(self, self->saddr, self->daddr);
90
}
91
}
92
93
static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
94
{
95
IRDA_DEBUG(4, "%s()\n", __func__ );
96
97
irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
98
irlan_client_kick_timer_expired);
99
}
100
101
/*
102
* Function irlan_client_wakeup (self, saddr, daddr)
103
*
104
* Wake up client
105
*
106
*/
107
void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
108
{
109
IRDA_DEBUG(1, "%s()\n", __func__ );
110
111
IRDA_ASSERT(self != NULL, return;);
112
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
113
114
/*
115
* Check if we are already awake, or if we are a provider in direct
116
* mode (in that case we must leave the client idle
117
*/
118
if ((self->client.state != IRLAN_IDLE) ||
119
(self->provider.access_type == ACCESS_DIRECT))
120
{
121
IRDA_DEBUG(0, "%s(), already awake!\n", __func__ );
122
return;
123
}
124
125
/* Addresses may have changed! */
126
self->saddr = saddr;
127
self->daddr = daddr;
128
129
if (self->disconnect_reason == LM_USER_REQUEST) {
130
IRDA_DEBUG(0, "%s(), still stopped by user\n", __func__ );
131
return;
132
}
133
134
/* Open TSAPs */
135
irlan_client_open_ctrl_tsap(self);
136
irlan_open_data_tsap(self);
137
138
irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);
139
140
/* Start kick timer */
141
irlan_client_start_kick_timer(self, 2*HZ);
142
}
143
144
/*
145
* Function irlan_discovery_indication (daddr)
146
*
147
* Remote device with IrLAN server support discovered
148
*
149
*/
150
void irlan_client_discovery_indication(discinfo_t *discovery,
151
DISCOVERY_MODE mode,
152
void *priv)
153
{
154
struct irlan_cb *self;
155
__u32 saddr, daddr;
156
157
IRDA_DEBUG(1, "%s()\n", __func__ );
158
159
IRDA_ASSERT(discovery != NULL, return;);
160
161
/*
162
* I didn't check it, but I bet that IrLAN suffer from the same
163
* deficiency as IrComm and doesn't handle two instances
164
* simultaneously connecting to each other.
165
* Same workaround, drop passive discoveries.
166
* Jean II */
167
if(mode == DISCOVERY_PASSIVE)
168
return;
169
170
saddr = discovery->saddr;
171
daddr = discovery->daddr;
172
173
/* Find instance */
174
rcu_read_lock();
175
self = irlan_get_any();
176
if (self) {
177
IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);
178
179
IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __func__ ,
180
daddr);
181
182
irlan_client_wakeup(self, saddr, daddr);
183
}
184
IRDA_ASSERT_LABEL(out:)
185
rcu_read_unlock();
186
}
187
188
/*
189
* Function irlan_client_data_indication (handle, skb)
190
*
191
* This function gets the data that is received on the control channel
192
*
193
*/
194
static int irlan_client_ctrl_data_indication(void *instance, void *sap,
195
struct sk_buff *skb)
196
{
197
struct irlan_cb *self;
198
199
IRDA_DEBUG(2, "%s()\n", __func__ );
200
201
self = (struct irlan_cb *) instance;
202
203
IRDA_ASSERT(self != NULL, return -1;);
204
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
205
IRDA_ASSERT(skb != NULL, return -1;);
206
207
irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
208
209
/* Ready for a new command */
210
IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __func__ );
211
self->client.tx_busy = FALSE;
212
213
/* Check if we have some queued commands waiting to be sent */
214
irlan_run_ctrl_tx_queue(self);
215
216
return 0;
217
}
218
219
static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
220
LM_REASON reason,
221
struct sk_buff *userdata)
222
{
223
struct irlan_cb *self;
224
struct tsap_cb *tsap;
225
struct sk_buff *skb;
226
227
IRDA_DEBUG(4, "%s(), reason=%d\n", __func__ , reason);
228
229
self = (struct irlan_cb *) instance;
230
tsap = (struct tsap_cb *) sap;
231
232
IRDA_ASSERT(self != NULL, return;);
233
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
234
IRDA_ASSERT(tsap != NULL, return;);
235
IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
236
237
IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;);
238
239
/* Remove frames queued on the control channel */
240
while ((skb = skb_dequeue(&self->client.txq)) != NULL) {
241
dev_kfree_skb(skb);
242
}
243
self->client.tx_busy = FALSE;
244
245
irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
246
}
247
248
/*
249
* Function irlan_client_open_tsaps (self)
250
*
251
* Initialize callbacks and open IrTTP TSAPs
252
*
253
*/
254
static void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
255
{
256
struct tsap_cb *tsap;
257
notify_t notify;
258
259
IRDA_DEBUG(4, "%s()\n", __func__ );
260
261
IRDA_ASSERT(self != NULL, return;);
262
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
263
264
/* Check if already open */
265
if (self->client.tsap_ctrl)
266
return;
267
268
irda_notify_init(&notify);
269
270
/* Set up callbacks */
271
notify.data_indication = irlan_client_ctrl_data_indication;
272
notify.connect_confirm = irlan_client_ctrl_connect_confirm;
273
notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
274
notify.instance = self;
275
strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name));
276
277
tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
278
if (!tsap) {
279
IRDA_DEBUG(2, "%s(), Got no tsap!\n", __func__ );
280
return;
281
}
282
self->client.tsap_ctrl = tsap;
283
}
284
285
/*
286
* Function irlan_client_connect_confirm (handle, skb)
287
*
288
* Connection to peer IrLAN laye confirmed
289
*
290
*/
291
static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
292
struct qos_info *qos,
293
__u32 max_sdu_size,
294
__u8 max_header_size,
295
struct sk_buff *skb)
296
{
297
struct irlan_cb *self;
298
299
IRDA_DEBUG(4, "%s()\n", __func__ );
300
301
self = (struct irlan_cb *) instance;
302
303
IRDA_ASSERT(self != NULL, return;);
304
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
305
306
self->client.max_sdu_size = max_sdu_size;
307
self->client.max_header_size = max_header_size;
308
309
/* TODO: we could set the MTU depending on the max_sdu_size */
310
311
irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
312
}
313
314
/*
315
* Function print_ret_code (code)
316
*
317
* Print return code of request to peer IrLAN layer.
318
*
319
*/
320
static void print_ret_code(__u8 code)
321
{
322
switch(code) {
323
case 0:
324
printk(KERN_INFO "Success\n");
325
break;
326
case 1:
327
IRDA_WARNING("IrLAN: Insufficient resources\n");
328
break;
329
case 2:
330
IRDA_WARNING("IrLAN: Invalid command format\n");
331
break;
332
case 3:
333
IRDA_WARNING("IrLAN: Command not supported\n");
334
break;
335
case 4:
336
IRDA_WARNING("IrLAN: Parameter not supported\n");
337
break;
338
case 5:
339
IRDA_WARNING("IrLAN: Value not supported\n");
340
break;
341
case 6:
342
IRDA_WARNING("IrLAN: Not open\n");
343
break;
344
case 7:
345
IRDA_WARNING("IrLAN: Authentication required\n");
346
break;
347
case 8:
348
IRDA_WARNING("IrLAN: Invalid password\n");
349
break;
350
case 9:
351
IRDA_WARNING("IrLAN: Protocol error\n");
352
break;
353
case 255:
354
IRDA_WARNING("IrLAN: Asynchronous status\n");
355
break;
356
}
357
}
358
359
/*
360
* Function irlan_client_parse_response (self, skb)
361
*
362
* Extract all parameters from received buffer, then feed them to
363
* check_params for parsing
364
*/
365
void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
366
{
367
__u8 *frame;
368
__u8 *ptr;
369
int count;
370
int ret;
371
__u16 val_len;
372
int i;
373
char *name;
374
char *value;
375
376
IRDA_ASSERT(skb != NULL, return;);
377
378
IRDA_DEBUG(4, "%s() skb->len=%d\n", __func__ , (int) skb->len);
379
380
IRDA_ASSERT(self != NULL, return;);
381
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
382
383
if (!skb) {
384
IRDA_ERROR("%s(), Got NULL skb!\n", __func__);
385
return;
386
}
387
frame = skb->data;
388
389
/*
390
* Check return code and print it if not success
391
*/
392
if (frame[0]) {
393
print_ret_code(frame[0]);
394
return;
395
}
396
397
name = kmalloc(255, GFP_ATOMIC);
398
if (!name)
399
return;
400
value = kmalloc(1016, GFP_ATOMIC);
401
if (!value) {
402
kfree(name);
403
return;
404
}
405
406
/* How many parameters? */
407
count = frame[1];
408
409
IRDA_DEBUG(4, "%s(), got %d parameters\n", __func__ , count);
410
411
ptr = frame+2;
412
413
/* For all parameters */
414
for (i=0; i<count;i++) {
415
ret = irlan_extract_param(ptr, name, value, &val_len);
416
if (ret < 0) {
417
IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __func__ );
418
break;
419
}
420
ptr += ret;
421
irlan_check_response_param(self, name, value, val_len);
422
}
423
/* Cleanup */
424
kfree(name);
425
kfree(value);
426
}
427
428
/*
429
* Function irlan_check_response_param (self, param, value, val_len)
430
*
431
* Check which parameter is received and update local variables
432
*
433
*/
434
static void irlan_check_response_param(struct irlan_cb *self, char *param,
435
char *value, int val_len)
436
{
437
__u16 tmp_cpu; /* Temporary value in host order */
438
__u8 *bytes;
439
int i;
440
441
IRDA_DEBUG(4, "%s(), parm=%s\n", __func__ , param);
442
443
IRDA_ASSERT(self != NULL, return;);
444
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
445
446
/* Media type */
447
if (strcmp(param, "MEDIA") == 0) {
448
if (strcmp(value, "802.3") == 0)
449
self->media = MEDIA_802_3;
450
else
451
self->media = MEDIA_802_5;
452
return;
453
}
454
if (strcmp(param, "FILTER_TYPE") == 0) {
455
if (strcmp(value, "DIRECTED") == 0)
456
self->client.filter_type |= IRLAN_DIRECTED;
457
else if (strcmp(value, "FUNCTIONAL") == 0)
458
self->client.filter_type |= IRLAN_FUNCTIONAL;
459
else if (strcmp(value, "GROUP") == 0)
460
self->client.filter_type |= IRLAN_GROUP;
461
else if (strcmp(value, "MAC_FRAME") == 0)
462
self->client.filter_type |= IRLAN_MAC_FRAME;
463
else if (strcmp(value, "MULTICAST") == 0)
464
self->client.filter_type |= IRLAN_MULTICAST;
465
else if (strcmp(value, "BROADCAST") == 0)
466
self->client.filter_type |= IRLAN_BROADCAST;
467
else if (strcmp(value, "IPX_SOCKET") == 0)
468
self->client.filter_type |= IRLAN_IPX_SOCKET;
469
470
}
471
if (strcmp(param, "ACCESS_TYPE") == 0) {
472
if (strcmp(value, "DIRECT") == 0)
473
self->client.access_type = ACCESS_DIRECT;
474
else if (strcmp(value, "PEER") == 0)
475
self->client.access_type = ACCESS_PEER;
476
else if (strcmp(value, "HOSTED") == 0)
477
self->client.access_type = ACCESS_HOSTED;
478
else {
479
IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
480
}
481
}
482
/* IRLAN version */
483
if (strcmp(param, "IRLAN_VER") == 0) {
484
IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0],
485
(__u8) value[1]);
486
487
self->version[0] = value[0];
488
self->version[1] = value[1];
489
return;
490
}
491
/* Which remote TSAP to use for data channel */
492
if (strcmp(param, "DATA_CHAN") == 0) {
493
self->dtsap_sel_data = value[0];
494
IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
495
return;
496
}
497
if (strcmp(param, "CON_ARB") == 0) {
498
memcpy(&tmp_cpu, value, 2); /* Align value */
499
le16_to_cpus(&tmp_cpu); /* Convert to host order */
500
self->client.recv_arb_val = tmp_cpu;
501
IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __func__ ,
502
self->client.recv_arb_val);
503
}
504
if (strcmp(param, "MAX_FRAME") == 0) {
505
memcpy(&tmp_cpu, value, 2); /* Align value */
506
le16_to_cpus(&tmp_cpu); /* Convert to host order */
507
self->client.max_frame = tmp_cpu;
508
IRDA_DEBUG(4, "%s(), max frame=%d\n", __func__ ,
509
self->client.max_frame);
510
}
511
512
/* RECONNECT_KEY, in case the link goes down! */
513
if (strcmp(param, "RECONNECT_KEY") == 0) {
514
IRDA_DEBUG(4, "Got reconnect key: ");
515
/* for (i = 0; i < val_len; i++) */
516
/* printk("%02x", value[i]); */
517
memcpy(self->client.reconnect_key, value, val_len);
518
self->client.key_len = val_len;
519
IRDA_DEBUG(4, "\n");
520
}
521
/* FILTER_ENTRY, have we got an ethernet address? */
522
if (strcmp(param, "FILTER_ENTRY") == 0) {
523
bytes = value;
524
IRDA_DEBUG(4, "Ethernet address = %pM\n", bytes);
525
for (i = 0; i < 6; i++)
526
self->dev->dev_addr[i] = bytes[i];
527
}
528
}
529
530
/*
531
* Function irlan_client_get_value_confirm (obj_id, value)
532
*
533
* Got results from remote LM-IAS
534
*
535
*/
536
void irlan_client_get_value_confirm(int result, __u16 obj_id,
537
struct ias_value *value, void *priv)
538
{
539
struct irlan_cb *self;
540
541
IRDA_DEBUG(4, "%s()\n", __func__ );
542
543
IRDA_ASSERT(priv != NULL, return;);
544
545
self = (struct irlan_cb *) priv;
546
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
547
548
/* We probably don't need to make any more queries */
549
iriap_close(self->client.iriap);
550
self->client.iriap = NULL;
551
552
/* Check if request succeeded */
553
if (result != IAS_SUCCESS) {
554
IRDA_DEBUG(2, "%s(), got NULL value!\n", __func__ );
555
irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
556
NULL);
557
return;
558
}
559
560
switch (value->type) {
561
case IAS_INTEGER:
562
self->dtsap_sel_ctrl = value->t.integer;
563
564
if (value->t.integer != -1) {
565
irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
566
NULL);
567
return;
568
}
569
irias_delete_value(value);
570
break;
571
default:
572
IRDA_DEBUG(2, "%s(), unknown type!\n", __func__ );
573
break;
574
}
575
irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
576
}
577
578