Import 2.2.8pre3
[davej-history.git] / net / irda / ircomm / ircomm_common.c
blobbc8758e1eff540c2808615890bcc9cf7ad9a5257
1 /*********************************************************************
2 *
3 * Filename: ircomm_common.c
4 * Version:
5 * Description: An implementation of IrCOMM service interface,
6 * state machine, and incidental function(s).
7 * Status: Experimental.
8 * Author: Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
9 * Source: irlpt_event.c
11 * Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
12 * All Rights Reserved.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
19 * I, Takahide Higuchi, provide no warranty for any of this software.
20 * This material is provided "AS-IS" and at no charge.
22 ********************************************************************/
25 * Reference:
26 * "'IrCOMM':Serial and Parallel Port Emulation Over IR(Wire Replacement)"
27 * version 1.0, which is available at http://www.irda.org/.
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/sched.h>
33 #include <linux/proc_fs.h>
34 #include <linux/init.h>
36 #include <net/irda/irda.h>
37 #include <net/irda/irlmp.h>
38 #include <net/irda/iriap.h>
39 #include <net/irda/irttp.h>
40 #include <net/irda/irias_object.h>
42 #include <net/irda/ircomm_common.h>
44 static char *revision_date = "Sun Apr 18 00:40:19 1999";
47 static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event,
48 struct sk_buff *skb );
50 static void ircomm_state_discoverywait( struct ircomm_cb *self, IRCOMM_EVENT event,
51 struct sk_buff *skb );
53 static void ircomm_state_queryparamwait( struct ircomm_cb *self, IRCOMM_EVENT event,
54 struct sk_buff *skb );
56 static void ircomm_state_querylsapwait( struct ircomm_cb *self, IRCOMM_EVENT event,
57 struct sk_buff *skb );
59 static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event,
60 struct sk_buff *skb );
61 static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event,
62 struct sk_buff *skb );
63 static void ircomm_state_conn( struct ircomm_cb *self, IRCOMM_EVENT event,
64 struct sk_buff *skb );
65 static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
66 struct sk_buff *skb);
67 static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state);
69 static void ircomm_discovery_indication(discovery_t *discovery);
70 static void ircomm_tx_controlchannel(struct ircomm_cb *self );
71 static int ircomm_proc_read(char *buf, char **start, off_t offset,
72 int len, int unused);
74 static void start_discovering(struct ircomm_cb *self);
75 static void query_lsapsel(struct ircomm_cb * self);
76 static void query_parameters(struct ircomm_cb *self);
77 static void queryias_done(struct ircomm_cb *self);
78 static void ircomm_getvalue_confirm(int result, __u16 obj_id,
79 struct ias_value *value, void *priv);
82 struct ircomm_cb *discovering_instance;
85 * debug parameter ircomm_cs:
86 * 0 = client/server, 1 = client only 2 = server only
87 * usage for example:
88 * insmod ircomm ircomm_cs=1
89 * LILO boot : Linux ircomm_cs=2 etc.
92 static int ircomm_cs = 0;
93 MODULE_PARM(ircomm_cs, "i");
97 static char *ircommstate[] = {
98 "IDLE",
100 "DISCOVERY_WAIT",
101 "QUERYPARAM_WAIT",
102 "QUERYLSAP_WAIT",
104 "WAITI",
105 "WAITR",
106 "CONN",
109 static char *ircommservicetype[] = {
110 "N/A",
111 "THREE_WIRE_RAW",
112 "THREE_WIRE",
113 "NINE_WIRE",
114 "CENTRONICS",
116 static char *ircommporttype[] = {
117 "Unknown",
118 "SERIAL",
119 "PARALLEL",
123 struct ircomm_cb **ircomm = NULL;
125 static char *ircommevent[] = {
126 "IRCOMM_CONNECT_REQUEST",
127 "TTP_CONNECT_INDICATION",
128 "LMP_CONNECT_INDICATION",
130 "TTP_CONNECT_CONFIRM",
131 "TTP_DISCONNECT_INDICATION",
132 "LMP_CONNECT_CONFIRM",
133 "LMP_DISCONNECT_INDICATION",
135 "IRCOMM_CONNECT_RESPONSE",
136 "IRCOMM_DISCONNECT_REQUEST",
138 "TTP_DATA_INDICATION",
139 "IRCOMM_DATA_REQUEST",
140 "LMP_DATA_INDICATION",
141 "IRCOMM_CONTROL_REQUEST",
143 "DISCOVERY_INDICATION",
144 "GOT_PARAMETERS",
145 "GOT_LSAPSEL",
146 "QUERYIAS_ERROR",
149 #ifdef CONFIG_PROC_FS
150 extern struct proc_dir_entry *proc_irda;
151 #endif
153 static void (*state[])( struct ircomm_cb *self, IRCOMM_EVENT event,
154 struct sk_buff *skb) =
156 ircomm_state_idle,
158 ircomm_state_discoverywait,
159 ircomm_state_queryparamwait,
160 ircomm_state_querylsapwait,
162 ircomm_state_waiti,
163 ircomm_state_waitr,
164 ircomm_state_conn,
167 __initfunc(int ircomm_init(void))
169 int i;
171 printk( "Linux-IrDA: IrCOMM protocol ( revision:%s ) \n",
172 revision_date);
173 DEBUG( 4, __FUNCTION__"()\n");
175 /* allocate master array */
177 ircomm = (struct ircomm_cb **) kmalloc( sizeof(struct ircomm_cb *) *
178 IRCOMM_MAX_CONNECTION,
179 GFP_KERNEL);
180 if ( ircomm == NULL) {
181 printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
182 return -ENOMEM;
185 memset( ircomm, 0, sizeof(struct ircomm_cb *) * IRCOMM_MAX_CONNECTION);
187 /* initialize structures */
189 for(i = 0;i < IRCOMM_MAX_CONNECTION; i++){
190 ircomm[i] = kmalloc( sizeof(struct ircomm_cb), GFP_KERNEL );
192 if(!ircomm[i]){
193 printk( KERN_ERR __FUNCTION__"(): kmalloc failed!\n");
194 return -ENOMEM;
198 memset( ircomm[i], 0, sizeof(struct ircomm_cb));
200 ircomm[i]->magic = IRCOMM_MAGIC;
201 /* default settings */
202 ircomm[i]->data_format = CS8;
203 ircomm[i]->flow_ctrl = USE_RTS|USE_DTR; /*TODO: is this OK? */
204 ircomm[i]->xon_char = 0x11;
205 ircomm[i]->xoff_char = 0x13;
206 ircomm[i]->enq_char = 0x05;
207 ircomm[i]->ack_char = 0x06;
209 ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE; /* 64 */
210 ircomm[i]->maxsdusize = SAR_DISABLE;
211 ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
212 if (ircomm[i]->ctrl_skb == NULL){
213 DEBUG(0,"ircomm:init_module:alloc_skb failed!\n");
214 return -ENOMEM;
217 skb_reserve(ircomm[i]->ctrl_skb,COMM_HEADER_SIZE);
222 * we register /proc/irda/ircomm
225 #ifdef CONFIG_PROC_FS
226 create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read;
227 #endif /* CONFIG_PROC_FS */
230 discovering_instance = NULL;
231 return 0;
234 #ifdef MODULE
235 void ircomm_cleanup(void)
237 int i;
239 DEBUG( 4, "ircomm:cleanup_module\n");
241 * free some resources
243 if (ircomm) {
244 for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
245 if (ircomm[i]) {
247 if(ircomm[i]->ctrl_skb){
248 dev_kfree_skb(ircomm[i]->ctrl_skb);
250 ircomm[i]->ctrl_skb = NULL;
253 DEBUG( 4, "freeing structures(%d)\n",i);
254 kfree(ircomm[i]);
255 ircomm[i] = NULL;
258 DEBUG( 4, "freeing master array\n");
259 kfree(ircomm);
260 ircomm = NULL;
263 #ifdef CONFIG_PROC_FS
264 remove_proc_entry("ircomm", proc_irda);
265 #endif /* CONFIG_PROC_FS */
267 #endif /* MODULE */
270 * ----------------------------------------------------------------------
271 * callbacks which accept incoming indication/confirm from IrTTP (or IrLMP)
272 * ----------------------------------------------------------------------
275 static int ircomm_accept_data_indication(void *instance, void *sap,
276 struct sk_buff *skb)
279 struct ircomm_cb *self = (struct ircomm_cb *)instance;
281 ASSERT( self != NULL, return -1;);
282 ASSERT( self->magic == IRCOMM_MAGIC, return -1;);
283 ASSERT( skb != NULL, return -1;);
285 DEBUG(4,__FUNCTION__"():\n");
286 ircomm_do_event( self, TTP_DATA_INDICATION, skb);
287 self->rx_packets++;
289 return 0;
292 static void ircomm_accept_connect_confirm(void *instance, void *sap,
293 struct qos_info *qos,
294 __u32 maxsdusize, struct sk_buff *skb)
297 struct ircomm_cb *self = (struct ircomm_cb *)instance;
299 ASSERT( self != NULL, return;);
300 ASSERT( self->magic == IRCOMM_MAGIC, return;);
301 ASSERT( skb != NULL, return;);
302 ASSERT( qos != NULL, return;);
304 DEBUG(0,__FUNCTION__"(): got connected!\n");
306 if(maxsdusize == SAR_DISABLE)
307 self->max_txbuff_size = qos->data_size.value;
308 else {
309 ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;);
310 self->max_txbuff_size = maxsdusize; /* use fragmentation */
313 self->qos = qos;
314 self->null_modem_mode = 0; /* disable null modem emulation */
316 ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb);
319 static void ircomm_accept_connect_indication(void *instance, void *sap,
320 struct qos_info *qos,
321 __u32 maxsdusize,
322 struct sk_buff *skb )
324 struct ircomm_cb *self = (struct ircomm_cb *)instance;
326 ASSERT( self != NULL, return;);
327 ASSERT( self->magic == IRCOMM_MAGIC, return;);
328 ASSERT( skb != NULL, return;);
329 ASSERT( qos != NULL, return;);
331 DEBUG(0,__FUNCTION__"()\n");
333 if(maxsdusize == SAR_DISABLE)
334 self->max_txbuff_size = qos->data_size.value;
335 else
336 self->max_txbuff_size = maxsdusize;
338 self->qos = qos;
339 ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
341 /* stop connecting */
342 wake_up_interruptible( &self->discovery_wait);
343 wake_up_interruptible( &self->ias_wait);
347 static void ircomm_accept_disconnect_indication(void *instance, void *sap,
348 LM_REASON reason,
349 struct sk_buff *skb)
351 struct ircomm_cb *self = (struct ircomm_cb *)instance;
353 ASSERT( self != NULL, return;);
354 ASSERT( self->magic == IRCOMM_MAGIC, return;);
356 DEBUG(0,__FUNCTION__"():\n");
357 ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
361 static void ircomm_accept_flow_indication( void *instance, void *sap,
362 LOCAL_FLOW cmd)
364 IRCOMM_CMD command;
365 struct ircomm_cb *self = (struct ircomm_cb *)instance;
367 ASSERT( self != NULL, return;);
368 ASSERT( self->magic == IRCOMM_MAGIC, return;);
370 switch(cmd){
371 case FLOW_START:
372 DEBUG(4,__FUNCTION__"():START\n");
373 command = TX_READY;
374 self->ttp_stop = 0;
375 if(self->notify.flow_indication)
376 self->notify.flow_indication( self->notify.instance,
377 self, command);
378 break;
380 case FLOW_STOP:
381 DEBUG(4,__FUNCTION__":STOP\n");
382 command = TX_BUSY;
383 self->ttp_stop = 1;
384 if(self->notify.flow_indication)
385 self->notify.flow_indication( self->notify.instance,
386 self, command);
387 break;
389 default:
390 DEBUG(0,__FUNCTION__"();unknown status!\n");
397 * ircomm_discovery_indication()
398 * Remote device is discovered, try query the remote IAS to see which
399 * device it is, and which services it has.
402 static void ircomm_discovery_indication(discovery_t *discovery)
404 struct ircomm_cb *self;
406 self = discovering_instance;
407 if(self == NULL)
408 return;
409 ASSERT(self->magic == IRCOMM_MAGIC, return;);
411 self->daddr = discovery->daddr;
412 self->saddr = discovery->saddr;
414 DEBUG( 0, __FUNCTION__"():daddr=%08x\n", self->daddr);
416 ircomm_do_event(self, DISCOVERY_INDICATION, NULL);
417 return;
421 * ircomm_getvalue_confirm()
422 * handler for iriap_getvaluebyclass_request()
424 static void ircomm_getvalue_confirm(int result, __u16 obj_id,
425 struct ias_value *value, void *priv)
427 struct ircomm_cb *self = (struct ircomm_cb *) priv;
428 struct sk_buff *skb= NULL;
429 __u8 *frame;
430 __u8 servicetype = 0 ;
431 ASSERT( self != NULL, return;);
432 ASSERT( self->magic == IRCOMM_MAGIC, return;);
434 /* Check if request succeeded */
435 if (result != IAS_SUCCESS) {
436 DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
437 ircomm_do_event(self, QUERYIAS_ERROR, NULL);
438 return;
441 DEBUG(4, __FUNCTION__"():type(%d)\n", value->type);
443 self->ias_type = value->type;
444 switch(value->type){
445 case IAS_OCT_SEQ:
447 DEBUG(4, __FUNCTION__"():got octet sequence:\n");
448 #if 0
450 int i;
451 for ( i=0;i<value->len;i++)
452 printk("%02x",
453 (__u8)(*(value->t.oct_seq + i)));
454 printk("\n");
456 #endif
457 skb = dev_alloc_skb((value->len) + 2);
458 ASSERT(skb != NULL, ircomm_do_event(self, QUERYIAS_ERROR, NULL);return;);
459 frame = skb_put(skb,2);
460 /* MSB first */
461 frame[0] = ( value->len >> 8 ) & 0xff;
462 frame[1] = value->len & 0xff;
464 frame = skb_put(skb,value->len);
465 memcpy(frame, value->t.oct_seq, value->len);
466 ircomm_parse_tuples(self, skb, IAS_PARAM);
467 kfree_skb(skb);
470 * check if servicetype we want is available
473 DEBUG(0,__FUNCTION__"():peer capability is:\n");
474 DEBUG(0,"3wire raw: %s\n",
475 ((self->peer_servicetype & THREE_WIRE_RAW) ? "yes":"no"));
476 DEBUG(0,"3wire : %s\n",
477 ((self->peer_servicetype & THREE_WIRE) ? "yes":"no"));
478 DEBUG(0,"9wire : %s\n",
479 ((self->peer_servicetype & NINE_WIRE) ? "yes":"no"));
480 DEBUG(0,"IEEE1284 : %s\n",
481 ((self->peer_servicetype & CENTRONICS) ? "yes":"no"));
483 self->servicetype &= self->peer_servicetype;
484 if(!(self->servicetype)){
485 DEBUG(0,__FUNCTION__"(): servicetype mismatch!\n");
486 ircomm_do_event(self, QUERYIAS_ERROR, NULL);
487 break;
491 * then choose better one
493 if(self->servicetype & THREE_WIRE_RAW)
494 servicetype = THREE_WIRE_RAW;
495 if(self->servicetype & THREE_WIRE)
496 servicetype = THREE_WIRE;
497 if(self->servicetype & NINE_WIRE)
498 servicetype = NINE_WIRE;
499 if(self->servicetype & CENTRONICS)
500 servicetype = CENTRONICS;
502 self->servicetype = servicetype;
504 /* enter next state */
505 ircomm_do_event(self, GOT_PARAMETERS, NULL);
506 break;
508 case IAS_INTEGER:
509 /* LsapSel seems to be sent to me */
510 DEBUG(0, __FUNCTION__"():got lsapsel = %d\n", value->t.integer);
512 if ( value->t.integer == -1){
513 DEBUG( 0, __FUNCTION__"():invalid value!\n");
514 ircomm_do_event(self, QUERYIAS_ERROR, NULL);
515 return;
517 self->dlsap = value->t.integer;
518 ircomm_do_event(self, GOT_LSAPSEL, NULL);
519 break;
521 case IAS_MISSING:
522 DEBUG( 0, __FUNCTION__":got IAS_MISSING\n");
523 ircomm_do_event(self, QUERYIAS_ERROR, NULL);
524 break;
526 default:
527 DEBUG( 0, __FUNCTION__":got unknown (strange?)type!\n");
528 ircomm_do_event(self, QUERYIAS_ERROR, NULL);
529 break;
536 * ----------------------------------------------------------------------
537 * Impl. of actions (descrived in section 7.4 of the reference)
538 * ----------------------------------------------------------------------
541 static void issue_connect_request(struct ircomm_cb *self,
542 struct sk_buff *userdata )
544 /* TODO: we have to send/build userdata field which contains
545 InitialControlParameters */
547 switch(self->servicetype){
548 case THREE_WIRE_RAW:
549 DEBUG(0, __FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
550 break;
552 case DEFAULT:
553 case THREE_WIRE:
554 case NINE_WIRE:
555 case CENTRONICS:
557 irttp_connect_request(self->tsap, self->dlsap,
558 self->saddr, self->daddr,
559 NULL, self->maxsdusize, userdata);
560 break;
562 default:
563 printk(KERN_ERR __FUNCTION__"():Illegal servicetype %d\n"
564 ,self->servicetype);
568 static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb)
572 * Not implemented parameter"Reason".That is optional.
573 * What is reason? maybe discribed in irmod.h?
576 if(self->notify.disconnect_indication)
577 self->notify.disconnect_indication( self->notify.instance,
578 self,
579 self->reason, skb);
583 static void connect_indication(struct ircomm_cb *self, struct qos_info *qos,
584 struct sk_buff *skb)
587 /* If controlparameters don't exist, we use the servicetype"DEFAULT".*/
588 /* if( !ircomm_parse_controlchannel( self, data)) */
589 /* self->servicetype = DEFAULT; TODOD:fix this! TH */
591 if(self->notify.connect_indication)
592 self->notify.connect_indication(self->notify.instance, self,
593 qos, 0, skb);
596 #if 0
597 /* it's for THREE_WIRE_RAW.*/
598 static void connect_indication_three_wire_raw(void)
600 DEBUG(0,"ircomm:connect_indication_threewire():not implemented!");
602 #endif
605 static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb)
607 DEBUG(4 ,__FUNCTION__"()\n");
609 /* give a connect_confirm to the client */
610 if( self->notify.connect_confirm )
611 self->notify.connect_confirm(self->notify.instance,
612 self, NULL, SAR_DISABLE, skb);
615 static void issue_connect_response(struct ircomm_cb *self,
616 struct sk_buff *skb)
619 DEBUG(0,__FUNCTION__"()\n");
621 if( self->servicetype == THREE_WIRE_RAW){
622 DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n");
623 /* irlmp_connect_rsp(); */
624 } else {
625 irttp_connect_response(self->tsap, self->maxsdusize, skb);
629 static void issue_disconnect_request(struct ircomm_cb *self,
630 struct sk_buff *userdata)
632 if(self->servicetype == THREE_WIRE_RAW){
633 DEBUG(0,__FUNCTION__"():3wireraw is not implemented\n");
635 else
636 irttp_disconnect_request(self->tsap, userdata,
637 self->disconnect_priority);
640 static void issue_data_request(struct ircomm_cb *self,
641 struct sk_buff *userdata )
643 int err;
645 if(self->servicetype == THREE_WIRE_RAW){
646 /* irlmp_data_request(self->lmhandle,userdata); */
647 DEBUG(0,__FUNCTION__"():not implemented!");
648 return;
651 DEBUG(4,__FUNCTION__"():sending frame\n");
652 err = irttp_data_request(self->tsap , userdata );
653 if(err){
654 printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n");
655 if(userdata)
656 dev_kfree_skb( userdata);
658 self->tx_packets++;
661 static void issue_control_request(struct ircomm_cb *self,
662 struct sk_buff *userdata )
664 int err;
666 DEBUG(4,__FUNCTION__"()\n");
667 if(self->servicetype == THREE_WIRE_RAW)
669 DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n");
672 else
674 err = irttp_data_request(self->tsap,userdata);
675 if(err)
677 printk( __FUNCTION__"():ttp_data_request failed\n");
678 if(userdata)
679 dev_kfree_skb( userdata);
681 else
682 self->tx_controls++;
684 self->pending_control_tuples = 0;
688 static void process_data(struct ircomm_cb *self, struct sk_buff *skb )
691 DEBUG(4,__FUNCTION__":skb->len=%d, ircomm header = 1, clen=%d\n",
692 (int)skb->len ,(int)skb->data[0]);
694 /* we have to parse control channel when receiving. (see
695 * page17 of IrCOMM standard) but it is not parsed here since
696 * upper layer may have some receive buffer.
698 * hence upper layer have to parse it when it consumes a packet.
699 * -- TH
702 /* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */
704 if(self->notify.data_indication && skb->len)
705 self->notify.data_indication(self->notify.instance, self,
706 skb);
709 int ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
711 /* Not implemented yet:THREE_WIRE_RAW service uses this function. */
712 DEBUG(0,"ircomm_data_indication:not implemented yet!\n");
714 return 0;
719 * ----------------------------------------------------------------------
720 * Implementation of state chart,
721 * descrived in section 7.1 of the specification.
722 * ----------------------------------------------------------------------
725 static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
726 struct sk_buff *skb)
729 DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n",
730 ircommstate[self->state], ircommevent[event]);
731 (*state[ self->state ]) ( self, event, skb);
734 static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state)
736 self->state = state;
737 DEBUG( 0, __FUNCTION__": NEXT STATE=%d(%s), servicetype=(%d)\n",
738 (int)state, ircommstate[self->state],self->servicetype);
744 * ircomm_state_idle
747 static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event,
748 struct sk_buff *skb )
750 switch(event){
751 case IRCOMM_CONNECT_REQUEST:
753 /* ircomm_next_state(self, COMM_WAITI); */
754 /* issue_connect_request( self, skb ); */
756 ircomm_next_state(self, COMM_DISCOVERY_WAIT);
757 start_discovering(self);
758 break;
760 case TTP_CONNECT_INDICATION:
762 ircomm_next_state(self, COMM_WAITR);
763 connect_indication( self, self->qos, skb);
764 break;
766 case LMP_CONNECT_INDICATION:
768 DEBUG(0,__FUNCTION__"():LMP_CONNECT_IND is notimplemented!");
769 /* connect_indication_three_wire_raw(); */
770 /* ircomm_next_state(self, COMM_WAITR); */
771 break;
773 default:
774 DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
775 event, ircommevent[event]);
780 * ircomm_state_discoverywait
782 static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT event,
783 struct sk_buff *skb )
785 switch(event){
787 case TTP_CONNECT_INDICATION:
789 ircomm_next_state(self, COMM_WAITR);
790 queryias_done(self);
791 connect_indication( self, self->qos, skb);
792 break;
794 case DISCOVERY_INDICATION:
795 ircomm_next_state(self, COMM_QUERYPARAM_WAIT);
796 query_parameters(self);
797 break;
799 case IRCOMM_DISCONNECT_REQUEST:
800 ircomm_next_state(self, COMM_IDLE);
801 queryias_done(self);
802 break;
804 case QUERYIAS_ERROR:
805 ircomm_next_state(self, COMM_IDLE);
806 disconnect_indication(self, NULL);
807 queryias_done(self);
808 break;
810 default:
811 DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
812 event, ircommevent[event]);
817 * ircomm_state_queryparamwait
820 static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT event,
821 struct sk_buff *skb )
823 switch(event){
825 case TTP_CONNECT_INDICATION:
827 ircomm_next_state(self, COMM_WAITR);
828 connect_indication( self, self->qos, skb);
829 break;
831 case GOT_PARAMETERS:
833 ircomm_next_state(self, COMM_QUERYLSAP_WAIT);
834 query_lsapsel( self );
835 break;
837 case IRCOMM_DISCONNECT_REQUEST:
838 ircomm_next_state(self, COMM_IDLE);
839 queryias_done(self);
840 break;
842 case QUERYIAS_ERROR:
843 ircomm_next_state(self, COMM_IDLE);
844 disconnect_indication(self, NULL);
845 queryias_done(self);
846 break;
848 default:
849 DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
850 event, ircommevent[event]);
855 * ircomm_state_querylsapwait
858 static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT event,
859 struct sk_buff *skb )
861 switch(event){
863 case TTP_CONNECT_INDICATION:
865 ircomm_next_state(self, COMM_WAITR);
866 connect_indication( self, self->qos, skb);
867 break;
869 case GOT_LSAPSEL:
871 ircomm_next_state(self, COMM_WAITI);
872 queryias_done(self);
873 issue_connect_request( self, skb );
874 break;
876 case IRCOMM_DISCONNECT_REQUEST:
877 ircomm_next_state(self, COMM_IDLE);
878 queryias_done(self);
879 break;
881 case QUERYIAS_ERROR:
882 ircomm_next_state(self, COMM_IDLE);
883 disconnect_indication(self, NULL);
884 queryias_done(self);
885 break;
888 default:
889 DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
890 event, ircommevent[event]);
895 * ircomm_state_waiti
898 static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
899 struct sk_buff *skb )
901 switch(event){
902 case TTP_CONNECT_CONFIRM:
903 ircomm_next_state(self, COMM_CONN);
904 connect_confirmation( self, skb );
905 break;
906 case TTP_DISCONNECT_INDICATION:
907 ircomm_next_state(self, COMM_IDLE);
908 disconnect_indication(self, skb);
909 break;
910 /* case LMP_CONNECT_CONFIRM: */
911 /* ircomm_connect_cnfirmation; */
912 /* ircomm_next_state(self, COMM_CONN); */
913 /* break; */
914 /* case LMP_DISCONNECT_INDICATION: */
915 /* ircomm_disconnect_ind; */
916 /* ircomm_next_state(self, COMM_IDLE); */
917 /* break; */
918 default:
919 DEBUG(0,__FUNCTION__"():unknown event =%d(%s)\n",
920 event, ircommevent[event]);
927 * ircomm_state_waitr
929 static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
930 struct sk_buff *skb )
933 switch(event){
934 case IRCOMM_CONNECT_RESPONSE:
936 /* issue_connect_response */
938 if(self->servicetype==THREE_WIRE_RAW){
939 DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n");
940 /* irlmp_connect_response(Vpeersap,
941 * ACCEPT,null);
943 } else {
944 ircomm_next_state(self, COMM_CONN);
945 issue_connect_response(self, skb);
947 break;
949 case IRCOMM_DISCONNECT_REQUEST:
950 ircomm_next_state(self, COMM_IDLE);
951 issue_disconnect_request(self, skb);
952 queryias_done(self);
953 break;
955 case TTP_DISCONNECT_INDICATION:
956 ircomm_next_state(self, COMM_IDLE);
957 disconnect_indication(self, skb);
958 break;
960 case DISCOVERY_INDICATION:
961 DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n");
962 queryias_done(self);
963 break;
964 case GOT_PARAMETERS:
965 DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n");
966 queryias_done(self);
967 break;
968 case GOT_LSAPSEL:
969 DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n");
970 queryias_done(self);
971 break;
973 /* case LMP_DISCONNECT_INDICATION: */
974 /* disconnect_indication(); */
975 /* ircomm_next_state(self, COMM_IDLE); */
976 /* break; */
977 default:
978 DEBUG(0,"ircomm_state_waitr:unknown event =%d(%s)\n",
979 event, ircommevent[event]);
984 * ircomm_state_conn
987 static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
988 struct sk_buff *skb )
990 switch(event){
991 case TTP_DATA_INDICATION:
992 process_data(self, skb);
993 break;
994 case IRCOMM_DATA_REQUEST:
995 issue_data_request(self, skb);
996 break;
997 /* case LMP_DATA_INDICATION: */
998 /* ircomm_data_indicated(); */
999 /* break; */
1000 case IRCOMM_CONTROL_REQUEST:
1001 issue_control_request(self, skb);
1002 break;
1003 case TTP_DISCONNECT_INDICATION:
1004 ircomm_next_state(self, COMM_IDLE);
1005 disconnect_indication(self, skb);
1006 break;
1007 case IRCOMM_DISCONNECT_REQUEST:
1008 ircomm_next_state(self, COMM_IDLE);
1009 issue_disconnect_request(self, skb);
1010 queryias_done(self);
1011 break;
1012 /* case LM_DISCONNECT_INDICATION: */
1013 /* disconnect_indication(); */
1014 /* ircomm_next_state(self, COMM_IDLE); */
1015 /* break; */
1017 case DISCOVERY_INDICATION:
1018 DEBUG(0, __FUNCTION__"():DISCOVERY_INDICATION\n");
1019 queryias_done(self);
1020 break;
1021 case GOT_PARAMETERS:
1022 DEBUG(0, __FUNCTION__"():GOT_PARAMETERS\n");
1023 queryias_done(self);
1024 break;
1025 case GOT_LSAPSEL:
1026 DEBUG(0, __FUNCTION__"():GOT_LSAPSEL\n");
1027 queryias_done(self);
1028 break;
1030 default:
1031 DEBUG(0,"ircomm_state_conn:unknown event =%d(%s)\n",
1032 event, ircommevent[event]);
1039 * ----------------------------------------------------------------------
1040 * IrCOMM service interfaces and supporting functions
1042 * ----------------------------------------------------------------------
1046 * start_discovering()
1048 * start discovering and enter DISCOVERY_WAIT state
1051 static void start_discovering(struct ircomm_cb *self)
1053 __u16 hints;
1054 ASSERT( self != NULL, return;);
1055 ASSERT( self->magic == IRCOMM_MAGIC, return;);
1056 DEBUG(4,__FUNCTION__"():servicetype = %d\n",self->servicetype);
1059 hints = irlmp_service_to_hint(S_COMM);
1061 DEBUG(0,__FUNCTION__"():start discovering..\n");
1062 switch (ircomm_cs) {
1063 case 0:
1064 MOD_INC_USE_COUNT;
1065 self->queryias_lock = 1;
1066 discovering_instance = self;
1067 self->skey = irlmp_register_service(hints);
1068 self->ckey = irlmp_register_client(hints, ircomm_discovery_indication,
1069 NULL);
1070 break;
1072 case 1: /* client only */
1073 MOD_INC_USE_COUNT;
1074 self->queryias_lock = 1;
1075 discovering_instance = self;
1076 DEBUG( 0, __FUNCTION__"():client only mode\n");
1077 self->ckey = irlmp_register_client(hints, ircomm_discovery_indication,
1078 NULL);
1079 break;
1081 case 2: /* server only */
1082 default:
1083 DEBUG( 0, __FUNCTION__"():server only mode\n");
1084 self->skey = irlmp_register_service(hints);
1085 discovering_instance = NULL;
1086 break;
1089 return;
1093 * queryias_done(self)
1095 * called when discovery process got wrong results, completed, or terminated.
1098 static void queryias_done(struct ircomm_cb *self)
1100 DEBUG(0, __FUNCTION__"():\n");
1101 if(self->queryias_lock){
1102 self->queryias_lock = 0;
1103 discovering_instance = NULL;
1104 MOD_DEC_USE_COUNT;
1105 irlmp_unregister_client(self->ckey);
1107 if(ircomm_cs != 1)
1108 irlmp_unregister_service(self->skey);
1109 return;
1114 static void query_parameters(struct ircomm_cb *self)
1117 DEBUG(0, __FUNCTION__"():querying IAS: Parameters..\n");
1118 iriap_getvaluebyclass_request( "IrDA:IrCOMM", "Parameters",
1119 self->saddr, self->daddr,
1120 ircomm_getvalue_confirm, self );
1124 static void query_lsapsel(struct ircomm_cb * self)
1126 DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n");
1128 if (!(self->servicetype & THREE_WIRE_RAW)) {
1129 iriap_getvaluebyclass_request(
1130 "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
1131 self->saddr, self->daddr,
1132 ircomm_getvalue_confirm, self );
1133 } else {
1134 DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n");
1139 * ircomm_connect_request()
1140 * Impl. of this function is differ from one of the reference.
1141 * This functin does discovery as well as sending connect request
1145 void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype)
1148 * TODO:build a packet which contains "initial control parameters"
1149 * and send it with connect_request
1152 ASSERT( self != NULL, return;);
1153 ASSERT( self->magic == IRCOMM_MAGIC, return;);
1156 DEBUG(0, __FUNCTION__"():sending connect_request...\n");
1158 self->servicetype= servicetype;
1159 /* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/
1161 self->maxsdusize = SAR_DISABLE;
1162 ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL);
1165 void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
1166 __u32 maxsdusize)
1169 ASSERT( self != NULL, return;);
1170 ASSERT( self->magic == IRCOMM_MAGIC, return;);
1171 /* ASSERT( userdata != NULL, return;); */
1173 DEBUG(4,"ircomm_connect_response:\n");
1176 * TODO:build a packet which contains "initial control parameters"
1177 * and send it with connect_response
1180 if(!userdata){
1181 /* FIXME: check for errors and initialize? DB */
1182 userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
1183 ASSERT(userdata != NULL, return;);
1185 skb_reserve(userdata,COMM_HEADER_SIZE);
1188 /* enable null-modem emulation (i.e. server mode )*/
1189 self->null_modem_mode = 1;
1191 self->maxsdusize = maxsdusize;
1192 if(maxsdusize != SAR_DISABLE)
1193 self->max_txbuff_size = maxsdusize;
1194 ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
1197 void ircomm_disconnect_request(struct ircomm_cb *self,
1198 struct sk_buff *userdata,
1199 int priority)
1202 ASSERT( self != NULL, return;);
1203 ASSERT( self->magic == IRCOMM_MAGIC, return;);
1204 DEBUG(0,__FUNCTION__"()\n");
1206 #if 0
1207 /* unregister layer */
1208 switch (ircomm_cs) {
1209 case 1: /* client only */
1210 irlmp_unregister_client(ckey);
1211 break;
1213 case 2: /* server only */
1214 irlmp_unregister_service(skey);
1215 break;
1216 case 0:
1217 default:
1218 irlmp_unregister_client(ckey);
1219 irlmp_unregister_service(skey);
1220 break;
1222 #endif
1224 self->disconnect_priority = priority;
1225 if(priority != P_HIGH)
1226 self->disconnect_priority = P_NORMAL;
1228 ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata);
1232 int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
1234 __u8 * frame;
1236 DEBUG(4,__FUNCTION__"()\n");
1237 ASSERT( self != NULL, return -EFAULT;);
1238 ASSERT( self->magic == IRCOMM_MAGIC, return -EFAULT;);
1239 ASSERT( userdata != NULL, return -EFAULT;);
1242 if(self->state != COMM_CONN){
1243 DEBUG(4,__FUNCTION__"():not connected, data is ignored\n");
1244 return -EINVAL;
1247 if(self->ttp_stop)
1248 return -EBUSY;
1250 if(self->control_ch_pending){
1251 /* send control_channel */
1252 ircomm_tx_controlchannel(self);
1255 if(self->ttp_stop)
1256 return -EBUSY;
1258 /* add "clen" field */
1259 frame = skb_push(userdata,1);
1260 frame[0]=0; /* without control channel */
1262 ircomm_do_event(self, IRCOMM_DATA_REQUEST, userdata);
1263 return 0;
1267 * ----------------------------------------------------------------------
1268 * IrCOMM_control.req and friends
1270 * ----------------------------------------------------------------------
1274 static void ircomm_tx_controlchannel(struct ircomm_cb *self )
1277 __u8 clen;
1278 struct sk_buff *skb = self->ctrl_skb;
1280 DEBUG(4,__FUNCTION__"()\n");
1281 /* 'self' should have been checked */
1282 ASSERT(!self->ttp_stop, return ;);
1283 ASSERT(self->state == COMM_CONN, return ;);
1285 /* add "clen" field */
1287 clen=skb->len;
1288 ASSERT(clen != 0,return;);
1290 skb_push(skb,1);
1291 skb->data[0]=clen;
1293 #if 0
1294 printk("tx_ctrl:");
1296 int i;
1297 for ( i=0;i<skb->len;i++)
1298 printk("%02x", skb->data[i]);
1299 printk("\n");
1301 #endif
1303 ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb);
1304 self->control_ch_pending = 0;
1306 skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
1307 ASSERT(skb != NULL, return ;);
1309 skb_reserve(skb,COMM_HEADER_SIZE);
1310 self->ctrl_skb = skb;
1314 static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl ,
1315 __u8 *value)
1317 __u8 *frame;
1318 struct sk_buff *skb;
1319 int i,c = 0;
1320 unsigned long flags;
1322 save_flags(flags);cli();
1324 skb = self->ctrl_skb;
1325 ASSERT(skb != NULL, return;);
1327 if(skb_tailroom(skb) < (pl+2)){
1328 DEBUG(0, __FUNCTION__"there's no room.. ignore it\n");
1329 self->ignored_control_tuples++;
1330 restore_flags(flags);
1331 return;
1334 frame = skb_put(skb,pl+2);
1335 frame[c++] = instruction; /* PI */
1336 frame[c++] = pl; /* PL */
1337 for(i=0; i < pl ; i++)
1338 frame[c++] = *value++; /* PV */
1339 restore_flags(flags);
1340 self->pending_control_tuples++;
1341 self->control_ch_pending = 1;
1347 * ircomm_control_request();
1348 * this function is exported as a request to send some control-channel tuples
1349 * to peer device
1352 void ircomm_control_request(struct ircomm_cb *self, __u8 instruction)
1355 __u8 pv[32]; /* 32 max, for PORT_NAME */
1356 __u8 *value = &pv[0];
1357 __u32 temp;
1358 int notsupp=0;
1360 ASSERT( self != NULL, return;);
1361 ASSERT( self->magic == IRCOMM_MAGIC, return;);
1363 if(self->servicetype == THREE_WIRE_RAW){
1364 DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW shuold not use me!\n");
1365 return;
1368 DEBUG(4,__FUNCTION__"()\n");
1370 /* find parameter and its length */
1372 if(self->servicetype == THREE_WIRE) goto threewire;
1373 if(self->servicetype == NINE_WIRE) goto ninewire;
1376 /* FIXME: centronics service is not fully implemented yet*/
1377 switch(instruction){
1378 case IEEE1284_MODE_SUPPORT:
1379 case IEEE1284_DEVICEID:
1380 append_tuple(self,instruction,0,NULL);
1381 break;
1382 case STATUS_QUERY:
1383 append_tuple(self,instruction,0,NULL);
1384 break;
1385 case SET_BUSY_TIMEOUT:
1386 value[0] = self->busy_timeout;
1387 append_tuple(self,instruction,1,value);
1388 break;
1389 case IEEE1284_ECP_EPP_DATA_TRANSFER:
1390 value[0] = self->ecp_epp_mode;
1391 value[1] = self->channel_or_addr;
1392 append_tuple(self,instruction,2,value);
1393 break;
1394 default:
1395 notsupp=1;
1398 ninewire:
1399 switch(instruction){
1400 case POLL_FOR_LINE_SETTINGS:
1401 append_tuple(self,instruction,0,NULL);
1402 break;
1403 case DTELINE_STATE:
1404 if(self->null_modem_mode){
1405 /* null modem emulation */
1407 /* output RTS as CTS */
1409 if(self->dte & DELTA_RTS)
1410 value[0] = DELTA_CTS;
1411 if(self->dte & MCR_RTS)
1412 value[0] |= MSR_CTS;
1414 /* output DTR as {DSR & CD & RI} */
1416 if(self->dte & DELTA_DTR)
1417 value[0] |= (DELTA_DSR|DELTA_RI|DELTA_DCD);
1418 if(self->dte & MCR_DTR)
1419 value[0] |= (MSR_DSR|MSR_RI|MSR_DCD);
1420 append_tuple(self,DCELINE_STATE,1,value);
1421 }else{
1422 value[0] = self->dte;
1423 append_tuple(self,instruction,1,value);
1425 self->dte &= ~(DELTA_RTS|DELTA_DTR);
1426 break;
1428 case DCELINE_STATE:
1429 value[0] = self->dce;
1430 append_tuple(self,instruction,1,value);
1431 break;
1433 default:
1434 notsupp=1;
1437 threewire:
1438 switch(instruction){
1440 case SERVICETYPE:
1441 value[0] = self->servicetype;
1442 append_tuple(self,instruction,1,value);
1443 break;
1445 case DATA_FORMAT:
1446 value[0] = self->data_format;
1447 append_tuple(self,instruction,1,value);
1448 break;
1450 case FLOW_CONTROL:
1451 if(self->null_modem_mode){
1452 /* inside out */
1453 value[0] = (self->flow_ctrl & 0x55) << 1;
1454 value[0] |= (self->flow_ctrl & 0xAA) >> 1;
1455 }else{
1456 value[0] = self->flow_ctrl;
1458 append_tuple(self,instruction,1,value);
1459 break;
1461 case LINESTATUS:
1462 value[0] = self->line_status;
1463 append_tuple(self,instruction,1,value);
1464 break;
1466 case BREAK_SIGNAL:
1467 value[0] = self->break_signal;
1468 append_tuple(self,instruction,1,value);
1469 break;
1471 case XON_XOFF_CHAR:
1472 value[0] = self->xon_char;
1473 value[1] = self->xoff_char;
1474 append_tuple(self,instruction,2,value);
1475 break;
1477 case ENQ_ACK_CHAR:
1478 value[0] = self->enq_char;
1479 value[1] = self->ack_char;
1480 append_tuple(self,instruction,2,value);
1481 break;
1483 case DATA_RATE:
1484 temp = self->data_rate;
1485 value[3] = (__u8)((temp >> 24) & 0x000000ff);
1486 value[2] = (__u8)((temp >> 16) & 0x000000ff);
1487 value[1] = (__u8)((temp >> 8) & 0x000000ff);
1488 value[0] = (__u8)(temp & 0x000000ff);
1489 append_tuple(self,instruction,4,value);
1490 break;
1491 #if 0
1492 case PORT_NAME:
1493 case FIXED_PORT_NAME:
1494 temp = strlen(&self->port_name);
1495 if(temp < 32){
1496 value = (__u8) (self->port_name);
1497 append_tuple(self,instruction,temp,value);
1498 }else
1499 DEBUG(0,__FUNCTION__"() PORT_NAME:too long\n");
1500 #endif
1501 break;
1503 default:
1504 if(notsupp)
1505 DEBUG(0,__FUNCTION__"():instruction(0x%02x)is not"
1506 "implemented\n",instruction);
1512 void ircomm_parse_tuples(struct ircomm_cb *self, struct sk_buff *skb, int type)
1515 __u8 *data;
1516 __u8 pi,plen;
1517 int clen = 0;
1518 int indicate=0;
1520 ASSERT(skb != NULL, return;);
1521 ASSERT(self != NULL, return ;);
1522 ASSERT(self->magic == IRCOMM_MAGIC, return ;);
1525 #ifdef IRCOMM_DEBUG_TUPLE
1526 DEBUG(0, __FUNCTION__"():tuple sequence is:\n");
1528 int i;
1529 for ( i=0;i< skb->len;i++)
1530 printk("%02x", (__u8)(skb->data[i]));
1531 printk("\n");
1533 #endif
1535 data = skb->data;
1536 if(type == IAS_PARAM)
1538 clen = (data[0] << 8) & 0xff00;
1539 clen |= data[1] & 0x00ff;
1540 ASSERT( clen <= (skb->len - 2) && clen <= 1024, goto corrupted;);
1541 DEBUG(4, __FUNCTION__"():IAS_PARAM len = %d\n",clen );
1542 skb_pull( skb, 2);
1544 else
1546 /* CONTROL_CHANNEL */
1547 clen = data[0];
1548 ASSERT( clen < skb->len, goto corrupted;);
1549 DEBUG(4, __FUNCTION__"():CONTROL_CHANNEL:len = %d\n",clen );
1550 skb_pull( skb, 1);
1553 while( clen >= 2 ){
1554 data = skb->data;
1555 indicate = 0;
1558 * parse controlparameters and set value into structure
1560 pi = data[0];
1561 plen = data[1];
1563 ASSERT( clen >= 2+plen, goto corrupted; );
1564 DEBUG(4, __FUNCTION__"():instruction=0x%02x,len=%d\n",
1565 pi, plen) ;
1568 switch(pi)
1570 case POLL_FOR_LINE_SETTINGS:
1571 ircomm_control_request(self, DTELINE_STATE);
1572 break;
1574 case SERVICETYPE:
1575 self->peer_servicetype = data[2];
1576 break;
1578 case PORT_TYPE:
1579 self->peer_port_type = data[2];
1580 break;
1582 case DATA_FORMAT:
1583 self->peer_data_format = data[2];
1584 break;
1586 case FLOW_CONTROL:
1587 self->peer_flow_ctrl = data[2];
1588 indicate = 1;
1589 break;
1591 case LINESTATUS:
1592 self->peer_line_status = data[2];
1593 indicate = 1;
1594 break;
1596 case BREAK_SIGNAL:
1597 self->peer_break_signal = data[2];
1598 /* indicate = 1; */
1599 break;
1601 case DCELINE_STATE:
1602 self->peer_dce = data[2];
1603 indicate = 1;
1604 break;
1606 case DTELINE_STATE:
1607 if(self->null_modem_mode){
1608 /* input DTR as {DSR & CD & RI} */
1609 self->peer_dce = 0;
1610 if(data[2] & DELTA_DTR)
1611 self->peer_dce |= (DELTA_DSR|
1612 DELTA_RI|
1613 DELTA_DCD);
1614 if(data[2] & MCR_DTR)
1615 self->peer_dce |= (MSR_DSR|
1616 MSR_RI|
1617 MSR_DCD);
1618 /* rts as cts */
1619 if(data[2] & DELTA_RTS)
1620 self->peer_dce |= DELTA_CTS;
1621 if(data[2] & MCR_RTS)
1622 self->peer_dce |= MSR_CTS;
1623 }else{
1624 self->peer_dte = data[2];
1626 indicate = 1;
1627 break;
1629 case XON_XOFF_CHAR:
1630 self->peer_xon_char = data[2];
1631 self->peer_xoff_char = data[3];
1632 indicate = 1;
1633 break;
1635 case ENQ_ACK_CHAR:
1636 self->peer_enq_char = data[2];
1637 self->peer_ack_char = data[3];
1638 indicate = 1;
1639 break;
1641 case DATA_RATE:
1642 self->peer_data_rate = ( data[5]<<24
1643 & data[4]<<16
1644 & data[3]<<8
1645 & data[2]);
1646 indicate = 1;
1647 break;
1649 case PORT_NAME:
1650 ASSERT(plen <= 32 , goto corrupted;);
1651 memcpy(self->port_name, data + 2, plen);
1652 *(__u8 *)(self->port_name+plen) = 0;
1653 break;
1655 case FIXED_PORT_NAME:
1656 ASSERT(plen <= 32 , goto corrupted;);
1657 memcpy(self->port_name, data + 2, plen);
1658 *(__u8 *)(self->port_name+plen) = 0;
1660 * We should not connect if user of IrCOMM can't
1661 * recognize the port name
1663 self->port_name_critical = TRUE;
1664 break;
1666 default:
1667 DEBUG(0, __FUNCTION__
1668 "():not implemented (PI=%d)\n", pi);
1672 if(indicate &&
1673 self->notify.flow_indication && type == CONTROL_CHANNEL)
1675 DEBUG(4,__FUNCTION__":indicating..:\n");
1676 self->pi = pi;
1677 if(self->notify.flow_indication)
1678 self->notify.flow_indication(self->notify.instance,
1679 self,
1680 CONTROL_CHANNEL);
1682 skb_pull(skb, 2+plen);
1683 clen -= (2+plen);
1686 return;
1688 corrupted:
1689 skb_pull(skb, skb->len); /* remove suspicious data */
1690 return;
1694 * ----------------------------------------------------------------------
1695 * Function ircomm_open_instance() ,ircomm_close_instance() and friends
1697 * ircomm_open_instance discoveres the peer device and then issues a
1698 * connect request
1699 * ----------------------------------------------------------------------
1704 struct ircomm_cb * ircomm_open_instance( struct notify_t client_notify)
1706 int i;
1707 struct ircomm_cb *self = NULL;
1708 struct notify_t notify;
1709 unsigned long flags;
1711 ASSERT(ircomm != NULL,return NULL;);
1712 DEBUG(0,__FUNCTION__"():\n");
1714 /* find free handle */
1716 save_flags(flags);
1717 cli();
1718 for(i = 0; i < IRCOMM_MAX_CONNECTION; i++){
1719 ASSERT(ircomm[i] != NULL,return(NULL););
1720 if(!ircomm[i]->in_use){
1721 self = ircomm[i];
1722 break;
1726 if (!self){
1727 DEBUG(0,__FUNCTION__"():no free handle!\n");
1728 return (NULL);
1731 self->in_use = 1;
1732 restore_flags(flags);
1734 self->notify = client_notify;
1735 self->ttp_stop = 0;
1736 self->control_ch_pending = 0;
1738 /* register callbacks */
1740 irda_notify_init(&notify);
1741 notify.data_indication = ircomm_accept_data_indication;
1742 notify.connect_confirm = ircomm_accept_connect_confirm;
1743 notify.connect_indication = ircomm_accept_connect_indication;
1744 notify.flow_indication = ircomm_accept_flow_indication;
1745 notify.disconnect_indication = ircomm_accept_disconnect_indication;
1746 notify.instance = self;
1747 strncpy( notify.name, "IrCOMM", NOTIFY_MAX_NAME);
1749 self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
1750 &notify);
1751 if(!self->tsap){
1752 DEBUG(0,__FUNCTION__"failed to allocate tsap\n");
1753 return NULL;
1756 ircomm_next_state(self, COMM_IDLE);
1757 return (self);
1760 int ircomm_close_instance(struct ircomm_cb *self)
1762 ASSERT( self != NULL, return -EIO;);
1763 ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;);
1764 ASSERT( self->ctrl_skb != NULL, return -EIO;);
1766 DEBUG(0,__FUNCTION__"()\n");
1768 /* shutdown ircomm layer */
1769 if(self->state != COMM_IDLE && self->state != COMM_WAITI)
1771 DEBUG(0,__FUNCTION__"():force disconnecting..\n");
1772 ircomm_disconnect_request(self, NULL, P_HIGH);
1775 skb_trim(self->ctrl_skb,0);
1776 /* remove a tsap */
1777 if(self->tsap)
1778 irttp_close_tsap(self->tsap);
1779 self->tsap = NULL;
1780 self->in_use = 0;
1781 return 0;
1786 * ----------------------------------------------------------------------
1787 * Function init_module(void) ,cleanup_module()
1789 * Initializes the ircomm control structure
1790 * These Function are called when you insmod / rmmod .
1791 * ----------------------------------------------------------------------
1794 #ifdef MODULE
1795 int init_module(void)
1797 int err;
1799 err = ircomm_init();
1801 DEBUG( 4, __FUNCTION__"():done.\n");
1802 return err;
1805 void cleanup_module(void)
1807 ircomm_cleanup();
1808 DEBUG( 4, __FUNCTION__"():done.\n");
1810 #endif /* MODULE */
1812 /************************************************************
1813 * proc stuff
1814 ************************************************************/
1816 #ifdef CONFIG_PROC_FS
1819 * Function proc_ircomm_read (buf, start, offset, len, unused)
1821 * this function is called if there is a access on /proc/irda/comm .
1824 int ircomm_proc_read(char *buf, char **start, off_t offset,
1825 int len, int unused)
1827 int i, index;
1829 len = 0;
1830 for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
1832 len += sprintf(buf+len, "instance %d:\n",i);
1833 if(ircomm[i]->in_use == 0){
1834 len += sprintf(buf+len, "\tunused\n");
1835 continue;
1838 if (ircomm[i] == NULL || ircomm[i]->magic != IRCOMM_MAGIC) {
1839 len += sprintf(buf+len, "\tbroken???\n");
1840 continue;
1843 switch (ircomm[i]->servicetype) {
1844 case UNKNOWN:
1845 index = 0;
1846 break;
1847 case THREE_WIRE_RAW:
1848 index = 1;
1849 break;
1850 case THREE_WIRE:
1851 index = 2;
1852 break;
1853 case NINE_WIRE:
1854 index = 3;
1855 break;
1856 case CENTRONICS:
1857 index = 4;
1858 break;
1859 default:
1860 index = 0;
1861 break;
1863 len += sprintf(buf+len, " service: %s ",
1864 ircommservicetype[index]);
1865 if(!index)
1866 continue;
1868 len += sprintf(buf+len, "porttype: %s ",
1869 ircommporttype[ircomm[i]->port_type]);
1870 len += sprintf(buf+len, "state: %s ",
1871 ircommstate[ircomm[i]->state]);
1872 len += sprintf(buf+len, "user: %s\n",
1873 ircomm[i]->notify.name);
1875 len += sprintf(buf+len, " tx packets: %d ",
1876 ircomm[i]->tx_packets);
1877 len += sprintf(buf+len, "rx packets: %d ",
1878 ircomm[i]->rx_packets);
1879 len += sprintf(buf+len, "tx controls: %d\n",
1880 ircomm[i]->tx_controls);
1882 len += sprintf(buf+len, " pending tuples: %d ",
1883 ircomm[i]->pending_control_tuples);
1884 len += sprintf(buf+len, " ignored tuples: %d\n",
1885 ircomm[i]->ignored_control_tuples);
1887 len += sprintf(buf+len, " nullmodem emulation: %s ",
1888 (ircomm[i]->null_modem_mode ? "yes":"no"));
1889 len += sprintf(buf+len, "IrTTP: %s\n",
1890 (ircomm[i]->ttp_stop ? "BUSY":"READY"));
1892 len += sprintf(buf+len, " Peer capability: ");
1893 if(ircomm[i]->peer_cap & THREE_WIRE_RAW)
1894 len += sprintf(buf+len, "3wire-raw ");
1895 if(ircomm[i]->peer_cap & THREE_WIRE)
1896 len += sprintf(buf+len, "3wire ");
1897 if(ircomm[i]->peer_cap & NINE_WIRE)
1898 len += sprintf(buf+len, "9wire ");
1899 if(ircomm[i]->peer_cap & CENTRONICS)
1900 len += sprintf(buf+len, "centronics");
1902 len += sprintf(buf+len, "\n Port name: %s\n",
1903 (ircomm[i]->port_name));
1906 return len;
1909 #endif /* CONFIG_PROC_FS */