1 /*********************************************************************
3 * Filename: ircomm_common.c
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 ********************************************************************/
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
,
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
,
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
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
[] = {
109 static char *ircommservicetype
[] = {
116 static char *ircommporttype
[] = {
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",
149 #ifdef CONFIG_PROC_FS
150 extern struct proc_dir_entry
*proc_irda
;
153 static void (*state
[])( struct ircomm_cb
*self
, IRCOMM_EVENT event
,
154 struct sk_buff
*skb
) =
158 ircomm_state_discoverywait
,
159 ircomm_state_queryparamwait
,
160 ircomm_state_querylsapwait
,
167 __initfunc(int ircomm_init(void))
171 printk( "Linux-IrDA: IrCOMM protocol ( revision:%s ) \n",
173 DEBUG( 4, __FUNCTION__
"()\n");
175 /* allocate master array */
177 ircomm
= (struct ircomm_cb
**) kmalloc( sizeof(struct ircomm_cb
*) *
178 IRCOMM_MAX_CONNECTION
,
180 if ( ircomm
== NULL
) {
181 printk( KERN_ERR __FUNCTION__
"(): kmalloc failed!\n");
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
);
193 printk( KERN_ERR __FUNCTION__
"(): kmalloc failed!\n");
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");
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
;
235 void ircomm_cleanup(void)
239 DEBUG( 4, "ircomm:cleanup_module\n");
241 * free some resources
244 for (i
=0; i
<IRCOMM_MAX_CONNECTION
; 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
);
258 DEBUG( 4, "freeing master array\n");
263 #ifdef CONFIG_PROC_FS
264 remove_proc_entry("ircomm", proc_irda
);
265 #endif /* CONFIG_PROC_FS */
270 * ----------------------------------------------------------------------
271 * callbacks which accept incoming indication/confirm from IrTTP (or IrLMP)
272 * ----------------------------------------------------------------------
275 static int ircomm_accept_data_indication(void *instance
, void *sap
,
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
);
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
;
309 ASSERT(maxsdusize
>= COMM_DEFAULT_DATA_SIZE
, return;);
310 self
->max_txbuff_size
= maxsdusize
; /* use fragmentation */
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
,
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
;
336 self
->max_txbuff_size
= maxsdusize
;
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
,
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
,
365 struct ircomm_cb
*self
= (struct ircomm_cb
*)instance
;
367 ASSERT( self
!= NULL
, return;);
368 ASSERT( self
->magic
== IRCOMM_MAGIC
, return;);
372 DEBUG(4,__FUNCTION__
"():START\n");
375 if(self
->notify
.flow_indication
)
376 self
->notify
.flow_indication( self
->notify
.instance
,
381 DEBUG(4,__FUNCTION__
":STOP\n");
384 if(self
->notify
.flow_indication
)
385 self
->notify
.flow_indication( self
->notify
.instance
,
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
;
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
);
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
;
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
);
441 DEBUG(4, __FUNCTION__
"():type(%d)\n", value
->type
);
443 self
->ias_type
= value
->type
;
447 DEBUG(4, __FUNCTION__
"():got octet sequence:\n");
451 for ( i
=0;i
<value
->len
;i
++)
453 (__u8
)(*(value
->t
.oct_seq
+ i
)));
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);
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
);
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
);
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
);
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
);
517 self
->dlsap
= value
->t
.integer
;
518 ircomm_do_event(self
, GOT_LSAPSEL
, NULL
);
522 DEBUG( 0, __FUNCTION__
":got IAS_MISSING\n");
523 ircomm_do_event(self
, QUERYIAS_ERROR
, NULL
);
527 DEBUG( 0, __FUNCTION__
":got unknown (strange?)type!\n");
528 ircomm_do_event(self
, QUERYIAS_ERROR
, NULL
);
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
){
549 DEBUG(0, __FUNCTION__
"():THREE_WIRE_RAW is not implemented\n");
557 irttp_connect_request(self
->tsap
, self
->dlsap
,
558 self
->saddr
, self
->daddr
,
559 NULL
, self
->maxsdusize
, userdata
);
563 printk(KERN_ERR __FUNCTION__
"():Illegal servicetype %d\n"
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
,
583 static void connect_indication(struct ircomm_cb
*self
, struct qos_info
*qos
,
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
,
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!");
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
,
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(); */
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");
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
)
645 if(self
->servicetype
== THREE_WIRE_RAW
){
646 /* irlmp_data_request(self->lmhandle,userdata); */
647 DEBUG(0,__FUNCTION__
"():not implemented!");
651 DEBUG(4,__FUNCTION__
"():sending frame\n");
652 err
= irttp_data_request(self
->tsap
, userdata
);
654 printk(KERN_ERR __FUNCTION__
":ttp_data_request failed\n");
656 dev_kfree_skb( userdata
);
661 static void issue_control_request(struct ircomm_cb
*self
,
662 struct sk_buff
*userdata
)
666 DEBUG(4,__FUNCTION__
"()\n");
667 if(self
->servicetype
== THREE_WIRE_RAW
)
669 DEBUG(0,__FUNCTION__
"():THREE_WIRE_RAW is not implemented\n");
674 err
= irttp_data_request(self
->tsap
,userdata
);
677 printk( __FUNCTION__
"():ttp_data_request failed\n");
679 dev_kfree_skb( userdata
);
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.
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
,
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");
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
,
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
)
737 DEBUG( 0, __FUNCTION__
": NEXT STATE=%d(%s), servicetype=(%d)\n",
738 (int)state
, ircommstate
[self
->state
],self
->servicetype
);
747 static void ircomm_state_idle( struct ircomm_cb
*self
, IRCOMM_EVENT event
,
748 struct sk_buff
*skb
)
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
);
760 case TTP_CONNECT_INDICATION
:
762 ircomm_next_state(self
, COMM_WAITR
);
763 connect_indication( self
, self
->qos
, skb
);
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); */
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
)
787 case TTP_CONNECT_INDICATION
:
789 ircomm_next_state(self
, COMM_WAITR
);
791 connect_indication( self
, self
->qos
, skb
);
794 case DISCOVERY_INDICATION
:
795 ircomm_next_state(self
, COMM_QUERYPARAM_WAIT
);
796 query_parameters(self
);
799 case IRCOMM_DISCONNECT_REQUEST
:
800 ircomm_next_state(self
, COMM_IDLE
);
805 ircomm_next_state(self
, COMM_IDLE
);
806 disconnect_indication(self
, NULL
);
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
)
825 case TTP_CONNECT_INDICATION
:
827 ircomm_next_state(self
, COMM_WAITR
);
828 connect_indication( self
, self
->qos
, skb
);
833 ircomm_next_state(self
, COMM_QUERYLSAP_WAIT
);
834 query_lsapsel( self
);
837 case IRCOMM_DISCONNECT_REQUEST
:
838 ircomm_next_state(self
, COMM_IDLE
);
843 ircomm_next_state(self
, COMM_IDLE
);
844 disconnect_indication(self
, NULL
);
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
)
863 case TTP_CONNECT_INDICATION
:
865 ircomm_next_state(self
, COMM_WAITR
);
866 connect_indication( self
, self
->qos
, skb
);
871 ircomm_next_state(self
, COMM_WAITI
);
873 issue_connect_request( self
, skb
);
876 case IRCOMM_DISCONNECT_REQUEST
:
877 ircomm_next_state(self
, COMM_IDLE
);
882 ircomm_next_state(self
, COMM_IDLE
);
883 disconnect_indication(self
, NULL
);
889 DEBUG(0,__FUNCTION__
"():unknown event =%d(%s)\n",
890 event
, ircommevent
[event
]);
898 static void ircomm_state_waiti(struct ircomm_cb
*self
, IRCOMM_EVENT event
,
899 struct sk_buff
*skb
)
902 case TTP_CONNECT_CONFIRM
:
903 ircomm_next_state(self
, COMM_CONN
);
904 connect_confirmation( self
, skb
);
906 case TTP_DISCONNECT_INDICATION
:
907 ircomm_next_state(self
, COMM_IDLE
);
908 disconnect_indication(self
, skb
);
910 /* case LMP_CONNECT_CONFIRM: */
911 /* ircomm_connect_cnfirmation; */
912 /* ircomm_next_state(self, COMM_CONN); */
914 /* case LMP_DISCONNECT_INDICATION: */
915 /* ircomm_disconnect_ind; */
916 /* ircomm_next_state(self, COMM_IDLE); */
919 DEBUG(0,__FUNCTION__
"():unknown event =%d(%s)\n",
920 event
, ircommevent
[event
]);
929 static void ircomm_state_waitr(struct ircomm_cb
*self
, IRCOMM_EVENT event
,
930 struct sk_buff
*skb
)
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,
944 ircomm_next_state(self
, COMM_CONN
);
945 issue_connect_response(self
, skb
);
949 case IRCOMM_DISCONNECT_REQUEST
:
950 ircomm_next_state(self
, COMM_IDLE
);
951 issue_disconnect_request(self
, skb
);
955 case TTP_DISCONNECT_INDICATION
:
956 ircomm_next_state(self
, COMM_IDLE
);
957 disconnect_indication(self
, skb
);
960 case DISCOVERY_INDICATION
:
961 DEBUG(0, __FUNCTION__
"():DISCOVERY_INDICATION\n");
965 DEBUG(0, __FUNCTION__
"():GOT_PARAMETERS\n");
969 DEBUG(0, __FUNCTION__
"():GOT_LSAPSEL\n");
973 /* case LMP_DISCONNECT_INDICATION: */
974 /* disconnect_indication(); */
975 /* ircomm_next_state(self, COMM_IDLE); */
978 DEBUG(0,"ircomm_state_waitr:unknown event =%d(%s)\n",
979 event
, ircommevent
[event
]);
987 static void ircomm_state_conn(struct ircomm_cb
*self
, IRCOMM_EVENT event
,
988 struct sk_buff
*skb
)
991 case TTP_DATA_INDICATION
:
992 process_data(self
, skb
);
994 case IRCOMM_DATA_REQUEST
:
995 issue_data_request(self
, skb
);
997 /* case LMP_DATA_INDICATION: */
998 /* ircomm_data_indicated(); */
1000 case IRCOMM_CONTROL_REQUEST
:
1001 issue_control_request(self
, skb
);
1003 case TTP_DISCONNECT_INDICATION
:
1004 ircomm_next_state(self
, COMM_IDLE
);
1005 disconnect_indication(self
, skb
);
1007 case IRCOMM_DISCONNECT_REQUEST
:
1008 ircomm_next_state(self
, COMM_IDLE
);
1009 issue_disconnect_request(self
, skb
);
1010 queryias_done(self
);
1012 /* case LM_DISCONNECT_INDICATION: */
1013 /* disconnect_indication(); */
1014 /* ircomm_next_state(self, COMM_IDLE); */
1017 case DISCOVERY_INDICATION
:
1018 DEBUG(0, __FUNCTION__
"():DISCOVERY_INDICATION\n");
1019 queryias_done(self
);
1021 case GOT_PARAMETERS
:
1022 DEBUG(0, __FUNCTION__
"():GOT_PARAMETERS\n");
1023 queryias_done(self
);
1026 DEBUG(0, __FUNCTION__
"():GOT_LSAPSEL\n");
1027 queryias_done(self
);
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
)
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
) {
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
,
1072 case 1: /* client only */
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
,
1081 case 2: /* server only */
1083 DEBUG( 0, __FUNCTION__
"():server only mode\n");
1084 self
->skey
= irlmp_register_service(hints
);
1085 discovering_instance
= NULL
;
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
;
1105 irlmp_unregister_client(self
->ckey
);
1108 irlmp_unregister_service(self
->skey
);
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
);
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
,
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
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
,
1202 ASSERT( self
!= NULL
, return;);
1203 ASSERT( self
->magic
== IRCOMM_MAGIC
, return;);
1204 DEBUG(0,__FUNCTION__
"()\n");
1207 /* unregister layer */
1208 switch (ircomm_cs
) {
1209 case 1: /* client only */
1210 irlmp_unregister_client(ckey
);
1213 case 2: /* server only */
1214 irlmp_unregister_service(skey
);
1218 irlmp_unregister_client(ckey
);
1219 irlmp_unregister_service(skey
);
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
)
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");
1250 if(self
->control_ch_pending
){
1251 /* send control_channel */
1252 ircomm_tx_controlchannel(self
);
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
);
1267 * ----------------------------------------------------------------------
1268 * IrCOMM_control.req and friends
1270 * ----------------------------------------------------------------------
1274 static void ircomm_tx_controlchannel(struct ircomm_cb
*self
)
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 */
1288 ASSERT(clen
!= 0,return;);
1297 for ( i
=0;i
<skb
->len
;i
++)
1298 printk("%02x", skb
->data
[i
]);
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
,
1318 struct sk_buff
*skb
;
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
);
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
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];
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");
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
);
1383 append_tuple(self
,instruction
,0,NULL
);
1385 case SET_BUSY_TIMEOUT
:
1386 value
[0] = self
->busy_timeout
;
1387 append_tuple(self
,instruction
,1,value
);
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
);
1399 switch(instruction
){
1400 case POLL_FOR_LINE_SETTINGS
:
1401 append_tuple(self
,instruction
,0,NULL
);
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
);
1422 value
[0] = self
->dte
;
1423 append_tuple(self
,instruction
,1,value
);
1425 self
->dte
&= ~(DELTA_RTS
|DELTA_DTR
);
1429 value
[0] = self
->dce
;
1430 append_tuple(self
,instruction
,1,value
);
1438 switch(instruction
){
1441 value
[0] = self
->servicetype
;
1442 append_tuple(self
,instruction
,1,value
);
1446 value
[0] = self
->data_format
;
1447 append_tuple(self
,instruction
,1,value
);
1451 if(self
->null_modem_mode
){
1453 value
[0] = (self
->flow_ctrl
& 0x55) << 1;
1454 value
[0] |= (self
->flow_ctrl
& 0xAA) >> 1;
1456 value
[0] = self
->flow_ctrl
;
1458 append_tuple(self
,instruction
,1,value
);
1462 value
[0] = self
->line_status
;
1463 append_tuple(self
,instruction
,1,value
);
1467 value
[0] = self
->break_signal
;
1468 append_tuple(self
,instruction
,1,value
);
1472 value
[0] = self
->xon_char
;
1473 value
[1] = self
->xoff_char
;
1474 append_tuple(self
,instruction
,2,value
);
1478 value
[0] = self
->enq_char
;
1479 value
[1] = self
->ack_char
;
1480 append_tuple(self
,instruction
,2,value
);
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
);
1493 case FIXED_PORT_NAME
:
1494 temp
= strlen(&self
->port_name
);
1496 value
= (__u8
) (self
->port_name
);
1497 append_tuple(self
,instruction
,temp
,value
);
1499 DEBUG(0,__FUNCTION__
"() PORT_NAME:too long\n");
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
)
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");
1529 for ( i
=0;i
< skb
->len
;i
++)
1530 printk("%02x", (__u8
)(skb
->data
[i
]));
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
);
1546 /* CONTROL_CHANNEL */
1548 ASSERT( clen
< skb
->len
, goto corrupted
;);
1549 DEBUG(4, __FUNCTION__
"():CONTROL_CHANNEL:len = %d\n",clen
);
1558 * parse controlparameters and set value into structure
1563 ASSERT( clen
>= 2+plen
, goto corrupted
; );
1564 DEBUG(4, __FUNCTION__
"():instruction=0x%02x,len=%d\n",
1570 case POLL_FOR_LINE_SETTINGS
:
1571 ircomm_control_request(self
, DTELINE_STATE
);
1575 self
->peer_servicetype
= data
[2];
1579 self
->peer_port_type
= data
[2];
1583 self
->peer_data_format
= data
[2];
1587 self
->peer_flow_ctrl
= data
[2];
1592 self
->peer_line_status
= data
[2];
1597 self
->peer_break_signal
= data
[2];
1602 self
->peer_dce
= data
[2];
1607 if(self
->null_modem_mode
){
1608 /* input DTR as {DSR & CD & RI} */
1610 if(data
[2] & DELTA_DTR
)
1611 self
->peer_dce
|= (DELTA_DSR
|
1614 if(data
[2] & MCR_DTR
)
1615 self
->peer_dce
|= (MSR_DSR
|
1619 if(data
[2] & DELTA_RTS
)
1620 self
->peer_dce
|= DELTA_CTS
;
1621 if(data
[2] & MCR_RTS
)
1622 self
->peer_dce
|= MSR_CTS
;
1624 self
->peer_dte
= data
[2];
1630 self
->peer_xon_char
= data
[2];
1631 self
->peer_xoff_char
= data
[3];
1636 self
->peer_enq_char
= data
[2];
1637 self
->peer_ack_char
= data
[3];
1642 self
->peer_data_rate
= ( data
[5]<<24
1650 ASSERT(plen
<= 32 , goto corrupted
;);
1651 memcpy(self
->port_name
, data
+ 2, plen
);
1652 *(__u8
*)(self
->port_name
+plen
) = 0;
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
;
1667 DEBUG(0, __FUNCTION__
1668 "():not implemented (PI=%d)\n", pi
);
1673 self
->notify
.flow_indication
&& type
== CONTROL_CHANNEL
)
1675 DEBUG(4,__FUNCTION__
":indicating..:\n");
1677 if(self
->notify
.flow_indication
)
1678 self
->notify
.flow_indication(self
->notify
.instance
,
1682 skb_pull(skb
, 2+plen
);
1689 skb_pull(skb
, skb
->len
); /* remove suspicious data */
1694 * ----------------------------------------------------------------------
1695 * Function ircomm_open_instance() ,ircomm_close_instance() and friends
1697 * ircomm_open_instance discoveres the peer device and then issues a
1699 * ----------------------------------------------------------------------
1704 struct ircomm_cb
* ircomm_open_instance( struct notify_t client_notify
)
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 */
1718 for(i
= 0; i
< IRCOMM_MAX_CONNECTION
; i
++){
1719 ASSERT(ircomm
[i
] != NULL
,return(NULL
););
1720 if(!ircomm
[i
]->in_use
){
1727 DEBUG(0,__FUNCTION__
"():no free handle!\n");
1732 restore_flags(flags
);
1734 self
->notify
= client_notify
;
1736 self
->control_ch_pending
= 0;
1738 /* register callbacks */
1740 irda_notify_init(¬ify
);
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
,
1752 DEBUG(0,__FUNCTION__
"failed to allocate tsap\n");
1756 ircomm_next_state(self
, COMM_IDLE
);
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);
1778 irttp_close_tsap(self
->tsap
);
1786 * ----------------------------------------------------------------------
1787 * Function init_module(void) ,cleanup_module()
1789 * Initializes the ircomm control structure
1790 * These Function are called when you insmod / rmmod .
1791 * ----------------------------------------------------------------------
1795 int init_module(void)
1799 err
= ircomm_init();
1801 DEBUG( 4, __FUNCTION__
"():done.\n");
1805 void cleanup_module(void)
1808 DEBUG( 4, __FUNCTION__
"():done.\n");
1812 /************************************************************
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
)
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");
1838 if (ircomm
[i
] == NULL
|| ircomm
[i
]->magic
!= IRCOMM_MAGIC
) {
1839 len
+= sprintf(buf
+len
, "\tbroken???\n");
1843 switch (ircomm
[i
]->servicetype
) {
1847 case THREE_WIRE_RAW
:
1863 len
+= sprintf(buf
+len
, " service: %s ",
1864 ircommservicetype
[index
]);
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
));
1909 #endif /* CONFIG_PROC_FS */