1 /*********************************************************************
3 * Filename: irlpt_common.c
6 * Status: Experimental.
7 * Author: Thomas Davis, <ratbert@radiks.net>
8 * Created at: Sat Feb 21 18:54:38 1998
9 * Modified at: Sun Mar 8 23:44:19 1998
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
13 * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
14 * Copyright (c) 1998, Dag Brattli, <dagb@cs.uit.no>
15 * All Rights Reserved.
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
22 * I, Thomas Davis, provide no warranty for any of this software.
23 * This material is provided "AS-IS" and at no charge.
25 ********************************************************************/
27 #include <linux/module.h>
29 #include <asm/segment.h>
31 #include <net/irda/irda.h>
32 #include <net/irda/irlap.h>
33 #include <net/irda/irlmp.h>
34 #include <net/irda/iriap.h>
35 #include <net/irda/irttp.h>
36 #include <net/irda/timer.h>
38 #include <net/irda/irlpt_common.h>
39 /* #include "irlpt_client.h" */
40 /* #include "irlpt_server.h" */
42 #include <asm/uaccess.h>
43 #include <linux/miscdevice.h>
44 #include <linux/proc_fs.h>
47 char *irlpt_service_type
[] = {
49 "IRLPT_THREE_WIRE_RAW",
56 char *irlpt_port_type
[] = {
62 char *irlpt_connected
[] = {
69 char *irlpt_reasons
[] = {
70 "SERVICE_CLOSE", /* Service has closed the connection */
71 "DISC_INDICATION", /* Received a disconnect request from peer entity*/
72 "NO_RESPONSE", /* To many retransmits without response */
73 "DEADLOCK_DETECTED", /* To many retransmits _with_ response */
74 "FOUND_NONE", /* No devices were discovered */
79 char *irlpt_client_fsm_state
[] = {
88 char *irlpt_server_fsm_state
[] = {
93 char *irlpt_fsm_event
[] = {
96 "IAS_PROVIDER_NOT_AVAIL",
100 "LMP_CONNECT_INDICATION",
101 "LMP_DISCONNECT_INDICATION",
102 "IRLPT_DISCOVERY_INDICATION",
103 "IRLPT_CONNECT_REQUEST",
104 "IRLPT_DISCONNECT_REQUEST",
105 "CLIENT_DATA_INDICATION",
108 hashbin_t
*irlpt_clients
= NULL
;
109 struct irlpt_cb
*irlpt_server
= NULL
;
110 int irlpt_common_debug
= 4; /* want to change this? please don't!
111 use irlpt_common_debug=3 on the command line! */
113 static struct wait_queue
*irlpt_wait
;
116 static char *rcsid
= "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
119 struct irlpt_cb
*irlpt_find_handle(unsigned int minor
)
121 struct irlpt_cb
*self
;
123 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
125 /* Check for server */
126 if (irlpt_server
!= NULL
&& irlpt_server
->ir_dev
.minor
== minor
) {
127 DEBUG(irlpt_common_debug
, __FUNCTION__
128 ": irlpt_server file handle!\n");
132 /* Check the clients */
133 self
= (struct irlpt_cb
*) hashbin_get_first( irlpt_clients
);
135 ASSERT( self
->magic
== IRLPT_MAGIC
, return NULL
;);
137 if ( minor
== self
->ir_dev
.minor
)
140 self
= (struct irlpt_cb
*) hashbin_get_next( irlpt_clients
);
143 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
148 ssize_t
irlpt_read( struct file
*file
, char *buffer
, size_t count
, loff_t
153 struct irlpt_cb
*self
;
154 struct sk_buff
*skb
= NULL
;
155 struct wait_queue wait
= { current
, NULL
};
157 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
159 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
161 ASSERT( self
!= NULL
, return 0;);
162 ASSERT( self
->magic
== IRLPT_MAGIC
, return 0;);
164 DEBUG( irlpt_common_debug
, __FUNCTION__
165 ": count=%d, skb_len=%d, connected=%d (%s) eof=%d\n",
166 count
, skb_queue_len(&self
->rx_queue
), self
->connected
,
167 irlpt_connected
[self
->connected
], self
->eof
);
169 if (self
->eof
&& !skb_queue_len(&self
->rx_queue
)) {
171 case LM_USER_REQUEST
:
173 DEBUG(3, "irlpt_read: returning 0\n");
175 case LM_LAP_DISCONNECT
:
187 while (len
<= count
) {
188 skb
= skb_dequeue(&self
->rx_queue
);
191 DEBUG(irlpt_common_debug
, __FUNCTION__
192 ": len=%d, skb->len=%d, count=%d\n",
193 len
, (int) skb
->len
, count
);
195 if ((skb
->len
+ len
) < count
) {
196 copy_to_user(ptr
, skb
->data
, skb
->len
);
202 skb_queue_head(&self
->rx_queue
, skb
);
206 DEBUG( irlpt_common_debug
, __FUNCTION__
207 ": skb=NULL, len=%d, count=%d, eof=%d\n",
208 len
, count
, self
->eof
);
210 if (!signal_pending(current
) && !self
->eof
) {
211 add_wait_queue(&irlpt_wait
, &wait
);
212 current
->state
= TASK_INTERRUPTIBLE
;
214 current
->state
= TASK_RUNNING
;
215 remove_wait_queue(&irlpt_wait
, &wait
);
221 DEBUG(irlpt_common_debug
, __FUNCTION__
": len=%d\n", len
);
222 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
226 ssize_t
irlpt_write(struct file
*file
, const char *buffer
,
227 size_t count
, loff_t
*noidea
)
229 struct irlpt_cb
*self
;
231 struct wait_queue wait
= { current
, NULL
};
233 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
235 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
237 ASSERT( self
!= NULL
, return 0;);
238 ASSERT( self
->magic
== IRLPT_MAGIC
, return 0;);
240 DEBUG( irlpt_common_debug
, __FUNCTION__
241 ": count = %d\n", count
);
243 if (self
->state
!= IRLPT_CLIENT_CONN
) {
244 DEBUG( irlpt_common_debug
, __FUNCTION__
245 ": state != IRLPT_CONN (possible link problems?)\n");
249 DEBUG( irlpt_common_debug
, __FUNCTION__
250 ": pkt_count = %d\n", self
->pkt_count
);
251 if (self
->pkt_count
> 8) {
252 DEBUG( irlpt_common_debug
, __FUNCTION__
253 ": too many outstanding buffers, going to sleep\n");
254 add_wait_queue(&self
->write_wait
, &wait
);
255 current
->state
= TASK_INTERRUPTIBLE
;
257 current
->state
= TASK_RUNNING
;
258 remove_wait_queue(&self
->write_wait
, &wait
);
261 DEBUG( irlpt_common_debug
, __FUNCTION__
262 ":count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
263 count
, self
->irlap_data_size
, IRLPT_MAX_HEADER
);
265 if (count
> (self
->irlap_data_size
- IRLPT_MAX_HEADER
)) {
266 count
= (self
->irlap_data_size
- IRLPT_MAX_HEADER
);
267 DEBUG(irlpt_common_debug
, __FUNCTION__
268 ": setting count to %d\n", count
);
271 DEBUG( irlpt_common_debug
, __FUNCTION__
": count = %d\n", count
);
273 skb
= dev_alloc_skb(count
+ IRLPT_MAX_HEADER
);
275 printk( KERN_INFO __FUNCTION__
": couldn't allocate skbuff!\n");
280 * we use the unused stamp field to hold the device minor
281 * number, so we can look it up when the skb is destroyed.
283 *((__u32
*) &skb
->stamp
) = MINOR( file
->f_dentry
->d_inode
->i_rdev
);
285 skb_reserve( skb
, IRLPT_MAX_HEADER
);
286 skb_put( skb
, count
);
288 skb
->destructor
= irlpt_flow_control
;
291 copy_from_user( skb
->data
, buffer
, count
);
293 irlmp_data_request(self
->lsap
, skb
);
295 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
300 loff_t
irlpt_seek( struct file
*file
, loff_t offset
, int count
)
302 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
304 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
311 * Function irlpt_select (inode, filp, mode, table)
313 * Implementation for the select() call
316 int irlpt_select( struct inode
*inode
, struct file
*filp
, int mode
,
319 struct irlpt_cb
*self
;
321 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
323 self
= irlpt_find_handle(MINOR( inode
->i_rdev
));
325 ASSERT( self
!= NULL
, return -1;);
326 ASSERT( self
->magic
== IRLPT_MAGIC
, return -1;);
330 if ( skb_queue_len( &self
->rx_queue
))
331 return 1; /* Readable */
332 select_wait( &self
->read_wait
, table
);
335 if ( self
->connected
)
337 select_wait( &self
->write_wait
, table
);
340 if ( self
->connected
)
342 select_wait( &self
->ex_wait
, table
);
348 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
356 * Function irobex_poll (file, wait)
361 static u_int
irlpt_poll(struct file
*file
, poll_table
*wait
)
363 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
365 /* check out /usr/src/pcmcia/modules/ds.c for an example */
366 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
373 * Function open_irlpt (inode, file)
378 int irlpt_open(struct inode
*inode
, struct file
*file
)
380 struct irlpt_cb
*self
;
382 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
384 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
386 ASSERT( self
!= NULL
, return -1;);
387 ASSERT( self
->magic
== IRLPT_MAGIC
, return -1;);
390 if (self
->state
== IRLPT_IDLE
) {
391 DEBUG( irlpt_common_debug
, __FUNCTION__
392 ": state == IRLPT_IDLE! (no device found yet)\n");
396 if (self
->state
== IRLPT_QUERY
||
397 self
->state
== IRLPT_READY
||
398 self
->state
== IRLPT_WAITI
) {
399 DEBUG( irlpt_common_debug
, __FUNCTION__
": state == IRLPT_QUERY, "
400 "IRLPT_READY or IRLPT_WAITI (link problems)!\n");
406 DEBUG( irlpt_common_debug
, __FUNCTION__
407 ": count not zero; actual = %d\n", self
->count
);
412 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
418 * Function close_irlpt (inode, file)
423 int irlpt_close(struct inode
*inode
, struct file
*file
)
425 struct irlpt_cb
*self
;
427 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
429 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
431 DEBUG(irlpt_common_debug
, __FUNCTION__
": have handle!\n");
433 ASSERT( self
!= NULL
, return -1;);
434 ASSERT( self
->magic
== IRLPT_MAGIC
, return -1;);
436 DEBUG(irlpt_common_debug
, __FUNCTION__
": self->count=%d\n", self
->count
);
440 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
445 void irlpt_dump_buffer( struct sk_buff
*skb
)
449 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
451 for(i
=0;i
<skb
->len
;i
++)
452 if (skb
->data
[i
] > 31 && skb
->data
[i
] < 128) {
453 printk("%c", skb
->data
[i
]);
455 if (skb
->data
[i
] == 0x0d) {
464 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
467 void irlpt_flow_control(struct sk_buff
*skb
)
469 struct irlpt_cb
*self
;
471 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
473 self
= irlpt_find_handle( *((__u32
*) &skb
->stamp
));
477 ASSERT(self
->pkt_count
>= 0, return;);
479 DEBUG(irlpt_common_debug
, __FUNCTION__
480 ": packet destroyed, count = %d\n", self
->pkt_count
);
482 wake_up_interruptible( &self
->write_wait
);
484 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
490 * Function init_module (void)
492 * Initialize the module, this function is called by the
493 * modprobe(1) program.
495 int init_module(void)
501 * Function cleanup_module (void)
503 * Remove the module, this function is called by the rmmod(1)
506 void cleanup_module(void)