Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

irmod.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  *                
00003  * Filename:      irmod.c
00004  * Version:       0.8
00005  * Description:   IrDA module code and some other stuff
00006  * Status:        Experimental.
00007  * Author:        Dag Brattli <dagb@cs.uit.no>
00008  * Created at:    Mon Dec 15 13:55:39 1997
00009  * Modified at:   Mon Jan 17 11:21:56 2000
00010  * Modified by:   Dag Brattli <dagb@cs.uit.no>
00011  * 
00012  *     Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
00013  *      
00014  *     This program is free software; you can redistribute it and/or 
00015  *     modify it under the terms of the GNU General Public License as 
00016  *     published by the Free Software Foundation; either version 2 of 
00017  *     the License, or (at your option) any later version.
00018  *  
00019  *     Neither Dag Brattli nor University of Tromsų admit liability nor
00020  *     provide warranty for any of this software. This material is 
00021  *     provided "AS-IS" and at no charge.
00022  *     
00023  ********************************************************************/
00024 
00025 #include <linux/config.h>
00026 #include <linux/module.h> 
00027 
00028 #include <linux/init.h>
00029 #include <linux/poll.h>
00030 #include <linux/proc_fs.h>
00031 
00032 #include <asm/segment.h>
00033 
00034 #include <net/irda/irda.h>
00035 #include <net/irda/irmod.h>
00036 #include <net/irda/irlap.h>
00037 #ifdef CONFIG_IRDA_COMPRESSION
00038 #include <net/irda/irlap_comp.h>
00039 #endif /* CONFIG_IRDA_COMPRESSION */
00040 #include <net/irda/irlmp.h>
00041 #include <net/irda/iriap.h>
00042 #include <net/irda/irias_object.h>
00043 #include <net/irda/irttp.h>
00044 #include <net/irda/irda_device.h>
00045 #include <net/irda/wrapper.h>
00046 #include <net/irda/timer.h>
00047 #include <net/irda/parameters.h>
00048 
00049 extern struct proc_dir_entry *proc_irda;
00050 
00051 struct irda_cb irda; /* One global instance */
00052 
00053 #ifdef CONFIG_IRDA_DEBUG
00054 __u32 irda_debug = IRDA_DEBUG_LEVEL;
00055 #endif
00056 
00057 extern void irda_proc_register(void);
00058 extern void irda_proc_unregister(void);
00059 extern int  irda_sysctl_register(void);
00060 extern void irda_sysctl_unregister(void);
00061 
00062 extern void irda_proto_init(struct net_proto *pro);
00063 extern void irda_proto_cleanup(void);
00064 
00065 extern int irda_device_init(void);
00066 extern int irlan_init(void);
00067 extern int irlan_client_init(void);
00068 extern int irlan_server_init(void);
00069 extern int ircomm_init(void);
00070 extern int ircomm_tty_init(void);
00071 extern int irlpt_client_init(void);
00072 extern int irlpt_server_init(void);
00073 
00074 #ifdef CONFIG_IRDA_COMPRESSION
00075 #ifdef CONFIG_IRDA_DEFLATE
00076 extern irda_deflate_init(void);
00077 #endif /* CONFIG_IRDA_DEFLATE */
00078 #endif /* CONFIG_IRDA_COMPRESSION */
00079 
00080 static int irda_open(struct inode * inode, struct file *file);
00081 static int irda_ioctl(struct inode *inode, struct file *filp, 
00082                       unsigned int cmd, unsigned long arg);
00083 static int irda_close(struct inode *inode, struct file *file);
00084 static ssize_t irda_read(struct file *file, char *buffer, size_t count, 
00085                          loff_t *noidea);
00086 static ssize_t irda_write(struct file *file, const char *buffer,
00087                           size_t count, loff_t *noidea);
00088 static u_int irda_poll(struct file *file, poll_table *wait);
00089 
00090 static struct file_operations irda_fops = {
00091         NULL,          /* seek */
00092         irda_read,     /* read */
00093         irda_write,    /* write */
00094         NULL,          /* readdir */
00095         irda_poll,     /* poll */
00096         irda_ioctl,    /* ioctl */
00097         NULL,          /* mmap */
00098         irda_open,
00099         NULL,
00100         irda_close,
00101         NULL,
00102         NULL,          /* fasync */
00103 };
00104 
00105 /* IrTTP */
00106 EXPORT_SYMBOL(irttp_open_tsap);
00107 EXPORT_SYMBOL(irttp_close_tsap);
00108 EXPORT_SYMBOL(irttp_connect_response);
00109 EXPORT_SYMBOL(irttp_data_request);
00110 EXPORT_SYMBOL(irttp_disconnect_request);
00111 EXPORT_SYMBOL(irttp_flow_request);
00112 EXPORT_SYMBOL(irttp_connect_request);
00113 EXPORT_SYMBOL(irttp_udata_request);
00114 EXPORT_SYMBOL(irttp_dup);
00115 
00116 /* Main IrDA module */
00117 #ifdef CONFIG_IRDA_DEBUG
00118 EXPORT_SYMBOL(irda_debug);
00119 #endif
00120 EXPORT_SYMBOL(irda_notify_init);
00121 EXPORT_SYMBOL(irmanager_notify);
00122 EXPORT_SYMBOL(irda_lock);
00123 #ifdef CONFIG_PROC_FS
00124 EXPORT_SYMBOL(proc_irda);
00125 #endif
00126 EXPORT_SYMBOL(irda_param_insert);
00127 EXPORT_SYMBOL(irda_param_extract);
00128 EXPORT_SYMBOL(irda_param_extract_all);
00129 EXPORT_SYMBOL(irda_param_pack);
00130 EXPORT_SYMBOL(irda_param_unpack);
00131 
00132 /* IrIAP/IrIAS */
00133 EXPORT_SYMBOL(iriap_open);
00134 EXPORT_SYMBOL(iriap_close);
00135 EXPORT_SYMBOL(iriap_getvaluebyclass_request);
00136 EXPORT_SYMBOL(irias_object_change_attribute);
00137 EXPORT_SYMBOL(irias_add_integer_attrib);
00138 EXPORT_SYMBOL(irias_add_octseq_attrib);
00139 EXPORT_SYMBOL(irias_add_string_attrib);
00140 EXPORT_SYMBOL(irias_insert_object);
00141 EXPORT_SYMBOL(irias_new_object);
00142 EXPORT_SYMBOL(irias_delete_object);
00143 EXPORT_SYMBOL(irias_delete_value);
00144 EXPORT_SYMBOL(irias_find_object);
00145 EXPORT_SYMBOL(irias_find_attrib);
00146 EXPORT_SYMBOL(irias_new_integer_value);
00147 EXPORT_SYMBOL(irias_new_string_value);
00148 EXPORT_SYMBOL(irias_new_octseq_value);
00149 
00150 /* IrLMP */
00151 EXPORT_SYMBOL(irlmp_discovery_request);
00152 EXPORT_SYMBOL(irlmp_register_client);
00153 EXPORT_SYMBOL(irlmp_unregister_client);
00154 EXPORT_SYMBOL(irlmp_update_client);
00155 EXPORT_SYMBOL(irlmp_register_service);
00156 EXPORT_SYMBOL(irlmp_unregister_service);
00157 EXPORT_SYMBOL(irlmp_service_to_hint);
00158 EXPORT_SYMBOL(irlmp_data_request);
00159 EXPORT_SYMBOL(irlmp_open_lsap);
00160 EXPORT_SYMBOL(irlmp_close_lsap);
00161 EXPORT_SYMBOL(irlmp_connect_request);
00162 EXPORT_SYMBOL(irlmp_connect_response);
00163 EXPORT_SYMBOL(irlmp_disconnect_request);
00164 EXPORT_SYMBOL(irlmp_get_daddr);
00165 EXPORT_SYMBOL(irlmp_get_saddr);
00166 EXPORT_SYMBOL(irlmp_dup);
00167 EXPORT_SYMBOL(lmp_reasons);
00168 
00169 /* Queue */
00170 EXPORT_SYMBOL(hashbin_find);
00171 EXPORT_SYMBOL(hashbin_new);
00172 EXPORT_SYMBOL(hashbin_insert);
00173 EXPORT_SYMBOL(hashbin_delete);
00174 EXPORT_SYMBOL(hashbin_remove);
00175 EXPORT_SYMBOL(hashbin_get_next);
00176 EXPORT_SYMBOL(hashbin_get_first);
00177 
00178 /* IrLAP */
00179 EXPORT_SYMBOL(irlap_open);
00180 EXPORT_SYMBOL(irlap_close);
00181 #ifdef CONFIG_IRDA_COMPRESSION
00182 EXPORT_SYMBOL(irda_unregister_compressor);
00183 EXPORT_SYMBOL(irda_register_compressor);
00184 #endif /* CONFIG_IRDA_COMPRESSION */
00185 EXPORT_SYMBOL(irda_init_max_qos_capabilies);
00186 EXPORT_SYMBOL(irda_qos_bits_to_value);
00187 EXPORT_SYMBOL(irda_device_setup);
00188 EXPORT_SYMBOL(irda_device_set_media_busy);
00189 EXPORT_SYMBOL(irda_device_txqueue_empty);
00190 
00191 EXPORT_SYMBOL(irda_device_dongle_init);
00192 EXPORT_SYMBOL(irda_device_dongle_cleanup);
00193 EXPORT_SYMBOL(irda_device_register_dongle);
00194 EXPORT_SYMBOL(irda_device_unregister_dongle);
00195 EXPORT_SYMBOL(irda_task_execute);
00196 EXPORT_SYMBOL(irda_task_kick);
00197 EXPORT_SYMBOL(irda_task_next_state);
00198 EXPORT_SYMBOL(irda_task_delete);
00199 
00200 EXPORT_SYMBOL(async_wrap_skb);
00201 EXPORT_SYMBOL(async_unwrap_char);
00202 EXPORT_SYMBOL(irda_start_timer);
00203 EXPORT_SYMBOL(setup_dma);
00204 EXPORT_SYMBOL(infrared_mode);
00205 
00206 #ifdef CONFIG_IRTTY
00207 EXPORT_SYMBOL(irtty_set_dtr_rts);
00208 EXPORT_SYMBOL(irtty_register_dongle);
00209 EXPORT_SYMBOL(irtty_unregister_dongle);
00210 EXPORT_SYMBOL(irtty_set_packet_mode);
00211 #endif
00212 
00213 int __init irda_init(void)
00214 {
00215         MESSAGE("IrDA (tm) Protocols for Linux-2.2 (Dag Brattli)\n");
00216         
00217         irlmp_init();
00218         irlap_init();
00219         
00220 #ifdef MODULE
00221         irda_device_init();     /* Called by init/main.c when non-modular */
00222 #endif
00223         iriap_init();
00224         irttp_init();
00225         
00226 #ifdef CONFIG_PROC_FS
00227         irda_proc_register();
00228 #endif
00229 #ifdef CONFIG_SYSCTL
00230         irda_sysctl_register();
00231 #endif
00232         irda.dev.minor = MISC_DYNAMIC_MINOR;
00233         irda.dev.name = "irda";
00234         irda.dev.fops = &irda_fops;
00235         
00236         misc_register(&irda.dev);
00237 
00238         irda.in_use = FALSE;
00239 
00240         /* 
00241          * Initialize modules that got compiled into the kernel 
00242          */
00243 #ifdef CONFIG_IRLAN
00244         irlan_init();
00245 #endif
00246 #ifdef CONFIG_IRCOMM
00247         ircomm_init();
00248         ircomm_tty_init();
00249 #endif
00250 
00251 #ifdef CONFIG_IRDA_COMPRESSION
00252 #ifdef CONFIG_IRDA_DEFLATE
00253         irda_deflate_init();
00254 #endif /* CONFIG_IRDA_DEFLATE */
00255 #endif /* CONFIG_IRDA_COMPRESSION */
00256 
00257         return 0;
00258 }
00259 
00260 #ifdef MODULE
00261 void irda_cleanup(void)
00262 {
00263         misc_deregister(&irda.dev);
00264 
00265 #ifdef CONFIG_SYSCTL
00266         irda_sysctl_unregister();
00267 #endif  
00268 
00269 #ifdef CONFIG_PROC_FS
00270         irda_proc_unregister();
00271 #endif
00272         /* Remove higher layers */
00273         irttp_cleanup();
00274         iriap_cleanup();
00275 
00276         /* Remove lower layers */
00277         irda_device_cleanup();
00278         irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */
00279 
00280         /* Remove middle layer */
00281         irlmp_cleanup();
00282 }
00283 #endif /* MODULE */
00284 
00285 /*
00286  * Function irda_unlock (lock)
00287  *
00288  *    Unlock variable. Returns false if lock is already unlocked
00289  *
00290  */
00291 inline int irda_unlock(int *lock) 
00292 {
00293         if (!test_and_clear_bit(0, (void *) lock))  {
00294                 printk("Trying to unlock already unlocked variable!\n");
00295                 return FALSE;
00296         }
00297         return TRUE;
00298 }
00299 
00300 /*
00301  * Function irda_notify_init (notify)
00302  *
00303  *    Used for initializing the notify structure
00304  *
00305  */
00306 void irda_notify_init(notify_t *notify)
00307 {
00308         notify->data_indication = NULL;
00309         notify->udata_indication = NULL;
00310         notify->connect_confirm = NULL;
00311         notify->connect_indication = NULL;
00312         notify->disconnect_indication = NULL;
00313         notify->flow_indication = NULL;
00314         notify->instance = NULL;
00315         strncpy(notify->name, "Unknown", NOTIFY_MAX_NAME);
00316 }
00317 
00318 /*
00319  * Function irda_execute_as_process (self, callback, param)
00320  *
00321  *    If a layer needs to have a function executed with a process context,
00322  *    then it can register the function here, and the function will then 
00323  *    be executed as fast as possible.
00324  *
00325  */
00326 void irda_execute_as_process( void *self, TODO_CALLBACK callback, __u32 param)
00327 {
00328         struct irda_todo *new;
00329         struct irmanager_event event;
00330 
00331         /* Make sure irmanager is running */
00332         if (!irda.in_use)
00333                 return;
00334 
00335         /* Make new todo event */
00336         new = (struct irda_todo *) kmalloc( sizeof(struct irda_todo),
00337                                             GFP_ATOMIC);
00338         if ( new == NULL) {
00339                 return;
00340         }
00341         memset( new, 0, sizeof( struct irda_todo));
00342 
00343         new->self = self;
00344         new->callback = callback;
00345         new->param = param;
00346         
00347         /* Queue todo */
00348         enqueue_last(&irda.todo_queue, (queue_t *) new);
00349 
00350         event.event = EVENT_NEED_PROCESS_CONTEXT;
00351 
00352         /* Notify the user space manager */
00353         irmanager_notify(&event);
00354 }
00355 
00356 /*
00357  * Function irmanger_notify (event)
00358  *
00359  *    Send an event to the user space manager
00360  *
00361  */
00362 void irmanager_notify( struct irmanager_event *event)
00363 {
00364         struct irda_event *new;
00365         
00366         IRDA_DEBUG(4, __FUNCTION__ "()\n");
00367         
00368         /* Make sure irmanager is running */
00369         if (!irda.in_use)
00370                 return;
00371 
00372         /* Make new IrDA Event */
00373         new = (struct irda_event *) kmalloc( sizeof(struct irda_event),
00374                                              GFP_ATOMIC);
00375         if ( new == NULL) {
00376                 return; 
00377         }
00378         memset(new, 0, sizeof( struct irda_event));
00379         new->event = *event;
00380         
00381         /* Queue event */
00382         enqueue_last(&irda.event_queue, (queue_t *) new);
00383         
00384         /* Wake up irmanager sleeping on read */
00385         wake_up_interruptible(&irda.wait_queue);
00386 }
00387 
00388 static int irda_open( struct inode * inode, struct file *file)
00389 {
00390         IRDA_DEBUG( 4, __FUNCTION__ "()\n");
00391 
00392         if (irda.in_use) {
00393                 IRDA_DEBUG(0, __FUNCTION__ 
00394                            "(), irmanager is already running!\n");
00395                 return -1;
00396         }
00397         irda.in_use = TRUE;
00398                 
00399         MOD_INC_USE_COUNT;
00400         
00401         return 0;
00402 }
00403 
00404 /*
00405  * Function irda_ioctl (inode, filp, cmd, arg)
00406  *
00407  *    Ioctl, used by irmanager to ...
00408  *
00409  */
00410 static int irda_ioctl(struct inode *inode, struct file *filp, 
00411                       unsigned int cmd, unsigned long arg)
00412 {
00413         struct irda_todo *todo;
00414         int err = 0;
00415         int size = _IOC_SIZE(cmd);
00416         
00417         IRDA_DEBUG(4, __FUNCTION__ "()\n");
00418         
00419         if (_IOC_DIR(cmd) & _IOC_READ)
00420                 err = verify_area( VERIFY_WRITE, (void *) arg, size);
00421         else if (_IOC_DIR(cmd) & _IOC_WRITE)
00422                 err = verify_area( VERIFY_READ, (void *) arg, size);
00423         if (err)
00424                 return err;
00425         
00426         switch (cmd) {
00427         case IRMGR_IOCTNPC:
00428                 /* Got process context! */
00429                 IRDA_DEBUG(4, __FUNCTION__ "(), got process context!\n");
00430                 
00431                 while ((todo = (struct irda_todo *) dequeue_first( 
00432                         &irda.todo_queue)) != NULL)
00433                 {
00434                         todo->callback(todo->self, todo->param);
00435 
00436                         kfree(todo);
00437                 }
00438                 break;
00439 
00440         default:
00441                 return -ENOIOCTLCMD;
00442         }
00443         
00444         return 0;
00445 }
00446 
00447 static int irda_close(struct inode *inode, struct file *file)
00448 {
00449         IRDA_DEBUG(4, __FUNCTION__ "()\n");
00450         
00451         MOD_DEC_USE_COUNT;
00452         
00453         irda.in_use = FALSE;
00454 
00455         return 0;
00456 }
00457 
00458 static ssize_t irda_read(struct file *file, char *buffer, size_t count, 
00459                          loff_t *noidea)
00460 {
00461         struct irda_event *event;
00462         unsigned long flags;
00463         int len;
00464 
00465         IRDA_DEBUG(4, __FUNCTION__ "()\n");
00466 
00467         /* * Go to sleep and wait for event if there is no event to be read! */
00468         save_flags( flags);
00469         cli();
00470         if ( !irda.event_queue)
00471                 interruptible_sleep_on( &irda.wait_queue);
00472         restore_flags(flags);
00473         
00474         /*
00475          *  Ensure proper reaction to signals, and screen out 
00476          *  blocked signals (page 112. linux device drivers)
00477          */
00478         if (signal_pending( current))
00479                 return -ERESTARTSYS;
00480 
00481         event = (struct irda_event *) dequeue_first( &irda.event_queue);
00482         if (!event)
00483                 return 0;
00484 
00485         len = sizeof(struct irmanager_event);
00486         copy_to_user(buffer, &event->event, len);
00487 
00488         /* Finished with event */
00489         kfree(event);
00490 
00491         return len;
00492 }
00493 
00494 static ssize_t irda_write(struct file *file, const char *buffer,
00495                           size_t count, loff_t *noidea)
00496 {
00497         IRDA_DEBUG(0, __FUNCTION__ "()\n");
00498         
00499         return 0;
00500 }
00501 
00502 static u_int irda_poll(struct file *file, poll_table *wait)
00503 {
00504         IRDA_DEBUG(0, __FUNCTION__ "(), Sorry not implemented yet!\n");
00505 
00506         return 0;
00507 }
00508 
00509 void irda_mod_inc_use_count(void)
00510 {
00511 #ifdef MODULE
00512         MOD_INC_USE_COUNT;
00513 #endif
00514 }
00515 
00516 void irda_mod_dec_use_count(void)
00517 {
00518 #ifdef MODULE
00519         MOD_DEC_USE_COUNT;
00520 #endif
00521 }
00522 
00523 /*
00524  * Function irda_proc_modcount (inode, fill)
00525  *
00526  *    Use by the proc file system functions to prevent the irda module
00527  *    being removed while the use is standing in the net/irda directory
00528  */
00529 void irda_proc_modcount(struct inode *inode, int fill)
00530 {
00531 #ifdef MODULE
00532 #ifdef CONFIG_PROC_FS
00533         if (fill)
00534                 MOD_INC_USE_COUNT;
00535         else
00536                 MOD_DEC_USE_COUNT;
00537 #endif /* CONFIG_PROC_FS */
00538 #endif /* MODULE */
00539 }
00540 
00541 #ifdef MODULE
00542 
00543 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
00544 MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); 
00545 MODULE_PARM(irda_debug, "1l");
00546 
00547 /*
00548  * Function init_module (void)
00549  *
00550  *    Initialize the irda module
00551  *
00552  */
00553 int init_module(void) 
00554 {
00555         irda_proto_init(NULL);
00556 
00557         return 0;
00558 }
00559 
00560 /*
00561  * Function cleanup_module (void)
00562  *
00563  *    Cleanup the irda module
00564  *
00565  */
00566 void cleanup_module(void) 
00567 {
00568         irda_proto_cleanup();
00569 }
00570 #endif /* MODULE */