drivers/can_virtual_kernel/can_virtual_kernel.c
changeset 391 7802a7d5584f
child 631 08b6b903f84a
equal deleted inserted replaced
390:31dc4ec8710c 391:7802a7d5584f
       
     1 /*
       
     2 This file is part of CanFestival, a library implementing CanOpen Stack. 
       
     3 
       
     4 Copyright (C): Edouard TISSERANT and Francis DUPIN
       
     5 
       
     6 See COPYING file for copyrights details.
       
     7 
       
     8 This library is free software; you can redistribute it and/or
       
     9 modify it under the terms of the GNU Lesser General Public
       
    10 License as published by the Free Software Foundation; either
       
    11 version 2.1 of the License, or (at your option) any later version.
       
    12 
       
    13 This library is distributed in the hope that it will be useful,
       
    14 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16 Lesser General Public License for more details.
       
    17 
       
    18 You should have received a copy of the GNU Lesser General Public
       
    19 License along with this library; if not, write to the Free Software
       
    20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    21 */
       
    22 
       
    23 /*
       
    24 	Virtual CAN driver.
       
    25 
       
    26 	Modification of drivers/can_virtual/can_virtual.c:
       
    27 	Rewritten from user-space library to kernel-space module with exported symbols
       
    28 */
       
    29 
       
    30 #include <linux/module.h>
       
    31 #include <linux/err.h>
       
    32 #include <linux/kfifo.h>
       
    33 #include <linux/spinlock.h>
       
    34 #include <linux/sched.h>
       
    35 #include <linux/wait.h>
       
    36 #include <linux/string.h>
       
    37 
       
    38 #define NEED_PRINT_MESSAGE
       
    39 #include "can_driver.h"
       
    40 #include "def.h"
       
    41 
       
    42 MODULE_LICENSE("GPL");
       
    43 
       
    44 #define MAX_NB_CAN_PIPES 16
       
    45 
       
    46 typedef struct {
       
    47   char used;
       
    48   struct kfifo *pipe;
       
    49   spinlock_t lock;
       
    50   wait_queue_head_t w_queue;
       
    51 } CANPipe;
       
    52 
       
    53 CANPipe canpipes[MAX_NB_CAN_PIPES] = {{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},{0,},};
       
    54 
       
    55 
       
    56 /*********functions which permit to communicate with the board****************/
       
    57 UNS8 canReceive_driver(CAN_HANDLE fd0, Message *m)
       
    58 {
       
    59 	long ret = wait_event_interruptible (((CANPipe*)fd0)->w_queue,
       
    60 		kfifo_len (((CANPipe*)fd0)->pipe) >= sizeof(Message));
       
    61 
       
    62 	// interrupted by signal
       
    63 	if (ret == -ERESTARTSYS)
       
    64 		return 2;
       
    65 
       
    66 	if (kfifo_get (((CANPipe*)fd0)->pipe, (unsigned char *)m, sizeof(Message)) != sizeof(Message))
       
    67 	{
       
    68 		printk(KERN_NOTICE "can_virtual: error receiving data from kernel fifo.\n");
       
    69 		return 1;
       
    70 	}
       
    71 	
       
    72 	return 0;
       
    73 }
       
    74 
       
    75 UNS8 canSend_driver(CAN_HANDLE fd0, Message *m)
       
    76 {
       
    77 	int i;
       
    78 
       
    79 	printk(KERN_INFO "%x->[ ", (CANPipe*)fd0 - &canpipes[0]); 
       
    80 	for(i=0; i < MAX_NB_CAN_PIPES; i++)
       
    81 	{
       
    82 		if(canpipes[i].used && &canpipes[i] != (CANPipe*)fd0)
       
    83 		{
       
    84 			printk("%x ",i);	
       
    85 		}
       
    86 	}
       
    87 	printk(" ]");
       
    88 	print_message(m);
       
    89   
       
    90 	// send to all readers, except myself
       
    91 	for(i=0; i < MAX_NB_CAN_PIPES; i++)
       
    92 	{
       
    93 		if(canpipes[i].used && &canpipes[i] != (CANPipe*)fd0)
       
    94 		{
       
    95 			unsigned int len;
       
    96 			len = kfifo_put (canpipes[i].pipe, (unsigned char *)m, sizeof(Message));
       
    97 			if (len != sizeof(Message)) {
       
    98 				printk(KERN_NOTICE "can_virtual: error sending data to kernel fifo.\n");
       
    99 				return 1;
       
   100 			}
       
   101 
       
   102 			// wake up canReceive_driver()
       
   103 			wake_up_interruptible (&canpipes[i].w_queue);
       
   104 		}
       
   105 	}
       
   106 
       
   107 	return 0;
       
   108 }
       
   109 
       
   110 int TranslateBaudRate(char* optarg){
       
   111 	if(!strcmp( optarg, "1M")) return (int)1000;
       
   112 	if(!strcmp( optarg, "500K")) return (int)500;
       
   113 	if(!strcmp( optarg, "250K")) return (int)250;
       
   114 	if(!strcmp( optarg, "125K")) return (int)125;
       
   115 	if(!strcmp( optarg, "100K")) return (int)100;
       
   116 	if(!strcmp( optarg, "50K")) return (int)50;
       
   117 	if(!strcmp( optarg, "20K")) return (int)20;
       
   118 	if(!strcmp( optarg, "10K")) return (int)10;
       
   119 	if(!strcmp( optarg, "5K")) return (int)5;
       
   120 	if(!strcmp( optarg, "none")) return 0;
       
   121 	return 0x0000;
       
   122 }
       
   123 
       
   124 UNS8 canChangeBaudRate_driver( CAN_HANDLE fd0, char* baud)
       
   125 {
       
   126     printk("%x-> changing to baud rate %s[%d]\n", (CANPipe*)fd0 - &canpipes[0],baud,TranslateBaudRate(baud)); 
       
   127     return 0;
       
   128 }
       
   129 
       
   130 
       
   131 CAN_HANDLE canOpen_driver(s_BOARD *board)
       
   132 {
       
   133 	int i;
       
   134 	for(i=0; i < MAX_NB_CAN_PIPES; i++)
       
   135 	{
       
   136 		if(!canpipes[i].used)
       
   137 			break;
       
   138 	}
       
   139 	
       
   140 	// initialize CANPipe structure
       
   141 	init_waitqueue_head(&canpipes[i].w_queue);
       
   142 	canpipes[i].lock = SPIN_LOCK_UNLOCKED;
       
   143 	canpipes[i].pipe = kfifo_alloc (10*sizeof(Message), GFP_KERNEL, &canpipes[i].lock);
       
   144 
       
   145 	if (i==MAX_NB_CAN_PIPES || (PTR_ERR(canpipes[i].pipe) == -ENOMEM))
       
   146 	{
       
   147 		printk (KERN_NOTICE "can_virtual: error initializing driver.\n");
       
   148 		return (CAN_HANDLE)NULL;
       
   149 	}
       
   150 	
       
   151 	canpipes[i].used = 1;	
       
   152 	return (CAN_HANDLE) &canpipes[i];
       
   153 }
       
   154 
       
   155 int canClose_driver(CAN_HANDLE fd0)
       
   156 {
       
   157 	((CANPipe*)fd0)->used = 0;
       
   158 	kfifo_free (((CANPipe*)fd0)->pipe);
       
   159 	
       
   160 	return 0;
       
   161 }
       
   162 
       
   163 EXPORT_SYMBOL(canOpen_driver);
       
   164 EXPORT_SYMBOL(canClose_driver);
       
   165 EXPORT_SYMBOL(canSend_driver);
       
   166 EXPORT_SYMBOL(canReceive_driver);
       
   167 EXPORT_SYMBOL(canChangeBaudRate_driver);