⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcan_fops_linux.c

📁 linux下的CAN BUS驱动代码。适合在arm平台使用。
💻 C
📖 第 1 页 / 共 2 页
字号:
//****************************************************************************// 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)//                Arno (a.vdlaan@hccnet.nl)//                John Privitera (JohnPrivitera@dciautomation.com)//****************************************************************************//****************************************************************************//// pcan_fops_linux.c - all file operation functions, exports only struct fops//// $Id: pcan_fops_linux.c $////****************************************************************************#define PCAN_OPEN_PATH_ARGS struct pcandev *dev#define PCAN_RELEASE_PATH_ARGS struct pcandev *dev#define REQ_IRQ_ARG dev#define WAIT_UNTIL_FIFO_EMPTY() wait_until_fifo_empty(dev, MAX_WAIT_UNTIL_CLOSE)//****************************************************************************// CODE//----------------------------------------------------------------------------// wait until write fifo is empty, max time in msecstatic void wait_until_fifo_empty(struct pcandev *dev, u32 mTime){  u32 dwStart = get_mtime();  while (!atomic_read(&dev->DataSendReady) && ((get_mtime() - dwStart) < mTime))    schedule();  // force it  atomic_set(&dev->DataSendReady, 1);}//----------------------------------------------------------------------------// is called when the path is openedstatic int pcan_open(struct inode *inode, struct file *filep){  struct pcandev *dev;  int err = 0;  struct fileobj *fobj = (struct fileobj *)NULL;  int _minor = minor(inode->i_rdev);  DPRINTK(KERN_DEBUG "%s: pcan_open(), minor = %d.\n", DEVICE_NAME, _minor);  dev = pcan_search_dev(_minor);  if (!dev)    return -ENODEV;  // create file object  fobj = kmalloc(sizeof(struct fileobj), GFP_KERNEL);  if (!fobj)  {    DPRINTK(KERN_DEBUG "%s: can't allocate kernel memory!\n", DEVICE_NAME);    return -ENOMEM;  }  // fill file object and init read and write method buffers  fobj->dev = dev;  if (filep->f_mode & FMODE_READ)  {    fobj->nReadRest = 0;    fobj->nTotalReadCount = 0;    fobj->pcReadPointer = fobj->pcReadBuffer;  }  if (filep->f_mode & FMODE_WRITE)  {    fobj->nWriteCount = 0;    fobj->pcWritePointer = fobj->pcWriteBuffer;  }  filep->private_data = (void *)fobj;  err = pcan_open_path(dev);  if (err && fobj) /* oops */    kfree(fobj);  return err;}static int pcan_release(struct inode *inode, struct file *filep){  struct fileobj *fobj = (struct fileobj *)filep->private_data;  struct pcandev *dev;  DPRINTK(KERN_DEBUG "%s: pcan_release()\n", DEVICE_NAME);  // free the associated irq and allocated memory  if (fobj && fobj->dev)  {    dev = fobj->dev;    pcan_release_path(dev);    kfree(fobj);  }  return 0;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_READ_MSGstatic int pcan_ioctl_read(struct file *filep, struct pcandev *dev, TPCANRdMsg *usr){  int err = 0;  TPCANRdMsg msg;  // DPRINTK(KERN_DEBUG "%s: pcan_ioctl(PCAN_READ_MSG)\n", DEVICE_NAME);  // support nonblocking read if requested  if ((filep->f_flags & O_NONBLOCK) && (!pcan_fifo_empty(&dev->readFifo)))    return -EAGAIN;  // sleep until data are available  err = wait_event_interruptible(dev->read_queue, (pcan_fifo_empty(&dev->readFifo)));  if (err)    goto fail;  // if the device is plugged out  if (!dev->ucPhysicallyInstalled)    return -ENODEV;   // get data out of fifo  err = pcan_fifo_get(&dev->readFifo, (void *)&msg);  if (err){    goto fail;  }  if (copy_to_user(usr, &msg, sizeof(*usr)))    err = -EFAULT;  fail:  return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_WRITE_MSGstatic int pcan_ioctl_write(struct file *filep, struct pcandev *dev, TPCANMsg *usr){  int err = 0;  TPCANMsg msg;  // DPRINTK(KERN_DEBUG "%s: pcan_ioctl(PCAN_WRITE_MSG)\n", DEVICE_NAME);  // support nonblocking write if requested  if ((filep->f_flags & O_NONBLOCK) && (!pcan_fifo_near_full(&dev->writeFifo)) && (!atomic_read(&dev->DataSendReady)))    return -EAGAIN;  // sleep until space is available  err = wait_event_interruptible(dev->write_queue,             (pcan_fifo_near_full(&dev->writeFifo) || atomic_read(&dev->DataSendReady)));  if (err)    goto fail;  // if the device is plugged out  if (!dev->ucPhysicallyInstalled)    return -ENODEV;  // get from user space  if (copy_from_user(&msg, usr, sizeof(msg)))  {    err = -EFAULT;    goto fail;  }  // filter extended data if initialized to standard only  if (!(dev->bExtended) && ((msg.MSGTYPE & MSGTYPE_EXTENDED) || (msg.ID > 2047)))  {    err = -EINVAL;    goto fail;  }  // put data into fifo  err = pcan_fifo_put(&dev->writeFifo, &msg);  if (!err)  {    // push a new transmission trough ioctl() only if interrupt triggered push was stalled    mb();    if (atomic_read(&dev->DataSendReady))    {      atomic_set(&dev->DataSendReady, 0);      mb();      err = dev->device_write(dev);      if (err)        atomic_set(&dev->DataSendReady, 1);    }    else    {      // DPRINTK(KERN_DEBUG "%s: pushed %d items into Fifo\n", DEVICE_NAME, dev->writeFifo.nStored);    }  }  fail:  return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_GET_EXT_STATUS int pcan_ioctl_extended_status(struct pcandev *dev, TPEXTENDEDSTATUS *status){  int err = 0;  TPEXTENDEDSTATUS local;  DPRINTK(KERN_DEBUG "%s: pcan_ioctl(PCAN_GET_EXT_STATUS)\n", DEVICE_NAME);  local = pcan_ioctl_extended_status_common(dev);  if (copy_to_user(status, &local, sizeof(local)))  {    err = -EFAULT;    goto fail;  }  dev->wCANStatus = 0;  dev->nLastError = 0;  fail:  return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_GET_STATUSstatic int pcan_ioctl_status(struct pcandev *dev, TPSTATUS *status){  int err = 0;  TPSTATUS local;  DPRINTK(KERN_DEBUG "%s: pcan_ioctl(PCAN_GET_STATUS)\n", DEVICE_NAME);  local = pcan_ioctl_status_common(dev);  if (copy_to_user(status, &local, sizeof(local)))  {    err = -EFAULT;    goto fail;  }  dev->wCANStatus = 0;  dev->nLastError = 0;  fail:  return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_DIAGstatic int pcan_ioctl_diag(struct pcandev *dev, TPDIAG *diag){  int err = 0;  TPDIAG local;  DPRINTK(KERN_DEBUG "%s: pcan_ioctl(PCAN_DIAG)\n", DEVICE_NAME);  local = pcan_ioctl_diag_common(dev);  if (copy_to_user(diag, &local, sizeof(local)))    err = -EFAULT;  return err;}//----------------------------------------------------------------------------// is called at user ioctl() with cmd = PCAN_INIT static int pcan_ioctl_init(struct pcandev *dev, TPCANInit *Init){  int err = 0;  TPCANInit local;  DPRINTK(KERN_DEBUG "%s: pcan_ioctl(PCAN_INIT)\n", DEVICE_NAME);  if (copy_from_user(&local, Init, sizeof(local)))  {    err = -EFAULT;    goto fail;  }  // flush fifo contents  err = pcan_fifo_reset(&dev->writeFifo);  if (err)    goto fail;  err = pcan_fifo_reset(&dev->readFifo);  if (err)    goto fail;  // wait until fifo is empty or MAX_WAIT_UNTIL_CLOSE time is elapsed  wait_until_fifo_empty(dev, MAX_WAIT_UNTIL_CLOSE);  // release the device  dev->device_release(dev);  // init again  err = dev->device_open(dev, local.wBTR0BTR1, local.ucCANMsgType, local.ucListenOnly);  if (!err)  {    dev->wBTR0BTR1    = local.wBTR0BTR1;    dev->ucCANMsgType = local.ucCANMsgType;    dev->ucListenOnly = local.ucListenOnly;  }  fail:  return err;}//----------------------------------------------------------------------------// get BTR0BTR1 init valuesstatic int pcan_ioctl_BTR0BTR1(struct pcandev *dev, TPBTR0BTR1 *BTR0BTR1){  int err = 0;  TPBTR0BTR1 local;  DPRINTK(KERN_DEBUG "%s: pcan_ioctl(PCAN_BTR0BTR1)\n", DEVICE_NAME);  if (copy_from_user(&local, BTR0BTR1, sizeof(local)))  {    err = -EFAULT;    goto fail;  }  // this does not influence hardware settings, only BTR0BTR1 values are calculated  local.wBTR0BTR1 = sja1000_bitrate(local.dwBitRate);  if (!local.wBTR0BTR1)  {    err = -EFAULT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -