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/config.h>
28 #include <linux/module.h>
30 #include <asm/segment.h>
32 #include <net/irda/irda.h>
33 #include <net/irda/irlap.h>
34 #include <net/irda/irlmp.h>
35 #include <net/irda/iriap.h>
36 #include <net/irda/irttp.h>
37 #include <net/irda/timer.h>
39 #include <net/irda/irlpt_common.h>
40 /* #include "irlpt_client.h" */
41 /* #include "irlpt_server.h" */
43 #include <asm/uaccess.h>
44 #include <linux/miscdevice.h>
45 #include <linux/proc_fs.h>
48 char *irlpt_service_type
[] = {
50 "IRLPT_THREE_WIRE_RAW",
57 char *irlpt_port_type
[] = {
63 char *irlpt_connected
[] = {
70 char *irlpt_reasons
[] = {
71 "SERVICE_CLOSE", /* Service has closed the connection */
72 "DISC_INDICATION", /* Received a disconnect request from peer entity*/
73 "NO_RESPONSE", /* To many retransmits without response */
74 "DEADLOCK_DETECTED", /* To many retransmits _with_ response */
75 "FOUND_NONE", /* No devices were discovered */
80 char *irlpt_client_fsm_state
[] = {
89 char *irlpt_server_fsm_state
[] = {
94 char *irlpt_fsm_event
[] = {
97 "IAS_PROVIDER_NOT_AVAIL",
101 "LMP_CONNECT_INDICATION",
102 "LMP_DISCONNECT_INDICATION",
103 "IRLPT_DISCOVERY_INDICATION",
104 "IRLPT_CONNECT_REQUEST",
105 "IRLPT_DISCONNECT_REQUEST",
106 "CLIENT_DATA_INDICATION",
109 hashbin_t
*irlpt_clients
= NULL
;
110 struct irlpt_cb
*irlpt_server
= NULL
;
111 int irlpt_common_debug
= 4; /* want to change this? please don't!
112 use irlpt_common_debug=3 on the command line! */
114 static struct wait_queue
*irlpt_wait
;
117 static char *rcsid
= "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
120 struct irlpt_cb
*irlpt_find_handle(unsigned int minor
)
122 struct irlpt_cb
*self
;
124 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
126 /* Check for server */
127 if (irlpt_server
!= NULL
&& irlpt_server
->ir_dev
.minor
== minor
) {
128 DEBUG(irlpt_common_debug
, __FUNCTION__
129 ": irlpt_server file handle!\n");
133 /* Check the clients */
134 self
= (struct irlpt_cb
*) hashbin_get_first( irlpt_clients
);
136 ASSERT( self
->magic
== IRLPT_MAGIC
, return NULL
;);
138 if ( minor
== self
->ir_dev
.minor
)
141 self
= (struct irlpt_cb
*) hashbin_get_next( irlpt_clients
);
144 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
149 ssize_t
irlpt_read( struct file
*file
, char *buffer
, size_t count
, loff_t
154 struct irlpt_cb
*self
;
155 struct sk_buff
*skb
= NULL
;
156 struct wait_queue wait
= { current
, NULL
};
158 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
160 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
162 ASSERT( self
!= NULL
, return 0;);
163 ASSERT( self
->magic
== IRLPT_MAGIC
, return 0;);
165 DEBUG( irlpt_common_debug
, __FUNCTION__
166 ": count=%d, skb_len=%d, connected=%d (%s) eof=%d\n",
167 count
, skb_queue_len(&self
->rx_queue
), self
->connected
,
168 irlpt_connected
[self
->connected
], self
->eof
);
170 if (self
->eof
&& !skb_queue_len(&self
->rx_queue
)) {
172 case LM_USER_REQUEST
:
174 DEBUG(3, "irlpt_read: returning 0\n");
176 case LM_LAP_DISCONNECT
:
188 while (len
<= count
) {
189 skb
= skb_dequeue(&self
->rx_queue
);
192 DEBUG(irlpt_common_debug
, __FUNCTION__
193 ": len=%d, skb->len=%d, count=%d\n",
194 len
, (int) skb
->len
, count
);
196 if ((skb
->len
+ len
) < count
) {
197 copy_to_user(ptr
, skb
->data
, skb
->len
);
203 skb_queue_head(&self
->rx_queue
, skb
);
207 DEBUG( irlpt_common_debug
, __FUNCTION__
208 ": skb=NULL, len=%d, count=%d, eof=%d\n",
209 len
, count
, self
->eof
);
211 if (!signal_pending(current
) && !self
->eof
) {
212 add_wait_queue(&irlpt_wait
, &wait
);
213 current
->state
= TASK_INTERRUPTIBLE
;
215 current
->state
= TASK_RUNNING
;
216 remove_wait_queue(&irlpt_wait
, &wait
);
222 DEBUG(irlpt_common_debug
, __FUNCTION__
": len=%d\n", len
);
223 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
227 ssize_t
irlpt_write(struct file
*file
, const char *buffer
,
228 size_t count
, loff_t
*noidea
)
230 struct irlpt_cb
*self
;
232 struct wait_queue wait
= { current
, NULL
};
234 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
236 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
238 ASSERT( self
!= NULL
, return 0;);
239 ASSERT( self
->magic
== IRLPT_MAGIC
, return 0;);
241 DEBUG( irlpt_common_debug
, __FUNCTION__
242 ": count = %d\n", count
);
244 if (self
->state
!= IRLPT_CLIENT_CONN
) {
245 DEBUG( irlpt_common_debug
, __FUNCTION__
246 ": state != IRLPT_CONN (possible link problems?)\n");
250 DEBUG( irlpt_common_debug
, __FUNCTION__
251 ": pkt_count = %d\n", self
->pkt_count
);
252 if (self
->pkt_count
> 8) {
253 DEBUG( irlpt_common_debug
, __FUNCTION__
254 ": too many outstanding buffers, going to sleep\n");
255 add_wait_queue(&self
->write_wait
, &wait
);
256 current
->state
= TASK_INTERRUPTIBLE
;
258 current
->state
= TASK_RUNNING
;
259 remove_wait_queue(&self
->write_wait
, &wait
);
262 DEBUG( irlpt_common_debug
, __FUNCTION__
263 ":count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
264 count
, self
->irlap_data_size
, IRLPT_MAX_HEADER
);
266 if (count
> (self
->irlap_data_size
- IRLPT_MAX_HEADER
)) {
267 count
= (self
->irlap_data_size
- IRLPT_MAX_HEADER
);
268 DEBUG(irlpt_common_debug
, __FUNCTION__
269 ": setting count to %d\n", count
);
272 DEBUG( irlpt_common_debug
, __FUNCTION__
": count = %d\n", count
);
274 skb
= dev_alloc_skb(count
+ IRLPT_MAX_HEADER
);
276 printk( KERN_INFO __FUNCTION__
": couldn't allocate skbuff!\n");
281 * we use the unused stamp field to hold the device minor
282 * number, so we can look it up when the skb is destroyed.
284 *((__u32
*) &skb
->stamp
) = MINOR( file
->f_dentry
->d_inode
->i_rdev
);
286 skb_reserve( skb
, IRLPT_MAX_HEADER
);
287 skb_put( skb
, count
);
289 skb
->destructor
= irlpt_flow_control
;
292 copy_from_user( skb
->data
, buffer
, count
);
294 irlmp_data_request(self
->lsap
, skb
);
296 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
301 loff_t
irlpt_seek( struct file
*file
, loff_t offset
, int count
)
303 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
305 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
312 * Function irlpt_select (inode, filp, mode, table)
314 * Implementation for the select() call
317 int irlpt_select( struct inode
*inode
, struct file
*filp
, int mode
,
320 struct irlpt_cb
*self
;
322 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
324 self
= irlpt_find_handle(MINOR( inode
->i_rdev
));
326 ASSERT( self
!= NULL
, return -1;);
327 ASSERT( self
->magic
== IRLPT_MAGIC
, return -1;);
331 if ( skb_queue_len( &self
->rx_queue
))
332 return 1; /* Readable */
333 select_wait( &self
->read_wait
, table
);
336 if ( self
->connected
)
338 select_wait( &self
->write_wait
, table
);
341 if ( self
->connected
)
343 select_wait( &self
->ex_wait
, table
);
349 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
357 * Function irobex_poll (file, wait)
362 static u_int
irlpt_poll(struct file
*file
, poll_table
*wait
)
364 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
366 /* check out /usr/src/pcmcia/modules/ds.c for an example */
367 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
374 * Function open_irlpt (inode, file)
379 int irlpt_open(struct inode
*inode
, struct file
*file
)
381 struct irlpt_cb
*self
;
383 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
385 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
387 ASSERT( self
!= NULL
, return -1;);
388 ASSERT( self
->magic
== IRLPT_MAGIC
, return -1;);
391 if (self
->state
== IRLPT_IDLE
) {
392 DEBUG( irlpt_common_debug
, __FUNCTION__
393 ": state == IRLPT_IDLE! (no device found yet)\n");
397 if (self
->state
== IRLPT_QUERY
||
398 self
->state
== IRLPT_READY
||
399 self
->state
== IRLPT_WAITI
) {
400 DEBUG( irlpt_common_debug
, __FUNCTION__
": state == IRLPT_QUERY, "
401 "IRLPT_READY or IRLPT_WAITI (link problems)!\n");
407 DEBUG( irlpt_common_debug
, __FUNCTION__
408 ": count not zero; actual = %d\n", self
->count
);
413 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
419 * Function close_irlpt (inode, file)
424 int irlpt_close(struct inode
*inode
, struct file
*file
)
426 struct irlpt_cb
*self
;
428 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
430 self
= irlpt_find_handle(MINOR( file
->f_dentry
->d_inode
->i_rdev
));
432 DEBUG(irlpt_common_debug
, __FUNCTION__
": have handle!\n");
434 ASSERT( self
!= NULL
, return -1;);
435 ASSERT( self
->magic
== IRLPT_MAGIC
, return -1;);
437 DEBUG(irlpt_common_debug
, __FUNCTION__
": self->count=%d\n", self
->count
);
441 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
446 void irlpt_dump_buffer( struct sk_buff
*skb
)
450 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
452 for(i
=0;i
<skb
->len
;i
++)
453 if (skb
->data
[i
] > 31 && skb
->data
[i
] < 128) {
454 printk("%c", skb
->data
[i
]);
456 if (skb
->data
[i
] == 0x0d) {
465 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
468 void irlpt_flow_control(struct sk_buff
*skb
)
470 struct irlpt_cb
*self
;
472 DEBUG(irlpt_common_debug
, "--> " __FUNCTION__
"\n");
474 self
= irlpt_find_handle( *((__u32
*) &skb
->stamp
));
478 ASSERT(self
->pkt_count
>= 0, return;);
480 DEBUG(irlpt_common_debug
, __FUNCTION__
481 ": packet destroyed, count = %d\n", self
->pkt_count
);
483 wake_up_interruptible( &self
->write_wait
);
485 DEBUG(irlpt_common_debug
, __FUNCTION__
" -->\n");
491 * Function init_module (void)
493 * Initialize the module, this function is called by the
494 * modprobe(1) program.
496 int init_module(void)
502 * Function cleanup_module (void)
504 * Remove the module, this function is called by the rmmod(1)
507 void cleanup_module(void)