1 /*********************************************************************
3 * Filename: irlan_client.c
5 * Description: IrDA LAN Access Protocol (IrLAN) Client
6 * Status: Experimental.
7 * Author: Dag Brattli <dagb@cs.uit.no>
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 <dagb@cs.uit.no>
11 * Sources: skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
12 * slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
13 * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
15 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
16 * All Rights Reserved.
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.
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.
27 ********************************************************************/
29 #include <linux/kernel.h>
30 #include <linux/string.h>
31 #include <linux/errno.h>
32 #include <linux/init.h>
33 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
35 #include <linux/if_arp.h>
38 #include <asm/system.h>
39 #include <asm/bitops.h>
40 #include <asm/byteorder.h>
42 #include <net/irda/irda.h>
43 #include <net/irda/irttp.h>
44 #include <net/irda/irlmp.h>
45 #include <net/irda/irias_object.h>
46 #include <net/irda/iriap.h>
47 #include <net/irda/timer.h>
49 #include <net/irda/irlan_common.h>
50 #include <net/irda/irlan_event.h>
51 #include <net/irda/irlan_eth.h>
52 #include <net/irda/irlan_provider.h>
53 #include <net/irda/irlan_client.h>
55 #undef CONFIG_IRLAN_GRATUITOUS_ARP
57 static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
60 static int irlan_client_ctrl_data_indication(void *instance, void *sap,
62 static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
67 static void irlan_check_response_param(struct irlan_cb *self, char *param,
68 char *value, int val_len);
70 static void irlan_client_kick_timer_expired(void *data)
72 struct irlan_cb *self = (struct irlan_cb *) data;
74 IRDA_DEBUG(2, __FUNCTION__ "()\n");
76 ASSERT(self != NULL, return;);
77 ASSERT(self->magic == IRLAN_MAGIC, return;);
80 * If we are in peer mode, the client may not have got the discovery
81 * indication it needs to make progress. If the client is still in
82 * IDLE state, we must kick it to, but only if the provider is not IDLE
84 if ((self->provider.access_type == ACCESS_PEER) &&
85 (self->client.state == IRLAN_IDLE) &&
86 (self->provider.state != IRLAN_IDLE)) {
87 irlan_client_wakeup(self, self->saddr, self->daddr);
91 void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
93 IRDA_DEBUG(4, __FUNCTION__ "()\n");
95 irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
96 irlan_client_kick_timer_expired);
100 * Function irlan_client_wakeup (self, saddr, daddr)
105 void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
107 IRDA_DEBUG(1, __FUNCTION__ "()\n");
109 ASSERT(self != NULL, return;);
110 ASSERT(self->magic == IRLAN_MAGIC, return;);
113 * Check if we are already awake, or if we are a provider in direct
114 * mode (in that case we must leave the client idle
116 if ((self->client.state != IRLAN_IDLE) ||
117 (self->provider.access_type == ACCESS_DIRECT))
119 IRDA_DEBUG(0, __FUNCTION__ "(), already awake!\n");
123 /* Addresses may have changed! */
127 if (self->disconnect_reason == LM_USER_REQUEST) {
128 IRDA_DEBUG(0, __FUNCTION__ "(), still stopped by user\n");
133 irlan_client_open_ctrl_tsap(self);
134 irlan_open_data_tsap(self);
136 irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);
138 /* Start kick timer */
139 irlan_client_start_kick_timer(self, 2*HZ);
143 * Function irlan_discovery_indication (daddr)
145 * Remote device with IrLAN server support discovered
148 void irlan_client_discovery_indication(discovery_t *discovery,
152 struct irlan_cb *self;
155 IRDA_DEBUG(1, __FUNCTION__"()\n");
157 ASSERT(irlan != NULL, return;);
158 ASSERT(discovery != NULL, return;);
161 * I didn't check it, but I bet that IrLAN suffer from the same
162 * deficiency as IrComm and doesn't handle two instances
163 * simultaneously connecting to each other.
164 * Same workaround, drop passive discoveries.
166 if(mode == DISCOVERY_PASSIVE)
169 saddr = discovery->saddr;
170 daddr = discovery->daddr;
173 self = (struct irlan_cb *) hashbin_get_first(irlan);
175 ASSERT(self->magic == IRLAN_MAGIC, return;);
177 IRDA_DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n",
180 irlan_client_wakeup(self, saddr, daddr);
185 * Function irlan_client_data_indication (handle, skb)
187 * This function gets the data that is received on the control channel
190 static int irlan_client_ctrl_data_indication(void *instance, void *sap,
193 struct irlan_cb *self;
195 IRDA_DEBUG(2, __FUNCTION__ "()\n");
197 self = (struct irlan_cb *) instance;
199 ASSERT(self != NULL, return -1;);
200 ASSERT(self->magic == IRLAN_MAGIC, return -1;);
201 ASSERT(skb != NULL, return -1;);
203 irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
205 /* Ready for a new command */
206 IRDA_DEBUG(2, __FUNCTION__ "(), clearing tx_busy\n");
207 self->client.tx_busy = FALSE;
209 /* Check if we have some queued commands waiting to be sent */
210 irlan_run_ctrl_tx_queue(self);
215 static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
217 struct sk_buff *userdata)
219 struct irlan_cb *self;
220 struct tsap_cb *tsap;
223 IRDA_DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
225 self = (struct irlan_cb *) instance;
226 tsap = (struct tsap_cb *) sap;
228 ASSERT(self != NULL, return;);
229 ASSERT(self->magic == IRLAN_MAGIC, return;);
230 ASSERT(tsap != NULL, return;);
231 ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
233 ASSERT(tsap == self->client.tsap_ctrl, return;);
235 /* Remove frames queued on the control channel */
236 while ((skb = skb_dequeue(&self->client.txq))) {
239 self->client.tx_busy = FALSE;
241 irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
245 * Function irlan_client_open_tsaps (self)
247 * Initialize callbacks and open IrTTP TSAPs
250 void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
252 struct tsap_cb *tsap;
255 IRDA_DEBUG(4, __FUNCTION__ "()\n");
257 ASSERT(self != NULL, return;);
258 ASSERT(self->magic == IRLAN_MAGIC, return;);
260 /* Check if already open */
261 if (self->client.tsap_ctrl)
264 irda_notify_init(¬ify);
266 /* Set up callbacks */
267 notify.data_indication = irlan_client_ctrl_data_indication;
268 notify.connect_confirm = irlan_client_ctrl_connect_confirm;
269 notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
270 notify.instance = self;
271 strncpy(notify.name, "IrLAN ctrl (c)", NOTIFY_MAX_NAME);
273 tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify);
275 IRDA_DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
278 self->client.tsap_ctrl = tsap;
282 * Function irlan_client_connect_confirm (handle, skb)
284 * Connection to peer IrLAN laye confirmed
287 static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
288 struct qos_info *qos,
290 __u8 max_header_size,
293 struct irlan_cb *self;
295 IRDA_DEBUG(4, __FUNCTION__ "()\n");
297 self = (struct irlan_cb *) instance;
299 ASSERT(self != NULL, return;);
300 ASSERT(self->magic == IRLAN_MAGIC, return;);
302 self->client.max_sdu_size = max_sdu_size;
303 self->client.max_header_size = max_header_size;
305 /* TODO: we could set the MTU depending on the max_sdu_size */
307 irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
311 * Function irlan_client_reconnect_data_channel (self)
313 * Try to reconnect data channel (currently not used)
316 void irlan_client_reconnect_data_channel(struct irlan_cb *self)
321 IRDA_DEBUG(4, __FUNCTION__ "()\n");
323 ASSERT(self != NULL, return;);
324 ASSERT(self->magic == IRLAN_MAGIC, return;);
326 skb = dev_alloc_skb(128);
330 /* Reserve space for TTP, LMP, and LAP header */
331 skb_reserve(skb, self->max_header_size);
336 frame[0] = CMD_RECONNECT_DATA_CHAN;
338 irlan_insert_array_param(skb, "RECONNECT_KEY",
339 self->client.reconnect_key,
340 self->client.key_len);
342 irttp_data_request(self->client.tsap_ctrl, skb);
346 * Function irlan_client_parse_response (self, skb)
348 * Extract all parameters from received buffer, then feed them to
349 * check_params for parsing
351 void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
362 ASSERT(skb != NULL, return;);
364 IRDA_DEBUG(4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
366 ASSERT(self != NULL, return;);
367 ASSERT(self->magic == IRLAN_MAGIC, return;);
370 ERROR( __FUNCTION__ "(), Got NULL skb!\n");
376 * Check return code and print it if not success
379 print_ret_code(frame[0]);
383 name = kmalloc(255, GFP_ATOMIC);
386 value = kmalloc(1016, GFP_ATOMIC);
392 /* How many parameters? */
395 IRDA_DEBUG(4, __FUNCTION__ "(), got %d parameters\n", count);
399 /* For all parameters */
400 for (i=0; i<count;i++) {
401 ret = irlan_extract_param(ptr, name, value, &val_len);
403 IRDA_DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
407 irlan_check_response_param(self, name, value, val_len);
415 * Function irlan_check_response_param (self, param, value, val_len)
417 * Check which parameter is received and update local variables
420 static void irlan_check_response_param(struct irlan_cb *self, char *param,
421 char *value, int val_len)
423 __u16 tmp_cpu; /* Temporary value in host order */
427 IRDA_DEBUG(4, __FUNCTION__ "(), parm=%s\n", param);
429 ASSERT(self != NULL, return;);
430 ASSERT(self->magic == IRLAN_MAGIC, return;);
433 if (strcmp(param, "MEDIA") == 0) {
434 if (strcmp(value, "802.3") == 0)
435 self->media = MEDIA_802_3;
437 self->media = MEDIA_802_5;
440 if (strcmp(param, "FILTER_TYPE") == 0) {
441 if (strcmp(value, "DIRECTED") == 0)
442 self->client.filter_type |= IRLAN_DIRECTED;
443 else if (strcmp(value, "FUNCTIONAL") == 0)
444 self->client.filter_type |= IRLAN_FUNCTIONAL;
445 else if (strcmp(value, "GROUP") == 0)
446 self->client.filter_type |= IRLAN_GROUP;
447 else if (strcmp(value, "MAC_FRAME") == 0)
448 self->client.filter_type |= IRLAN_MAC_FRAME;
449 else if (strcmp(value, "MULTICAST") == 0)
450 self->client.filter_type |= IRLAN_MULTICAST;
451 else if (strcmp(value, "BROADCAST") == 0)
452 self->client.filter_type |= IRLAN_BROADCAST;
453 else if (strcmp(value, "IPX_SOCKET") == 0)
454 self->client.filter_type |= IRLAN_IPX_SOCKET;
457 if (strcmp(param, "ACCESS_TYPE") == 0) {
458 if (strcmp(value, "DIRECT") == 0)
459 self->client.access_type = ACCESS_DIRECT;
460 else if (strcmp(value, "PEER") == 0)
461 self->client.access_type = ACCESS_PEER;
462 else if (strcmp(value, "HOSTED") == 0)
463 self->client.access_type = ACCESS_HOSTED;
465 IRDA_DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
469 if (strcmp(param, "IRLAN_VER") == 0) {
470 IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0],
473 self->version[0] = value[0];
474 self->version[1] = value[1];
477 /* Which remote TSAP to use for data channel */
478 if (strcmp(param, "DATA_CHAN") == 0) {
479 self->dtsap_sel_data = value[0];
480 IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
483 if (strcmp(param, "CON_ARB") == 0) {
484 memcpy(&tmp_cpu, value, 2); /* Align value */
485 le16_to_cpus(&tmp_cpu); /* Convert to host order */
486 self->client.recv_arb_val = tmp_cpu;
487 IRDA_DEBUG(2, __FUNCTION__ "(), receive arb val=%d\n",
488 self->client.recv_arb_val);
490 if (strcmp(param, "MAX_FRAME") == 0) {
491 memcpy(&tmp_cpu, value, 2); /* Align value */
492 le16_to_cpus(&tmp_cpu); /* Convert to host order */
493 self->client.max_frame = tmp_cpu;
494 IRDA_DEBUG(4, __FUNCTION__ "(), max frame=%d\n",
495 self->client.max_frame);
498 /* RECONNECT_KEY, in case the link goes down! */
499 if (strcmp(param, "RECONNECT_KEY") == 0) {
500 IRDA_DEBUG(4, "Got reconnect key: ");
501 /* for (i = 0; i < val_len; i++) */
502 /* printk("%02x", value[i]); */
503 memcpy(self->client.reconnect_key, value, val_len);
504 self->client.key_len = val_len;
507 /* FILTER_ENTRY, have we got an ethernet address? */
508 if (strcmp(param, "FILTER_ENTRY") == 0) {
510 IRDA_DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
511 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
513 for (i = 0; i < 6; i++)
514 self->dev.dev_addr[i] = bytes[i];
519 * Function irlan_client_get_value_confirm (obj_id, value)
521 * Got results from remote LM-IAS
524 void irlan_client_get_value_confirm(int result, __u16 obj_id,
525 struct ias_value *value, void *priv)
527 struct irlan_cb *self;
529 IRDA_DEBUG(4, __FUNCTION__ "()\n");
531 ASSERT(priv != NULL, return;);
533 self = (struct irlan_cb *) priv;
534 ASSERT(self->magic == IRLAN_MAGIC, return;);
536 /* We probably don't need to make any more queries */
537 iriap_close(self->client.iriap);
538 self->client.iriap = NULL;
540 /* Check if request succeeded */
541 if (result != IAS_SUCCESS) {
542 IRDA_DEBUG(2, __FUNCTION__ "(), got NULL value!\n");
543 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
548 switch (value->type) {
550 self->dtsap_sel_ctrl = value->t.integer;
552 if (value->t.integer != -1) {
553 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
557 irias_delete_value(value);
560 IRDA_DEBUG(2, __FUNCTION__ "(), unknown type!\n");
563 irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);