Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.39-rc6 1099 lines 27 kB view raw
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 660 IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); 661 662 memcpy(name, fp+n, name_len); n+=name_len; 663 name[name_len] = '\0'; 664 665 attr_len = fp[n++]; 666 667 IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); 668 669 memcpy(attr, fp+n, attr_len); n+=attr_len; 670 attr[attr_len] = '\0'; 671 672 IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr); 673 obj = irias_find_object(name); 674 675 if (obj == NULL) { 676 IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name); 677 iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN, 678 &irias_missing); 679 return; 680 } 681 IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id); 682 683 attrib = irias_find_attrib(obj, attr); 684 if (attrib == NULL) { 685 IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr); 686 iriap_getvaluebyclass_response(self, obj->id, 687 IAS_ATTRIB_UNKNOWN, 688 &irias_missing); 689 return; 690 } 691 692 /* We have a match; send the value. */ 693 iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS, 694 attrib->value); 695} 696 697/* 698 * Function iriap_send_ack (void) 699 * 700 * Currently not used 701 * 702 */ 703void iriap_send_ack(struct iriap_cb *self) 704{ 705 struct sk_buff *tx_skb; 706 __u8 *frame; 707 708 IRDA_DEBUG(2, "%s()\n", __func__); 709 710 IRDA_ASSERT(self != NULL, return;); 711 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 712 713 tx_skb = alloc_skb(LMP_MAX_HEADER + 1, GFP_ATOMIC); 714 if (!tx_skb) 715 return; 716 717 /* Reserve space for MUX and LAP header */ 718 skb_reserve(tx_skb, self->max_header_size); 719 skb_put(tx_skb, 1); 720 frame = tx_skb->data; 721 722 /* Build frame */ 723 frame[0] = IAP_LST | IAP_ACK | self->operation; 724 725 irlmp_data_request(self->lsap, tx_skb); 726} 727 728void iriap_connect_request(struct iriap_cb *self) 729{ 730 int ret; 731 732 IRDA_ASSERT(self != NULL, return;); 733 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 734 735 ret = irlmp_connect_request(self->lsap, LSAP_IAS, 736 self->saddr, self->daddr, 737 NULL, NULL); 738 if (ret < 0) { 739 IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); 740 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv); 741 } 742} 743 744/* 745 * Function iriap_connect_confirm (handle, skb) 746 * 747 * LSAP connection confirmed! 748 * 749 */ 750static void iriap_connect_confirm(void *instance, void *sap, 751 struct qos_info *qos, __u32 max_seg_size, 752 __u8 max_header_size, 753 struct sk_buff *skb) 754{ 755 struct iriap_cb *self; 756 757 self = (struct iriap_cb *) instance; 758 759 IRDA_ASSERT(self != NULL, return;); 760 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 761 IRDA_ASSERT(skb != NULL, return;); 762 763 self->max_data_size = max_seg_size; 764 self->max_header_size = max_header_size; 765 766 del_timer(&self->watchdog_timer); 767 768 iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, skb); 769 770 /* Drop reference count - see state_s_make_call(). */ 771 dev_kfree_skb(skb); 772} 773 774/* 775 * Function iriap_connect_indication ( handle, skb) 776 * 777 * Remote LM-IAS is requesting connection 778 * 779 */ 780static void iriap_connect_indication(void *instance, void *sap, 781 struct qos_info *qos, __u32 max_seg_size, 782 __u8 max_header_size, 783 struct sk_buff *skb) 784{ 785 struct iriap_cb *self, *new; 786 787 IRDA_DEBUG(1, "%s()\n", __func__); 788 789 self = (struct iriap_cb *) instance; 790 791 IRDA_ASSERT(skb != NULL, return;); 792 IRDA_ASSERT(self != NULL, goto out;); 793 IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;); 794 795 /* Start new server */ 796 new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL); 797 if (!new) { 798 IRDA_DEBUG(0, "%s(), open failed\n", __func__); 799 goto out; 800 } 801 802 /* Now attach up the new "socket" */ 803 new->lsap = irlmp_dup(self->lsap, new); 804 if (!new->lsap) { 805 IRDA_DEBUG(0, "%s(), dup failed!\n", __func__); 806 goto out; 807 } 808 809 new->max_data_size = max_seg_size; 810 new->max_header_size = max_header_size; 811 812 /* Clean up the original one to keep it in listen state */ 813 irlmp_listen(self->lsap); 814 815 iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, skb); 816 817out: 818 /* Drop reference count - see state_r_disconnect(). */ 819 dev_kfree_skb(skb); 820} 821 822/* 823 * Function iriap_data_indication (handle, skb) 824 * 825 * Receives data from connection identified by handle from IrLMP 826 * 827 */ 828static int iriap_data_indication(void *instance, void *sap, 829 struct sk_buff *skb) 830{ 831 struct iriap_cb *self; 832 __u8 *frame; 833 __u8 opcode; 834 835 IRDA_DEBUG(3, "%s()\n", __func__); 836 837 self = (struct iriap_cb *) instance; 838 839 IRDA_ASSERT(skb != NULL, return 0;); 840 IRDA_ASSERT(self != NULL, goto out;); 841 IRDA_ASSERT(self->magic == IAS_MAGIC, goto out;); 842 843 frame = skb->data; 844 845 if (self->mode == IAS_SERVER) { 846 /* Call server */ 847 IRDA_DEBUG(4, "%s(), Calling server!\n", __func__); 848 iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb); 849 goto out; 850 } 851 opcode = frame[0]; 852 if (~opcode & IAP_LST) { 853 IRDA_WARNING("%s:, IrIAS multiframe commands or " 854 "results is not implemented yet!\n", 855 __func__); 856 goto out; 857 } 858 859 /* Check for ack frames since they don't contain any data */ 860 if (opcode & IAP_ACK) { 861 IRDA_DEBUG(0, "%s() Got ack frame!\n", __func__); 862 goto out; 863 } 864 865 opcode &= ~IAP_LST; /* Mask away LST bit */ 866 867 switch (opcode) { 868 case GET_INFO_BASE: 869 IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n"); 870 break; 871 case GET_VALUE_BY_CLASS: 872 iriap_do_call_event(self, IAP_RECV_F_LST, NULL); 873 874 switch (frame[1]) { 875 case IAS_SUCCESS: 876 iriap_getvaluebyclass_confirm(self, skb); 877 break; 878 case IAS_CLASS_UNKNOWN: 879 IRDA_DEBUG(1, "%s(), No such class!\n", __func__); 880 /* Finished, close connection! */ 881 iriap_disconnect_request(self); 882 883 /* 884 * Warning, the client might close us, so remember 885 * no to use self anymore after calling confirm 886 */ 887 if (self->confirm) 888 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 889 self->priv); 890 break; 891 case IAS_ATTRIB_UNKNOWN: 892 IRDA_DEBUG(1, "%s(), No such attribute!\n", __func__); 893 /* Finished, close connection! */ 894 iriap_disconnect_request(self); 895 896 /* 897 * Warning, the client might close us, so remember 898 * no to use self anymore after calling confirm 899 */ 900 if (self->confirm) 901 self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL, 902 self->priv); 903 break; 904 } 905 break; 906 default: 907 IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __func__, 908 opcode); 909 break; 910 } 911 912out: 913 /* Cleanup - sub-calls will have done skb_get() as needed. */ 914 dev_kfree_skb(skb); 915 return 0; 916} 917 918/* 919 * Function iriap_call_indication (self, skb) 920 * 921 * Received call to server from peer LM-IAS 922 * 923 */ 924void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb) 925{ 926 __u8 *fp; 927 __u8 opcode; 928 929 IRDA_DEBUG(4, "%s()\n", __func__); 930 931 IRDA_ASSERT(self != NULL, return;); 932 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 933 IRDA_ASSERT(skb != NULL, return;); 934 935 fp = skb->data; 936 937 opcode = fp[0]; 938 if (~opcode & 0x80) { 939 IRDA_WARNING("%s: IrIAS multiframe commands or results " 940 "is not implemented yet!\n", __func__); 941 return; 942 } 943 opcode &= 0x7f; /* Mask away LST bit */ 944 945 switch (opcode) { 946 case GET_INFO_BASE: 947 IRDA_WARNING("%s: GetInfoBaseDetails not implemented yet!\n", 948 __func__); 949 break; 950 case GET_VALUE_BY_CLASS: 951 iriap_getvaluebyclass_indication(self, skb); 952 break; 953 } 954 /* skb will be cleaned up in iriap_data_indication */ 955} 956 957/* 958 * Function iriap_watchdog_timer_expired (data) 959 * 960 * Query has taken too long time, so abort 961 * 962 */ 963static void iriap_watchdog_timer_expired(void *data) 964{ 965 struct iriap_cb *self = (struct iriap_cb *) data; 966 967 IRDA_ASSERT(self != NULL, return;); 968 IRDA_ASSERT(self->magic == IAS_MAGIC, return;); 969 970 /* iriap_close(self); */ 971} 972 973#ifdef CONFIG_PROC_FS 974 975static const char *const ias_value_types[] = { 976 "IAS_MISSING", 977 "IAS_INTEGER", 978 "IAS_OCT_SEQ", 979 "IAS_STRING" 980}; 981 982static inline struct ias_object *irias_seq_idx(loff_t pos) 983{ 984 struct ias_object *obj; 985 986 for (obj = (struct ias_object *) hashbin_get_first(irias_objects); 987 obj; obj = (struct ias_object *) hashbin_get_next(irias_objects)) { 988 if (pos-- == 0) 989 break; 990 } 991 992 return obj; 993} 994 995static void *irias_seq_start(struct seq_file *seq, loff_t *pos) 996{ 997 spin_lock_irq(&irias_objects->hb_spinlock); 998 999 return *pos ? irias_seq_idx(*pos - 1) : SEQ_START_TOKEN; 1000} 1001 1002static void *irias_seq_next(struct seq_file *seq, void *v, loff_t *pos) 1003{ 1004 ++*pos; 1005 1006 return (v == SEQ_START_TOKEN) 1007 ? (void *) hashbin_get_first(irias_objects) 1008 : (void *) hashbin_get_next(irias_objects); 1009} 1010 1011static void irias_seq_stop(struct seq_file *seq, void *v) 1012{ 1013 spin_unlock_irq(&irias_objects->hb_spinlock); 1014} 1015 1016static int irias_seq_show(struct seq_file *seq, void *v) 1017{ 1018 if (v == SEQ_START_TOKEN) 1019 seq_puts(seq, "LM-IAS Objects:\n"); 1020 else { 1021 struct ias_object *obj = v; 1022 struct ias_attrib *attrib; 1023 1024 IRDA_ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -EINVAL;); 1025 1026 seq_printf(seq, "name: %s, id=%d\n", 1027 obj->name, obj->id); 1028 1029 /* Careful for priority inversions here ! 1030 * All other uses of attrib spinlock are independent of 1031 * the object spinlock, so we are safe. Jean II */ 1032 spin_lock(&obj->attribs->hb_spinlock); 1033 1034 /* List all attributes for this object */ 1035 for (attrib = (struct ias_attrib *) hashbin_get_first(obj->attribs); 1036 attrib != NULL; 1037 attrib = (struct ias_attrib *) hashbin_get_next(obj->attribs)) { 1038 1039 IRDA_ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, 1040 goto outloop; ); 1041 1042 seq_printf(seq, " - Attribute name: \"%s\", ", 1043 attrib->name); 1044 seq_printf(seq, "value[%s]: ", 1045 ias_value_types[attrib->value->type]); 1046 1047 switch (attrib->value->type) { 1048 case IAS_INTEGER: 1049 seq_printf(seq, "%d\n", 1050 attrib->value->t.integer); 1051 break; 1052 case IAS_STRING: 1053 seq_printf(seq, "\"%s\"\n", 1054 attrib->value->t.string); 1055 break; 1056 case IAS_OCT_SEQ: 1057 seq_printf(seq, "octet sequence (%d bytes)\n", 1058 attrib->value->len); 1059 break; 1060 case IAS_MISSING: 1061 seq_puts(seq, "missing\n"); 1062 break; 1063 default: 1064 seq_printf(seq, "type %d?\n", 1065 attrib->value->type); 1066 } 1067 seq_putc(seq, '\n'); 1068 1069 } 1070 IRDA_ASSERT_LABEL(outloop:) 1071 spin_unlock(&obj->attribs->hb_spinlock); 1072 } 1073 1074 return 0; 1075} 1076 1077static const struct seq_operations irias_seq_ops = { 1078 .start = irias_seq_start, 1079 .next = irias_seq_next, 1080 .stop = irias_seq_stop, 1081 .show = irias_seq_show, 1082}; 1083 1084static int irias_seq_open(struct inode *inode, struct file *file) 1085{ 1086 IRDA_ASSERT( irias_objects != NULL, return -EINVAL;); 1087 1088 return seq_open(file, &irias_seq_ops); 1089} 1090 1091const struct file_operations irias_seq_fops = { 1092 .owner = THIS_MODULE, 1093 .open = irias_seq_open, 1094 .read = seq_read, 1095 .llseek = seq_lseek, 1096 .release = seq_release, 1097}; 1098 1099#endif /* PROC_FS */