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

📄 pcan_usb.c

📁 CAN 驱动编程
💻 C
📖 第 1 页 / 共 2 页
字号:
//****************************************************************************// Copyright (C) 2001,2002,2003  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)//****************************************************************************//****************************************************************************//// pcan_usb.c - the outer usb parts for pcan-usb support//// $Log: pcan_usb.c,v $// Revision 1.2  2003/03/02 10:46:31  klaus// merged USB thread into main path//// Revision 1.1.2.36  2003/02/25 20:23:37  klaus// moved pcan_usb_start() from pcan_open() to pcan_device_open()//// Revision 1.1.2.35  2003/02/24 19:12:43  klaus// added debug message at 'while .. schedule()'//// Revision 1.1.2.34  2003/02/23 19:33:06  klaus// tried to fix "not possible to stop" bug//// Revision 1.1.2.33  2003/02/16 19:55:52  klaus// USB Integration, first non public release//// Revision 1.1.2.32  2003/02/16 16:36:16  klaus// pcan_usb_kernel.c returned to main modules//// Revision 1.1.2.31  2003/02/09 13:18:09  klaus// modifications to support linux 2.2.19 kernels//// Revision 1.1.2.30  2003/02/09 13:18:09  klaus// modifications to support linux 2.2.19 kernels//// Revision 1.1.2.29  2003/02/09 10:29:20  klaus// code cleanup, Release_20030208_x//// Revision 1.1.2.28  2003/02/08 19:33:48  klaus// cosmetic changes//// Revision 1.1.2.27  2003/02/08 17:32:43  klaus// modified to use pcan_usb_kernel as prorietary module//// Revision 1.1.2.26  2003/02/05 23:12:19  klaus// adapted to RedHat 7.2//// Revision 1.1.2.25  2003/01/29 20:34:20  klaus// release_20030129_a and release_20030129_u released////****************************************************************************//****************************************************************************// INCLUDES#include <src/pcan_common.h>     // must always be the 1st include#include <linux/stddef.h>        // NULL#include <linux/errno.h>#include <linux/slab.h>          // kmalloc()#ifndef LINUX_22#include <linux/module.h>        // MODULE_DEVICE_TABLE()#endif#include <linux/usb.h>#include <src/pcan_usb.h>#include <src/pcan_usb_kernel.h>//****************************************************************************// DEFINES#define PCAN_USB_MINOR_BASE 32           // starting point of minors for USB devices#define PCAN_USB_VENDOR_ID  0x0c72#define PCAN_USB_PRODUCT_ID 0x000c#define URB_READ_BUFFER_SIZE      1024   // buffer for read URB data (IN)#define URB_READ_BUFFER_SIZE_OLD    64   // used length for revision < 6//****************************************************************************// GLOBALS#ifndef LINUX_22static struct usb_device_id pcan_usb_ids[] ={	{ USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USB_PRODUCT_ID) },	{ }						// Terminating entry};MODULE_DEVICE_TABLE (usb, pcan_usb_ids);#endif//****************************************************************************// LOCALSstatic u16 usb_devices = 0;        // the number of accepted usb_devices//****************************************************************************// CODE//****************************************************************************// get cyclic data from endpoint 2static void pcan_usb_write_notify(purb_t purb);static int pcan_usb_write(struct pcandev *dev){  int err = 0;  USB_PORT *u = &dev->port.usb;  int nDataLength = u->Endpoint[3].wDataSz;  DPRINTK(KERN_DEBUG "%s: pcan_usb_write()\n", DEVICE_NAME);  // don't do anything with non-existent hardware  if (!dev->ucPhysicallyInstalled)    return -ENODEV;  err = pcan_hw_Y(dev, u->pucWriteBuffer, &nDataLength);  // fill the URB and submit  if (nDataLength)  {    FILL_BULK_URB(u->write_data, u->usb_dev,                  usb_sndbulkpipe(u->usb_dev, u->Endpoint[3].ucNumber),                  u->pucWriteBuffer, nDataLength, pcan_usb_write_notify, dev);    // start next urb    if ((err = usb_submit_urb(u->write_data)))    {      dev->nLastError = err;      dev->dwErrorCounter++;       DPRINTK(KERN_ERR "%s: pcan_usb_write() can't submit! (%d)",DEVICE_NAME, err);    }    else      atomic_add(1, &dev->port.usb.active_urbs);  }  // it's no error if I can't get more data but still a packet was sent  if ((err == -ENODATA) && (nDataLength))    err = 0;  return err;}//****************************************************************************// notify functions for read and write datastatic void pcan_usb_write_notify(purb_t purb){  int err     = 0;  u16 wwakeup = 0;	struct pcandev *dev = purb->context;  // DPRINTK(KERN_DEBUG "%s: pcan_usb_write_notify() (%d)\n", DEVICE_NAME, purb->status);  // un-register outstanding urb  atomic_sub(1, &dev->port.usb.active_urbs);  // don't count interrupts - count packets  dev->dwInterruptCounter++;                                  // do write  if (!purb->status) // stop with first error    err = pcan_usb_write(dev);  if (err == -ENODATA)    wwakeup++;  else  {    dev->nLastError = err;    dev->dwErrorCounter++;     dev->wCANStatus |= CAN_ERR_QXMTFULL; // fatal error!  }  if (wwakeup)  {    atomic_set(&dev->DataSendReady, 1); // signal to write I'm ready    wake_up_interruptible(&dev->write_queue);  }}static void pcan_usb_read_notify(purb_t purb){  int err = 0;	struct pcandev *dev = purb->context;  USB_PORT *u = &dev->port.usb;  // DPRINTK(KERN_DEBUG "%s: pcan_usb_read_notify() (%d)\n", DEVICE_NAME, purb->status);  // un-register outstanding urb  atomic_sub(1, &dev->port.usb.active_urbs);  // don't count interrupts - count packets  dev->dwInterruptCounter++;                                  // do interleaving read  if (!purb->status && dev->ucPhysicallyInstalled) // stop with first error  {    u8  *m_pucTransferBuffer = purb->transfer_buffer;    int m_nCurrentLength     = purb->actual_length;    // buffer interleave to increase speed    if (m_pucTransferBuffer == u->pucReadBuffer[0])    {      FILL_BULK_URB(purb, u->usb_dev,                    usb_rcvbulkpipe(u->usb_dev, u->Endpoint[2].ucNumber),                    u->pucReadBuffer[1], u->wReadBufferLength, pcan_usb_read_notify, dev);    }    else    {      FILL_BULK_URB(purb, u->usb_dev,                    usb_rcvbulkpipe(u->usb_dev, u->Endpoint[2].ucNumber),                    u->pucReadBuffer[0], u->wReadBufferLength, pcan_usb_read_notify, dev);    }    // start next urb    if ((err = usb_submit_urb(purb)))    {      dev->nLastError = err;       dev->dwErrorCounter++;      printk(KERN_ERR "%s: pcan_usb_read_notify() can't submit! (%d)",DEVICE_NAME, err);    }    else      atomic_add(1, &dev->port.usb.active_urbs);    err = pcan_hw_X(dev, m_pucTransferBuffer, m_nCurrentLength);    if (err)    {      dev->nLastError = err;       dev->wCANStatus |=  CAN_ERR_QOVERRUN;      dev->dwErrorCounter++;      DPRINTK(KERN_DEBUG "%s: error %d from hw_DecodeMessage()\n", DEVICE_NAME, err);    }  }  else  {    printk(KERN_ERR "%s: read data stream torn off caused by ", DEVICE_NAME);    if (!dev->ucPhysicallyInstalled)      printk("device plug out!\n");    else      printk("err %d!\n", purb->status);  }}//****************************************************************************// usb resource allocation //static int pcan_usb_allocate_resources(struct pcandev *dev){  int err = 0;  USB_PORT *u = &dev->port.usb;  DPRINTK(KERN_DEBUG "%s: pcan_usb_allocate_resources()\n", DEVICE_NAME);  // allocate X data for comparison  if (!u->pvXptr)  {    if (!(u->pvXptr = kmalloc(pcan_X(), GFP_KERNEL)))    {      err = -ENOMEM;      goto fail;    }  }  dev->wInitStep = 4;  // make param URB  u->param_urb = usb_alloc_urb(0);  if (!u->param_urb)    err = -ENOMEM;  dev->wInitStep = 5;  // allocate write buffer  u->pucWriteBuffer =  kmalloc(u->Endpoint[3].wDataSz, GFP_KERNEL);  DPRINTK(KERN_DEBUG "%s: kmalloc() = %p\n", DEVICE_NAME, u->pucWriteBuffer);  if (!u->pucWriteBuffer)  {    err = -ENOMEM;    goto fail;  }  dev->wInitStep = 6;  // make write urb  u->write_data = usb_alloc_urb(0);  if (!u->write_data)  {    err = -ENOMEM;    goto fail;  }  dev->wInitStep = 7;  // reset telegram count  u->dwTelegramCount = 0;  // allocate both read buffers for URB  u->pucReadBuffer[0] =  kmalloc(URB_READ_BUFFER_SIZE * 2, GFP_KERNEL);  DPRINTK(KERN_DEBUG "%s: kmalloc() = %p\n", DEVICE_NAME, u->pucReadBuffer[0]);  if (!u->pucReadBuffer[0])  {    err = -ENOMEM;    goto fail;  }  u->pucReadBuffer[1] = u->pucReadBuffer[0] + URB_READ_BUFFER_SIZE;  dev->wInitStep = 8;  // make read urb  u->read_data = usb_alloc_urb(0);  if (!u->read_data)  {    err = -ENOMEM;    goto fail;  }  dev->wInitStep = 9;  // different revisions use different buffer sizes  if (u->ucRevision < 6)    u->wReadBufferLength = URB_READ_BUFFER_SIZE_OLD;  else    u->wReadBufferLength = URB_READ_BUFFER_SIZE;  fail:  return err;}//****************************************************************************// usb resource de-allocation //static int pcan_usb_free_resources(struct pcandev *dev){  int err = 0;  USB_PORT *u = &dev->port.usb;  DPRINTK(KERN_DEBUG "%s: pcan_usb_free_resources()\n", DEVICE_NAME);  // at this point no URB must be pending  // this is forced at pcan_usb_stop  switch (dev->wInitStep)  {    case 9:      // free read URB      usb_free_urb(u->read_data);    case 8:      kfree(u->pucReadBuffer[0]);    case 7:      // free write urb      usb_free_urb(u->write_data);    case 6:      kfree(u->pucWriteBuffer);    case 5:      // free param urb      usb_free_urb(u->param_urb);    case 4:      // remove X information      if (u->pvXptr)      {        kfree(u->pvXptr);        u->pvXptr = NULL;      }      dev->wInitStep = 3;  }  return err;}//****************************************************************************// start and stop functions for CAN data IN and OUTstatic int pcan_usb_start(struct pcandev *dev){  int err = 0;  USB_PORT *u = &dev->port.usb;  DPRINTK(KERN_DEBUG "%s: pcan_usb_start()\n", DEVICE_NAME);   FILL_BULK_URB(u->read_data, u->usb_dev,                usb_rcvbulkpipe(u->usb_dev, u->Endpoint[2].ucNumber),                u->pucReadBuffer[0], u->wReadBufferLength, pcan_usb_read_notify, dev);  // submit urb  if ((err = usb_submit_urb(u->read_data)))    printk(KERN_ERR "%s: pcan_usb_start() can't submit! (%d)\n",DEVICE_NAME, err);  else    atomic_add(1, &dev->port.usb.active_urbs);  return err;

⌨️ 快捷键说明

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