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