📄 pcan_main.c
字号:
//****************************************************************************// Copyright (C) 2001-2007 PEAK System-Technik GmbH//// linux@peak-system.com// www.peak-system.com//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)//// Major contributions by:// Edouard Tisserant (edouard.tisserant@lolitech.fr) XENOMAI// Laurent Bessard (laurent.bessard@lolitech.fr) XENOMAI// Oliver Hartkopp (oliver.hartkopp@volkswagen.de) socketCAN// // Contributions: Marcel Offermans (marcel.offermans@luminis.nl)// Philipp Baer (philipp.baer@informatik.uni-ulm.de)// Garth Zeglin (garthz@ri.cmu.edu)// Harald Koenig (H.Koenig@science-computing.de)//****************************************************************************//****************************************************************************//// pcan_main.c - the starting point of the driver,// init and cleanup and proc interface//// $Id: pcan_main.c 526 2007-10-29 21:42:02Z khitschler $////****************************************************************************//****************************************************************************// INCLUDES#include <src/pcan_common.h> // must always be the 1st include#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)#include <linux/config.h>#else#include <linux/autoconf.h>#endif// #define KBUILD_MODNAME pcan#include <linux/module.h>#include <linux/kernel.h> // DPRINTK()#include <linux/slab.h> // kmalloc()#include <linux/fs.h> // everything...#include <linux/errno.h> // error codes#include <linux/types.h> // size_t#include <linux/proc_fs.h> // proc#include <linux/fcntl.h> // O_ACCMODE#include <linux/capability.h> // all about restrictions#include <linux/param.h> // because of HZ#include <asm/system.h> // cli(), *_flags#include <asm/uaccess.h> // copy_...#include <src/pcan_main.h>#ifdef PCI_SUPPORT#include <src/pcan_pci.h> // get support for PCAN-PCI#endif#ifdef ISA_SUPPORT#include <src/pcan_isa.h> // get support for PCAN-ISA and PCAN-104#endif#ifdef DONGLE_SUPPORT#include <src/pcan_dongle.h> // get support for PCAN-Dongle#endif#ifdef USB_SUPPORT#include <src/pcan_usb.h> // get support for PCAN-USB#endif#ifdef PCCARD_SUPPORT#include <src/pcan_pccard.h>#endif#ifdef NETDEV_SUPPORT#include <src/pcan_netdev.h>#endif#include <src/pcan_fops.h>#include <src/pcan_fifo.h>#include <src/pcan_filter.h>//****************************************************************************// DEFINES#define DEFAULT_BTR0BTR1 CAN_BAUD_500K // defaults to 500 kbit/sec#define DEFAULT_EXTENDED 1 // catch all frames#define DEFAULT_LISTENONLY 0//****************************************************************************// GLOBALS// filled by module initialisationchar *type[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};u16 io[8] = {0, 0, 0, 0, 0, 0, 0, 0};u8 irq[8] = {0, 0, 0, 0, 0, 0, 0, 0};u16 bitrate = DEFAULT_BTR0BTR1;char *assign = NULL;//----------------------------------------------------------------------------// the global driver object, create itstruct driverobj pcan_drv = {};#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)//----------------------------------------------------------------------------// some stuff to support SysFS coming with kernel 2.6#include <linux/device.h>// not yet implemented#endif// build current driver config string for output in kernel log and procfsconst char current_config[] = " "#ifdef DEBUG"[dbg] "#endif#ifdef MODVERSIONS"[mod] "#endif#ifdef ISA_SUPPORT"[isa] "#endif#ifdef PCI_SUPPORT"[pci] "#endif#ifdef DONGLE_SUPPORT"[dng] "#endif#ifdef PARPORT_SUBSYSTEM"[par] "#endif#ifdef USB_SUPPORT"[usb] "#endif#ifdef PCCARD_SUPPORT"[pcc] "#endif#ifdef NETDEV_SUPPORT"[net] "#endif#ifndef NO_RT"[rt] "#endif;// for procfs output the current_config is copied into this string (centered!)char config[] = "*----------------------------------------------------------------------------";//****************************************************************************// LOCALS//****************************************************************************// CODE#ifdef NO_RT #include "pcan_main_linux.c"#else #include "pcan_main_rt.c"#endif//****************************************************************************// debug utilityvoid buffer_dump(u8 *pucBuffer, u16 wLineCount){ #ifdef DEBUG int i, j; for (i = 0; i < wLineCount; i++) { printk(KERN_DEBUG "%s: %04x ", DEVICE_NAME, i * 16); for (j = 0; j < 8; j++) printk(" %02x", *pucBuffer++); printk(" "); for (j = 0; j < 8; j++) printk(" %02x", *pucBuffer++); printk("\n"); } #endif}//----------------------------------------------------------------------------// convert struct can_frame to struct TPCANMsg// To reduce the complexity (and CPU usage) there are no checks (e.g. for dlc)// here as it is assumed that the creator of the source struct has done this workvoid frame2msg(struct can_frame *cf, TPCANMsg *msg){ if (cf->can_id & CAN_ERR_FLAG) { memset(msg, 0, sizeof(*msg)); msg->MSGTYPE = MSGTYPE_STATUS; msg->LEN = 4; if (cf->can_id & CAN_ERR_CRTL) { // handle data overrun if (cf->data[1] & CAN_ERR_CRTL_RX_OVERFLOW) msg->DATA[3] |= CAN_ERR_OVERRUN; // handle CAN_ERR_BUSHEAVY if (cf->data[1] & CAN_ERR_CRTL_RX_WARNING) msg->DATA[3] |= CAN_ERR_BUSHEAVY; } if (cf->can_id & CAN_ERR_BUSOFF_NETDEV) msg->DATA[3] |= CAN_ERR_BUSOFF; return; } if (cf->can_id & CAN_RTR_FLAG) msg->MSGTYPE = MSGTYPE_RTR; else msg->MSGTYPE = MSGTYPE_STANDARD; if (cf->can_id & CAN_EFF_FLAG) msg->MSGTYPE |= MSGTYPE_EXTENDED; msg->ID = cf->can_id & CAN_EFF_MASK; /* remove EFF/RTR/ERR flags */ msg->LEN = cf->can_dlc; /* no need to check value range here */ memcpy(&msg->DATA[0], &cf->data[0], 8); /* also copy trailing zeros */}//----------------------------------------------------------------------------// convert struct TPCANMsg to struct can_frame// To reduce the complexity (and CPU usage) there are no checks (e.g. for dlc)// here as it is assumed that the creator of the source struct has done this workvoid msg2frame(struct can_frame *cf, TPCANMsg *msg){ cf->can_id = msg->ID; if (msg->MSGTYPE & MSGTYPE_RTR) cf->can_id |= CAN_RTR_FLAG; if (msg->MSGTYPE & MSGTYPE_EXTENDED) cf->can_id |= CAN_EFF_FLAG; // if (msg->MSGTYPE & MSGTYPE_??????) // cf->can_id |= CAN_ERR_FLAG; cf->can_dlc = msg->LEN; /* no need to check value range here */ memcpy(&cf->data[0], &msg->DATA[0], 8); /* also copy trailing zeros */}//----------------------------------------------------------------------------// request time in msec, fastu32 get_mtime(void){ return (jiffies / HZ) * 1000;}// x = (x >= y) ? x - y : 0;static void subtract_timeval(struct timeval *x, struct timeval *y){ if (x->tv_usec >= y->tv_usec) x->tv_usec -= y->tv_usec; else { if (x->tv_sec) { x->tv_sec--; x->tv_usec += (1000000 - y->tv_usec); } else goto fail; } if (x->tv_sec >= y->tv_sec) { x->tv_sec -= y->tv_sec; return; } fail: x->tv_sec = x->tv_usec = 0;} // get relative time to start of drivervoid get_relative_time(struct timeval *tv, struct timeval *tr){ if (!tv) DO_GETTIMEOFDAY((*tr)); else memcpy(tr, tv, sizeof(*tr)); subtract_timeval(tr, &pcan_drv.sInitTime);}// convert timeval to pcan used milliseconds / microseconds notationvoid timeval2pcan(struct timeval *tv, u32 *msecs, u16 *usecs){ *msecs = (u32)(tv->tv_sec * 1000 + tv->tv_usec / 1000); *usecs = (u16)(tv->tv_usec % 1000); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -