00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <linux/config.h>
00032 #include <linux/module.h>
00033 #include <linux/sched.h>
00034 #include <linux/proc_fs.h>
00035 #include <linux/init.h>
00036
00037 #include <net/irda/irda.h>
00038 #include <net/irda/irmod.h>
00039 #include <net/irda/irlmp.h>
00040 #include <net/irda/iriap.h>
00041 #include <net/irda/irttp.h>
00042 #include <net/irda/irias_object.h>
00043
00044 #include <net/irda/ircomm_event.h>
00045 #include <net/irda/ircomm_lmp.h>
00046 #include <net/irda/ircomm_ttp.h>
00047 #include <net/irda/ircomm_param.h>
00048 #include <net/irda/ircomm_core.h>
00049
00050 static int __ircomm_close(struct ircomm_cb *self);
00051 static void ircomm_control_indication(struct ircomm_cb *self,
00052 struct sk_buff *skb, int clen);
00053
00054 #ifdef CONFIG_PROC_FS
00055 static int ircomm_proc_read(char *buf, char **start, off_t offset, int len,
00056 int unused);
00057
00058 extern struct proc_dir_entry *proc_irda;
00059 #endif
00060
00061 hashbin_t *ircomm = NULL;
00062
00063 int __init ircomm_init(void)
00064 {
00065 ircomm = hashbin_new(HB_LOCAL);
00066 if (ircomm == NULL) {
00067 ERROR(__FUNCTION__ "(), can't allocate hashbin!\n");
00068 return -ENOMEM;
00069 }
00070
00071 #ifdef CONFIG_PROC_FS
00072 create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
00073 #endif
00074
00075 MESSAGE("IrCOMM protocol (Dag Brattli)\n");
00076
00077 return 0;
00078 }
00079
00080 #ifdef MODULE
00081 void ircomm_cleanup(void)
00082 {
00083 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00084
00085 hashbin_delete(ircomm, (FREE_FUNC) __ircomm_close);
00086
00087 #ifdef CONFIG_PROC_FS
00088 remove_proc_entry("ircomm", proc_irda);
00089 #endif
00090 }
00091 #endif
00092
00093
00094
00095
00096
00097
00098
00099 struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
00100 {
00101 struct ircomm_cb *self = NULL;
00102 int ret;
00103
00104 IRDA_DEBUG(2, __FUNCTION__ "(), service_type=0x%02x\n",
00105 service_type);
00106
00107 ASSERT(ircomm != NULL, return NULL;);
00108
00109 self = kmalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
00110 if (self == NULL)
00111 return NULL;
00112
00113 memset(self, 0, sizeof(struct ircomm_cb));
00114
00115 self->notify = *notify;
00116 self->magic = IRCOMM_MAGIC;
00117
00118
00119 if (service_type & IRCOMM_3_WIRE_RAW) {
00120 self->flow_status = FLOW_START;
00121 ret = ircomm_open_lsap(self);
00122 } else
00123 ret = ircomm_open_tsap(self);
00124
00125 if (ret < 0)
00126 return NULL;
00127
00128 self->service_type = service_type;
00129 self->line = line;
00130
00131 hashbin_insert(ircomm, (queue_t *) self, line, NULL);
00132
00133 ircomm_next_state(self, IRCOMM_IDLE);
00134
00135 return self;
00136 }
00137
00138
00139
00140
00141
00142
00143
00144 static int __ircomm_close(struct ircomm_cb *self)
00145 {
00146 IRDA_DEBUG(2, __FUNCTION__"()\n");
00147
00148
00149 ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL, NULL);
00150
00151
00152 if (self->tsap) {
00153 irttp_close_tsap(self->tsap);
00154 self->tsap = NULL;
00155 }
00156
00157
00158 if (self->lsap) {
00159 irlmp_close_lsap(self->lsap);
00160 self->lsap = NULL;
00161 }
00162 self->magic = 0;
00163
00164 kfree(self);
00165
00166 return 0;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175 int ircomm_close(struct ircomm_cb *self)
00176 {
00177 struct ircomm_cb *entry;
00178
00179 ASSERT(self != NULL, return -EIO;);
00180 ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
00181
00182 IRDA_DEBUG(0, __FUNCTION__ "()\n");
00183
00184 entry = hashbin_remove(ircomm, self->line, NULL);
00185
00186 ASSERT(entry == self, return -1;);
00187
00188 return __ircomm_close(self);
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198 int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
00199 __u32 saddr, __u32 daddr, struct sk_buff *skb,
00200 __u8 service_type)
00201 {
00202 struct ircomm_info info;
00203 int ret;
00204
00205 IRDA_DEBUG(2 , __FUNCTION__"()\n");
00206
00207 ASSERT(self != NULL, return -1;);
00208 ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
00209
00210 self->service_type= service_type;
00211
00212 info.dlsap_sel = dlsap_sel;
00213 info.saddr = saddr;
00214 info.daddr = daddr;
00215
00216 ret = ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, skb, &info);
00217
00218 return ret;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
00228 struct ircomm_info *info)
00229 {
00230 int clen = 0;
00231
00232 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00233
00234
00235 if (skb->len > 0)
00236 clen = skb->data[0];
00237
00238
00239
00240
00241
00242
00243 if (self->notify.connect_indication)
00244 self->notify.connect_indication(self->notify.instance, self,
00245 info->qos, info->max_data_size,
00246 info->max_header_size, skb);
00247 else {
00248 IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
00249 dev_kfree_skb(skb);
00250 }
00251 }
00252
00253
00254
00255
00256
00257
00258
00259 int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
00260 {
00261 int ret;
00262
00263 ASSERT(self != NULL, return -1;);
00264 ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
00265
00266 IRDA_DEBUG(4, __FUNCTION__ "()\n");
00267
00268 ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL);
00269
00270 return ret;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279 void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
00280 struct ircomm_info *info)
00281 {
00282 IRDA_DEBUG(4, __FUNCTION__"()\n");
00283
00284 if (self->notify.connect_confirm )
00285 self->notify.connect_confirm(self->notify.instance,
00286 self, info->qos,
00287 info->max_data_size,
00288 info->max_header_size, skb);
00289 else {
00290 IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
00291 dev_kfree_skb(skb);
00292 }
00293 }
00294
00295
00296
00297
00298
00299
00300
00301 int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb)
00302 {
00303 int ret;
00304
00305 IRDA_DEBUG(4, __FUNCTION__"()\n");
00306
00307 ASSERT(self != NULL, return -EFAULT;);
00308 ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
00309 ASSERT(skb != NULL, return -EFAULT;);
00310
00311 ret = ircomm_do_event(self, IRCOMM_DATA_REQUEST, skb, NULL);
00312
00313 return ret;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
00323 {
00324 IRDA_DEBUG(4, __FUNCTION__"()\n");
00325
00326 ASSERT(skb->len > 0, return;);
00327
00328 if (self->notify.data_indication)
00329 self->notify.data_indication(self->notify.instance, self, skb);
00330 else {
00331 IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
00332 dev_kfree_skb(skb);
00333 }
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
00343 {
00344 int clen;
00345
00346 ASSERT(skb->len > 0, return;);
00347
00348 clen = skb->data[0];
00349
00350
00351
00352
00353
00354
00355 if (clen > 0)
00356 ircomm_control_indication(self, skb, clen);
00357
00358
00359 skb_pull(skb, clen+1);
00360
00361 if (skb->len)
00362 ircomm_data_indication(self, skb);
00363 else {
00364 IRDA_DEBUG(4, __FUNCTION__
00365 "(), data was control info only!\n");
00366 dev_kfree_skb(skb);
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376 int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
00377 {
00378 int ret;
00379
00380 IRDA_DEBUG(2, __FUNCTION__"()\n");
00381
00382 ASSERT(self != NULL, return -EFAULT;);
00383 ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
00384 ASSERT(skb != NULL, return -EFAULT;);
00385
00386 ret = ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb, NULL);
00387
00388 return ret;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 static void ircomm_control_indication(struct ircomm_cb *self,
00398 struct sk_buff *skb, int clen)
00399 {
00400 struct sk_buff *ctrl_skb;
00401
00402 IRDA_DEBUG(2, __FUNCTION__"()\n");
00403
00404 ctrl_skb = skb_clone(skb, GFP_ATOMIC);
00405 if (!ctrl_skb)
00406 return;
00407
00408
00409 skb_trim(ctrl_skb, clen+1);
00410
00411
00412 if (self->notify.udata_indication)
00413 self->notify.udata_indication(self->notify.instance, self,
00414 ctrl_skb);
00415 else {
00416 IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
00417 dev_kfree_skb(skb);
00418 }
00419 }
00420
00421
00422
00423
00424
00425
00426
00427 int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
00428 {
00429 struct ircomm_info info;
00430 int ret;
00431
00432 IRDA_DEBUG(2, __FUNCTION__"()\n");
00433
00434 ASSERT(self != NULL, return -1;);
00435 ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
00436
00437 ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata,
00438 &info);
00439 return ret;
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
00449 struct ircomm_info *info)
00450 {
00451 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00452
00453 ASSERT(info != NULL, return;);
00454
00455 if (self->notify.disconnect_indication) {
00456 self->notify.disconnect_indication(self->notify.instance, self,
00457 info->reason, skb);
00458 } else {
00459 IRDA_DEBUG(0, __FUNCTION__ "(), missing handler\n");
00460 dev_kfree_skb(skb);
00461 }
00462 }
00463
00464
00465
00466
00467
00468
00469
00470 void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
00471 {
00472 IRDA_DEBUG(2, __FUNCTION__ "()\n");
00473
00474 ASSERT(self != NULL, return;);
00475 ASSERT(self->magic == IRCOMM_MAGIC, return;);
00476
00477 if (self->service_type == IRCOMM_3_WIRE_RAW)
00478 return;
00479
00480 irttp_flow_request(self->tsap, flow);
00481 }
00482
00483 #ifdef CONFIG_PROC_FS
00484
00485
00486
00487
00488
00489
00490 int ircomm_proc_read(char *buf, char **start, off_t offset, int len,
00491 int unused)
00492 {
00493 struct ircomm_cb *self;
00494 unsigned long flags;
00495 int i=0;
00496
00497 save_flags(flags);
00498 cli();
00499
00500 len = 0;
00501
00502 len += sprintf(buf+len, "Instance %d:\n", i++);
00503
00504 self = (struct ircomm_cb *) hashbin_get_first(ircomm);
00505 while (self != NULL) {
00506 ASSERT(self->magic == IRCOMM_MAGIC, return len;);
00507
00508 self = (struct ircomm_cb *) hashbin_get_next(ircomm);
00509 }
00510 restore_flags(flags);
00511
00512 return len;
00513 }
00514 #endif
00515
00516 #ifdef MODULE
00517 int init_module(void)
00518 {
00519 return ircomm_init();
00520 }
00521
00522 void cleanup_module(void)
00523 {
00524 ircomm_cleanup();
00525 }
00526 #endif
00527