Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iriap.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Filename: iriap.c
4  * Version: 0.8
5  * Description: Information Access Protocol (IAP)
6  * Status: Experimental.
7  * Author: Dag Brattli <[email protected]>
8  * Created at: Thu Aug 21 00:02:07 1997
9  * Modified at: Sat Dec 25 16:42:42 1999
10  * Modified by: Dag Brattli <[email protected]>
11  *
12  * Copyright (c) 1998-1999 Dag Brattli <[email protected]>,
13  * All Rights Reserved.
14  * Copyright (c) 2000-2003 Jean Tourrilhes <[email protected]>
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License as
18  * published by the Free Software Foundation; either version 2 of
19  * the License, or (at your option) any later version.
20  *
21  * Neither Dag Brattli nor University of Tromsø admit liability nor
22  * provide warranty for any of this software. This material is
23  * provided "AS-IS" and at no charge.
24  *
25  ********************************************************************/
26 
27 #include <linux/module.h>
28 #include <linux/types.h>
29 #include <linux/skbuff.h>
30 #include <linux/fs.h>
31 #include <linux/string.h>
32 #include <linux/init.h>
33 #include <linux/seq_file.h>
34 #include <linux/slab.h>
35 
36 #include <asm/byteorder.h>
37 #include <asm/unaligned.h>
38 
39 #include <net/irda/irda.h>
40 #include <net/irda/irttp.h>
41 #include <net/irda/irlmp.h>
42 #include <net/irda/irias_object.h>
43 #include <net/irda/iriap_event.h>
44 #include <net/irda/iriap.h>
45 
46 #ifdef CONFIG_IRDA_DEBUG
47 /* FIXME: This one should go in irlmp.c */
48 static const char *const ias_charset_types[] = {
49  "CS_ASCII",
50  "CS_ISO_8859_1",
51  "CS_ISO_8859_2",
52  "CS_ISO_8859_3",
53  "CS_ISO_8859_4",
54  "CS_ISO_8859_5",
55  "CS_ISO_8859_6",
56  "CS_ISO_8859_7",
57  "CS_ISO_8859_8",
58  "CS_ISO_8859_9",
59  "CS_UNICODE"
60 };
61 #endif /* CONFIG_IRDA_DEBUG */
62 
63 static hashbin_t *iriap = NULL;
64 static void *service_handle;
65 
66 static void __iriap_close(struct iriap_cb *self);
67 static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
68 static void iriap_disconnect_indication(void *instance, void *sap,
69  LM_REASON reason, struct sk_buff *skb);
70 static void iriap_connect_indication(void *instance, void *sap,
71  struct qos_info *qos, __u32 max_sdu_size,
72  __u8 max_header_size,
73  struct sk_buff *skb);
74 static void iriap_connect_confirm(void *instance, void *sap,
75  struct qos_info *qos,
76  __u32 max_sdu_size, __u8 max_header_size,
77  struct sk_buff *skb);
78 static int iriap_data_indication(void *instance, void *sap,
79  struct sk_buff *skb);
80 
81 static void iriap_watchdog_timer_expired(void *data);
82 
83 static inline void iriap_start_watchdog_timer(struct iriap_cb *self,
84  int timeout)
85 {
86  irda_start_timer(&self->watchdog_timer, timeout, self,
87  iriap_watchdog_timer_expired);
88 }
89 
90 static struct lock_class_key irias_objects_key;
91 
92 /*
93  * Function iriap_init (void)
94  *
95  * Initializes the IrIAP layer, called by the module initialization code
96  * in irmod.c
97  */
98 int __init iriap_init(void)
99 {
100  struct ias_object *obj;
101  struct iriap_cb *server;
102  __u8 oct_seq[6];
103  __u16 hints;
104 
105  /* Allocate master array */
106  iriap = hashbin_new(HB_LOCK);
107  if (!iriap)
108  return -ENOMEM;
109 
110  /* Object repository - defined in irias_object.c */
112  if (!irias_objects) {
113  IRDA_WARNING("%s: Can't allocate irias_objects hashbin!\n",
114  __func__);
115  hashbin_delete(iriap, NULL);
116  return -ENOMEM;
117  }
118 
120  "irias_objects");
121 
122  /*
123  * Register some default services for IrLMP
124  */
126  service_handle = irlmp_register_service(hints);
127 
128  /* Register the Device object with LM-IAS */
129  obj = irias_new_object("Device", IAS_DEVICE_ID);
130  irias_add_string_attrib(obj, "DeviceName", "Linux", IAS_KERNEL_ATTR);
131 
132  oct_seq[0] = 0x01; /* Version 1 */
133  oct_seq[1] = 0x00; /* IAS support bits */
134  oct_seq[2] = 0x00; /* LM-MUX support bits */
135 #ifdef CONFIG_IRDA_ULTRA
136  oct_seq[2] |= 0x04; /* Connectionless Data support */
137 #endif
138  irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3,
140  irias_insert_object(obj);
141 
142  /*
143  * Register server support with IrLMP so we can accept incoming
144  * connections
145  */
146  server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
147  if (!server) {
148  IRDA_DEBUG(0, "%s(), unable to open server\n", __func__);
149  return -1;
150  }
151  iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
152 
153  return 0;
154 }
155 
156 /*
157  * Function iriap_cleanup (void)
158  *
159  * Initializes the IrIAP layer, called by the module cleanup code in
160  * irmod.c
161  */
162 void iriap_cleanup(void)
163 {
164  irlmp_unregister_service(service_handle);
165 
166  hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
168 }
169 
170 /*
171  * Function iriap_open (void)
172  *
173  * Opens an instance of the IrIAP layer, and registers with IrLMP
174  */
177 {
178  struct iriap_cb *self;
179 
180  IRDA_DEBUG(2, "%s()\n", __func__);
181 
182  self = kzalloc(sizeof(*self), GFP_ATOMIC);
183  if (!self) {
184  IRDA_WARNING("%s: Unable to kmalloc!\n", __func__);
185  return NULL;
186  }
187 
188  /*
189  * Initialize instance
190  */
191 
192  self->magic = IAS_MAGIC;
193  self->mode = mode;
194  if (mode == IAS_CLIENT)
195  iriap_register_lsap(self, slsap_sel, mode);
196 
197  self->confirm = callback;
198  self->priv = priv;
199 
200  /* iriap_getvaluebyclass_request() will construct packets before
201  * we connect, so this must have a sane value... Jean II */
202  self->max_header_size = LMP_MAX_HEADER;
203 
204  init_timer(&self->watchdog_timer);
205 
206  hashbin_insert(iriap, (irda_queue_t *) self, (long) self, NULL);
207 
208  /* Initialize state machines */
213 
214  return self;
215 }
217 
218 /*
219  * Function __iriap_close (self)
220  *
221  * Removes (deallocates) the IrIAP instance
222  *
223  */
224 static void __iriap_close(struct iriap_cb *self)
225 {
226  IRDA_DEBUG(4, "%s()\n", __func__);
227 
228  IRDA_ASSERT(self != NULL, return;);
229  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
230 
231  del_timer(&self->watchdog_timer);
232 
233  if (self->request_skb)
234  dev_kfree_skb(self->request_skb);
235 
236  self->magic = 0;
237 
238  kfree(self);
239 }
240 
241 /*
242  * Function iriap_close (void)
243  *
244  * Closes IrIAP and deregisters with IrLMP
245  */
246 void iriap_close(struct iriap_cb *self)
247 {
248  struct iriap_cb *entry;
249 
250  IRDA_DEBUG(2, "%s()\n", __func__);
251 
252  IRDA_ASSERT(self != NULL, return;);
253  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
254 
255  if (self->lsap) {
256  irlmp_close_lsap(self->lsap);
257  self->lsap = NULL;
258  }
259 
260  entry = (struct iriap_cb *) hashbin_remove(iriap, (long) self, NULL);
261  IRDA_ASSERT(entry == self, return;);
262 
263  __iriap_close(self);
264 }
266 
267 static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
268 {
270 
271  IRDA_DEBUG(2, "%s()\n", __func__);
272 
273  irda_notify_init(&notify);
274  notify.connect_confirm = iriap_connect_confirm;
275  notify.connect_indication = iriap_connect_indication;
276  notify.disconnect_indication = iriap_disconnect_indication;
277  notify.data_indication = iriap_data_indication;
278  notify.instance = self;
279  if (mode == IAS_CLIENT)
280  strcpy(notify.name, "IrIAS cli");
281  else
282  strcpy(notify.name, "IrIAS srv");
283 
284  self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
285  if (self->lsap == NULL) {
286  IRDA_ERROR("%s: Unable to allocated LSAP!\n", __func__);
287  return -1;
288  }
289  self->slsap_sel = self->lsap->slsap_sel;
290 
291  return 0;
292 }
293 
294 /*
295  * Function iriap_disconnect_indication (handle, reason)
296  *
297  * Got disconnect, so clean up everything associated with this connection
298  *
299  */
300 static void iriap_disconnect_indication(void *instance, void *sap,
302  struct sk_buff *skb)
303 {
304  struct iriap_cb *self;
305 
306  IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
307 
308  self = instance;
309 
310  IRDA_ASSERT(self != NULL, return;);
311  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
312 
313  IRDA_ASSERT(iriap != NULL, return;);
314 
315  del_timer(&self->watchdog_timer);
316 
317  /* Not needed */
318  if (skb)
319  dev_kfree_skb(skb);
320 
321  if (self->mode == IAS_CLIENT) {
322  IRDA_DEBUG(4, "%s(), disconnect as client\n", __func__);
323 
324 
326  NULL);
327  /*
328  * Inform service user that the request failed by sending
329  * it a NULL value. Warning, the client might close us, so
330  * remember no to use self anymore after calling confirm
331  */
332  if (self->confirm)
333  self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
334  } else {
335  IRDA_DEBUG(4, "%s(), disconnect as server\n", __func__);
337  NULL);
338  iriap_close(self);
339  }
340 }
341 
342 /*
343  * Function iriap_disconnect_request (handle)
344  */
345 static void iriap_disconnect_request(struct iriap_cb *self)
346 {
347  struct sk_buff *tx_skb;
348 
349  IRDA_DEBUG(4, "%s()\n", __func__);
350 
351  IRDA_ASSERT(self != NULL, return;);
352  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
353 
354  tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
355  if (tx_skb == NULL) {
356  IRDA_DEBUG(0,
357  "%s(), Could not allocate an sk_buff of length %d\n",
358  __func__, LMP_MAX_HEADER);
359  return;
360  }
361 
362  /*
363  * Reserve space for MUX control and LAP header
364  */
365  skb_reserve(tx_skb, LMP_MAX_HEADER);
366 
367  irlmp_disconnect_request(self->lsap, tx_skb);
368 }
369 
370 /*
371  * Function iriap_getvaluebyclass (addr, name, attr)
372  *
373  * Retrieve all values from attribute in all objects with given class
374  * name
375  */
378  char *name, char *attr)
379 {
380  struct sk_buff *tx_skb;
381  int name_len, attr_len, skb_len;
382  __u8 *frame;
383 
384  IRDA_ASSERT(self != NULL, return -1;);
385  IRDA_ASSERT(self->magic == IAS_MAGIC, return -1;);
386 
387  /* Client must supply the destination device address */
388  if (!daddr)
389  return -1;
390 
391  self->daddr = daddr;
392  self->saddr = saddr;
393 
394  /*
395  * Save operation, so we know what the later indication is about
396  */
397  self->operation = GET_VALUE_BY_CLASS;
398 
399  /* Give ourselves 10 secs to finish this operation */
400  iriap_start_watchdog_timer(self, 10*HZ);
401 
402  name_len = strlen(name); /* Up to IAS_MAX_CLASSNAME = 60 */
403  attr_len = strlen(attr); /* Up to IAS_MAX_ATTRIBNAME = 60 */
404 
405  skb_len = self->max_header_size+2+name_len+1+attr_len+4;
406  tx_skb = alloc_skb(skb_len, GFP_ATOMIC);
407  if (!tx_skb)
408  return -ENOMEM;
409 
410  /* Reserve space for MUX and LAP header */
411  skb_reserve(tx_skb, self->max_header_size);
412  skb_put(tx_skb, 3+name_len+attr_len);
413  frame = tx_skb->data;
414 
415  /* Build frame */
416  frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
417  frame[1] = name_len; /* Insert length of name */
418  memcpy(frame+2, name, name_len); /* Insert name */
419  frame[2+name_len] = attr_len; /* Insert length of attr */
420  memcpy(frame+3+name_len, attr, attr_len); /* Insert attr */
421 
423 
424  /* Drop reference count - see state_s_disconnect(). */
425  dev_kfree_skb(tx_skb);
426 
427  return 0;
428 }
430 
431 /*
432  * Function iriap_getvaluebyclass_confirm (self, skb)
433  *
434  * Got result from GetValueByClass command. Parse it and return result
435  * to service user.
436  *
437  */
438 static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,
439  struct sk_buff *skb)
440 {
441  struct ias_value *value;
442  int charset;
444  __u32 tmp_cpu32;
445  __u16 obj_id;
446  __u16 len;
447  __u8 type;
448  __u8 *fp;
449  int n;
450 
451  IRDA_ASSERT(self != NULL, return;);
452  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
453  IRDA_ASSERT(skb != NULL, return;);
454 
455  /* Initialize variables */
456  fp = skb->data;
457  n = 2;
458 
459  /* Get length, MSB first */
460  len = get_unaligned_be16(fp + n);
461  n += 2;
462 
463  IRDA_DEBUG(4, "%s(), len=%d\n", __func__, len);
464 
465  /* Get object ID, MSB first */
466  obj_id = get_unaligned_be16(fp + n);
467  n += 2;
468 
469  type = fp[n++];
470  IRDA_DEBUG(4, "%s(), Value type = %d\n", __func__, type);
471 
472  switch (type) {
473  case IAS_INTEGER:
474  memcpy(&tmp_cpu32, fp+n, 4); n += 4;
475  be32_to_cpus(&tmp_cpu32);
476  value = irias_new_integer_value(tmp_cpu32);
477 
478  /* Legal values restricted to 0x01-0x6f, page 15 irttp */
479  IRDA_DEBUG(4, "%s(), lsap=%d\n", __func__, value->t.integer);
480  break;
481  case IAS_STRING:
482  charset = fp[n++];
483 
484  switch (charset) {
485  case CS_ASCII:
486  break;
487 /* case CS_ISO_8859_1: */
488 /* case CS_ISO_8859_2: */
489 /* case CS_ISO_8859_3: */
490 /* case CS_ISO_8859_4: */
491 /* case CS_ISO_8859_5: */
492 /* case CS_ISO_8859_6: */
493 /* case CS_ISO_8859_7: */
494 /* case CS_ISO_8859_8: */
495 /* case CS_ISO_8859_9: */
496 /* case CS_UNICODE: */
497  default:
498  IRDA_DEBUG(0, "%s(), charset %s, not supported\n",
499  __func__, ias_charset_types[charset]);
500 
501  /* Aborting, close connection! */
502  iriap_disconnect_request(self);
503  return;
504  /* break; */
505  }
506  value_len = fp[n++];
507  IRDA_DEBUG(4, "%s(), strlen=%d\n", __func__, value_len);
508 
509  /* Make sure the string is null-terminated */
510  if (n + value_len < skb->len)
511  fp[n + value_len] = 0x00;
512  IRDA_DEBUG(4, "Got string %s\n", fp+n);
513 
514  /* Will truncate to IAS_MAX_STRING bytes */
515  value = irias_new_string_value(fp+n);
516  break;
517  case IAS_OCT_SEQ:
518  value_len = get_unaligned_be16(fp + n);
519  n += 2;
520 
521  /* Will truncate to IAS_MAX_OCTET_STRING bytes */
522  value = irias_new_octseq_value(fp+n, value_len);
523  break;
524  default:
525  value = irias_new_missing_value();
526  break;
527  }
528 
529  /* Finished, close connection! */
530  iriap_disconnect_request(self);
531 
532  /* Warning, the client might close us, so remember no to use self
533  * anymore after calling confirm
534  */
535  if (self->confirm)
536  self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
537  else {
538  IRDA_DEBUG(0, "%s(), missing handler!\n", __func__);
539  irias_delete_value(value);
540  }
541 }
542 
543 /*
544  * Function iriap_getvaluebyclass_response ()
545  *
546  * Send answer back to remote LM-IAS
547  *
548  */
549 static void iriap_getvaluebyclass_response(struct iriap_cb *self,
550  __u16 obj_id,
551  __u8 ret_code,
552  struct ias_value *value)
553 {
554  struct sk_buff *tx_skb;
555  int n;
556  __be32 tmp_be32;
557  __be16 tmp_be16;
558  __u8 *fp;
559 
560  IRDA_DEBUG(4, "%s()\n", __func__);
561 
562  IRDA_ASSERT(self != NULL, return;);
563  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
564  IRDA_ASSERT(value != NULL, return;);
565  IRDA_ASSERT(value->len <= 1024, return;);
566 
567  /* Initialize variables */
568  n = 0;
569 
570  /*
571  * We must adjust the size of the response after the length of the
572  * value. We add 32 bytes because of the 6 bytes for the frame and
573  * max 5 bytes for the value coding.
574  */
575  tx_skb = alloc_skb(value->len + self->max_header_size + 32,
576  GFP_ATOMIC);
577  if (!tx_skb)
578  return;
579 
580  /* Reserve space for MUX and LAP header */
581  skb_reserve(tx_skb, self->max_header_size);
582  skb_put(tx_skb, 6);
583 
584  fp = tx_skb->data;
585 
586  /* Build frame */
587  fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
588  fp[n++] = ret_code;
589 
590  /* Insert list length (MSB first) */
591  tmp_be16 = htons(0x0001);
592  memcpy(fp+n, &tmp_be16, 2); n += 2;
593 
594  /* Insert object identifier ( MSB first) */
595  tmp_be16 = cpu_to_be16(obj_id);
596  memcpy(fp+n, &tmp_be16, 2); n += 2;
597 
598  switch (value->type) {
599  case IAS_STRING:
600  skb_put(tx_skb, 3 + value->len);
601  fp[n++] = value->type;
602  fp[n++] = 0; /* ASCII */
603  fp[n++] = (__u8) value->len;
604  memcpy(fp+n, value->t.string, value->len); n+=value->len;
605  break;
606  case IAS_INTEGER:
607  skb_put(tx_skb, 5);
608  fp[n++] = value->type;
609 
610  tmp_be32 = cpu_to_be32(value->t.integer);
611  memcpy(fp+n, &tmp_be32, 4); n += 4;
612  break;
613  case IAS_OCT_SEQ:
614  skb_put(tx_skb, 3 + value->len);
615  fp[n++] = value->type;
616 
617  tmp_be16 = cpu_to_be16(value->len);
618  memcpy(fp+n, &tmp_be16, 2); n += 2;
619  memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
620  break;
621  case IAS_MISSING:
622  IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __func__);
623  skb_put(tx_skb, 1);
624  fp[n++] = value->type;
625  break;
626  default:
627  IRDA_DEBUG(0, "%s(), type not implemented!\n", __func__);
628  break;
629  }
631 
632  /* Drop reference count - see state_r_execute(). */
633  dev_kfree_skb(tx_skb);
634 }
635 
636 /*
637  * Function iriap_getvaluebyclass_indication (self, skb)
638  *
639  * getvaluebyclass is requested from peer LM-IAS
640  *
641  */
642 static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
643  struct sk_buff *skb)
644 {
645  struct ias_object *obj;
646  struct ias_attrib *attrib;
647  int name_len;
648  int attr_len;
649  char name[IAS_MAX_CLASSNAME + 1]; /* 60 bytes */
650  char attr[IAS_MAX_ATTRIBNAME + 1]; /* 60 bytes */
651  __u8 *fp;
652  int n;
653 
654  IRDA_DEBUG(4, "%s()\n", __func__);
655 
656  IRDA_ASSERT(self != NULL, return;);
657  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
658  IRDA_ASSERT(skb != NULL, return;);
659 
660  fp = skb->data;
661  n = 1;
662 
663  name_len = fp[n++];
664 
665  IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
666 
667  memcpy(name, fp+n, name_len); n+=name_len;
668  name[name_len] = '\0';
669 
670  attr_len = fp[n++];
671 
672  IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
673 
674  memcpy(attr, fp+n, attr_len); n+=attr_len;
675  attr[attr_len] = '\0';
676 
677  IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
678  obj = irias_find_object(name);
679 
680  if (obj == NULL) {
681  IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name);
682  iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
683  &irias_missing);
684  return;
685  }
686  IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
687 
688  attrib = irias_find_attrib(obj, attr);
689  if (attrib == NULL) {
690  IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr);
691  iriap_getvaluebyclass_response(self, obj->id,
693  &irias_missing);
694  return;
695  }
696 
697  /* We have a match; send the value. */
698  iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
699  attrib->value);
700 }
701 
702 /*
703  * Function iriap_send_ack (void)
704  *
705  * Currently not used
706  *
707  */
708 void iriap_send_ack(struct iriap_cb *self)
709 {
710  struct sk_buff *tx_skb;
711  __u8 *frame;
712 
713  IRDA_DEBUG(2, "%s()\n", __func__);
714 
715  IRDA_ASSERT(self != NULL, return;);
716  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
717 
718  tx_skb = alloc_skb(LMP_MAX_HEADER + 1, GFP_ATOMIC);
719  if (!tx_skb)
720  return;
721 
722  /* Reserve space for MUX and LAP header */
723  skb_reserve(tx_skb, self->max_header_size);
724  skb_put(tx_skb, 1);
725  frame = tx_skb->data;
726 
727  /* Build frame */
728  frame[0] = IAP_LST | IAP_ACK | self->operation;
729 
730  irlmp_data_request(self->lsap, tx_skb);
731 }
732 
733 void iriap_connect_request(struct iriap_cb *self)
734 {
735  int ret;
736 
737  IRDA_ASSERT(self != NULL, return;);
738  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
739 
740  ret = irlmp_connect_request(self->lsap, LSAP_IAS,
741  self->saddr, self->daddr,
742  NULL, NULL);
743  if (ret < 0) {
744  IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
745  self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
746  }
747 }
748 
749 /*
750  * Function iriap_connect_confirm (handle, skb)
751  *
752  * LSAP connection confirmed!
753  *
754  */
755 static void iriap_connect_confirm(void *instance, void *sap,
756  struct qos_info *qos, __u32 max_seg_size,
757  __u8 max_header_size,
758  struct sk_buff *skb)
759 {
760  struct iriap_cb *self;
761 
762  self = instance;
763 
764  IRDA_ASSERT(self != NULL, return;);
765  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
766  IRDA_ASSERT(skb != NULL, return;);
767 
768  self->max_data_size = max_seg_size;
769  self->max_header_size = max_header_size;
770 
771  del_timer(&self->watchdog_timer);
772 
774 
775  /* Drop reference count - see state_s_make_call(). */
776  dev_kfree_skb(skb);
777 }
778 
779 /*
780  * Function iriap_connect_indication ( handle, skb)
781  *
782  * Remote LM-IAS is requesting connection
783  *
784  */
785 static void iriap_connect_indication(void *instance, void *sap,
786  struct qos_info *qos, __u32 max_seg_size,
787  __u8 max_header_size,
788  struct sk_buff *skb)
789 {
790  struct iriap_cb *self, *new;
791 
792  IRDA_DEBUG(1, "%s()\n", __func__);
793 
794  self = instance;
795 
796  IRDA_ASSERT(skb != NULL, return;);
797  IRDA_ASSERT(self != NULL, goto out;);
798  IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
799 
800  /* Start new server */
802  if (!new) {
803  IRDA_DEBUG(0, "%s(), open failed\n", __func__);
804  goto out;
805  }
806 
807  /* Now attach up the new "socket" */
808  new->lsap = irlmp_dup(self->lsap, new);
809  if (!new->lsap) {
810  IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
811  goto out;
812  }
813 
814  new->max_data_size = max_seg_size;
815  new->max_header_size = max_header_size;
816 
817  /* Clean up the original one to keep it in listen state */
818  irlmp_listen(self->lsap);
819 
821 
822 out:
823  /* Drop reference count - see state_r_disconnect(). */
824  dev_kfree_skb(skb);
825 }
826 
827 /*
828  * Function iriap_data_indication (handle, skb)
829  *
830  * Receives data from connection identified by handle from IrLMP
831  *
832  */
833 static int iriap_data_indication(void *instance, void *sap,
834  struct sk_buff *skb)
835 {
836  struct iriap_cb *self;
837  __u8 *frame;
838  __u8 opcode;
839 
840  IRDA_DEBUG(3, "%s()\n", __func__);
841 
842  self = instance;
843 
844  IRDA_ASSERT(skb != NULL, return 0;);
845  IRDA_ASSERT(self != NULL, goto out;);
846  IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;);
847 
848  frame = skb->data;
849 
850  if (self->mode == IAS_SERVER) {
851  /* Call server */
852  IRDA_DEBUG(4, "%s(), Calling server!\n", __func__);
854  goto out;
855  }
856  opcode = frame[0];
857  if (~opcode & IAP_LST) {
858  IRDA_WARNING("%s:, IrIAS multiframe commands or "
859  "results is not implemented yet!\n",
860  __func__);
861  goto out;
862  }
863 
864  /* Check for ack frames since they don't contain any data */
865  if (opcode & IAP_ACK) {
866  IRDA_DEBUG(0, "%s() Got ack frame!\n", __func__);
867  goto out;
868  }
869 
870  opcode &= ~IAP_LST; /* Mask away LST bit */
871 
872  switch (opcode) {
873  case GET_INFO_BASE:
874  IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
875  break;
876  case GET_VALUE_BY_CLASS:
878 
879  switch (frame[1]) {
880  case IAS_SUCCESS:
881  iriap_getvaluebyclass_confirm(self, skb);
882  break;
883  case IAS_CLASS_UNKNOWN:
884  IRDA_DEBUG(1, "%s(), No such class!\n", __func__);
885  /* Finished, close connection! */
886  iriap_disconnect_request(self);
887 
888  /*
889  * Warning, the client might close us, so remember
890  * no to use self anymore after calling confirm
891  */
892  if (self->confirm)
893  self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
894  self->priv);
895  break;
896  case IAS_ATTRIB_UNKNOWN:
897  IRDA_DEBUG(1, "%s(), No such attribute!\n", __func__);
898  /* Finished, close connection! */
899  iriap_disconnect_request(self);
900 
901  /*
902  * Warning, the client might close us, so remember
903  * no to use self anymore after calling confirm
904  */
905  if (self->confirm)
906  self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL,
907  self->priv);
908  break;
909  }
910  break;
911  default:
912  IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __func__,
913  opcode);
914  break;
915  }
916 
917 out:
918  /* Cleanup - sub-calls will have done skb_get() as needed. */
919  dev_kfree_skb(skb);
920  return 0;
921 }
922 
923 /*
924  * Function iriap_call_indication (self, skb)
925  *
926  * Received call to server from peer LM-IAS
927  *
928  */
929 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
930 {
931  __u8 *fp;
932  __u8 opcode;
933 
934  IRDA_DEBUG(4, "%s()\n", __func__);
935 
936  IRDA_ASSERT(self != NULL, return;);
937  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
938  IRDA_ASSERT(skb != NULL, return;);
939 
940  fp = skb->data;
941 
942  opcode = fp[0];
943  if (~opcode & 0x80) {
944  IRDA_WARNING("%s: IrIAS multiframe commands or results "
945  "is not implemented yet!\n", __func__);
946  return;
947  }
948  opcode &= 0x7f; /* Mask away LST bit */
949 
950  switch (opcode) {
951  case GET_INFO_BASE:
952  IRDA_WARNING("%s: GetInfoBaseDetails not implemented yet!\n",
953  __func__);
954  break;
955  case GET_VALUE_BY_CLASS:
956  iriap_getvaluebyclass_indication(self, skb);
957  break;
958  }
959  /* skb will be cleaned up in iriap_data_indication */
960 }
961 
962 /*
963  * Function iriap_watchdog_timer_expired (data)
964  *
965  * Query has taken too long time, so abort
966  *
967  */
968 static void iriap_watchdog_timer_expired(void *data)
969 {
970  struct iriap_cb *self = (struct iriap_cb *) data;
971 
972  IRDA_ASSERT(self != NULL, return;);
973  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
974 
975  /* iriap_close(self); */
976 }
977 
978 #ifdef CONFIG_PROC_FS
979 
980 static const char *const ias_value_types[] = {
981  "IAS_MISSING",
982  "IAS_INTEGER",
983  "IAS_OCT_SEQ",
984  "IAS_STRING"
985 };
986 
987 static inline struct ias_object *irias_seq_idx(loff_t pos)
988 {
989  struct ias_object *obj;
990 
991  for (obj = (struct ias_object *) hashbin_get_first(irias_objects);
992  obj; obj = (struct ias_object *) hashbin_get_next(irias_objects)) {
993  if (pos-- == 0)
994  break;
995  }
996 
997  return obj;
998 }
999 
1000 static void *irias_seq_start(struct seq_file *seq, loff_t *pos)
1001 {
1002  spin_lock_irq(&irias_objects->hb_spinlock);
1003 
1004  return *pos ? irias_seq_idx(*pos - 1) : SEQ_START_TOKEN;
1005 }
1006 
1007 static void *irias_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1008 {
1009  ++*pos;
1010 
1011  return (v == SEQ_START_TOKEN)
1012  ? (void *) hashbin_get_first(irias_objects)
1013  : (void *) hashbin_get_next(irias_objects);
1014 }
1015 
1016 static void irias_seq_stop(struct seq_file *seq, void *v)
1017 {
1018  spin_unlock_irq(&irias_objects->hb_spinlock);
1019 }
1020 
1021 static int irias_seq_show(struct seq_file *seq, void *v)
1022 {
1023  if (v == SEQ_START_TOKEN)
1024  seq_puts(seq, "LM-IAS Objects:\n");
1025  else {
1026  struct ias_object *obj = v;
1027  struct ias_attrib *attrib;
1028 
1029  IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -EINVAL;);
1030 
1031  seq_printf(seq, "name: %s, id=%d\n",
1032  obj->name, obj->id);
1033 
1034  /* Careful for priority inversions here !
1035  * All other uses of attrib spinlock are independent of
1036  * the object spinlock, so we are safe. Jean II */
1037  spin_lock(&obj->attribs->hb_spinlock);
1038 
1039  /* List all attributes for this object */
1040  for (attrib = (struct ias_attrib *) hashbin_get_first(obj->attribs);
1041  attrib != NULL;
1042  attrib = (struct ias_attrib *) hashbin_get_next(obj->attribs)) {
1043 
1044  IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC,
1045  goto outloop; );
1046 
1047  seq_printf(seq, " - Attribute name: \"%s\", ",
1048  attrib->name);
1049  seq_printf(seq, "value[%s]: ",
1050  ias_value_types[attrib->value->type]);
1051 
1052  switch (attrib->value->type) {
1053  case IAS_INTEGER:
1054  seq_printf(seq, "%d\n",
1055  attrib->value->t.integer);
1056  break;
1057  case IAS_STRING:
1058  seq_printf(seq, "\"%s\"\n",
1059  attrib->value->t.string);
1060  break;
1061  case IAS_OCT_SEQ:
1062  seq_printf(seq, "octet sequence (%d bytes)\n",
1063  attrib->value->len);
1064  break;
1065  case IAS_MISSING:
1066  seq_puts(seq, "missing\n");
1067  break;
1068  default:
1069  seq_printf(seq, "type %d?\n",
1070  attrib->value->type);
1071  }
1072  seq_putc(seq, '\n');
1073 
1074  }
1075  IRDA_ASSERT_LABEL(outloop:)
1076  spin_unlock(&obj->attribs->hb_spinlock);
1077  }
1078 
1079  return 0;
1080 }
1081 
1082 static const struct seq_operations irias_seq_ops = {
1083  .start = irias_seq_start,
1084  .next = irias_seq_next,
1085  .stop = irias_seq_stop,
1086  .show = irias_seq_show,
1087 };
1088 
1089 static int irias_seq_open(struct inode *inode, struct file *file)
1090 {
1091  IRDA_ASSERT( irias_objects != NULL, return -EINVAL;);
1092 
1093  return seq_open(file, &irias_seq_ops);
1094 }
1095 
1096 const struct file_operations irias_seq_fops = {
1097  .owner = THIS_MODULE,
1098  .open = irias_seq_open,
1099  .read = seq_read,
1100  .llseek = seq_lseek,
1101  .release = seq_release,
1102 };
1103 
1104 #endif /* PROC_FS */