📄 skel.c
字号:
/* comedi/drivers/skel.c Skeleton code for a Comedi driver COMEDI - Linux Control and Measurement Device Interface Copyright (C) 2000 David A. Schleef <ds@schleef.org> 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.*//*Driver: skel.oDescription: Skeleton driver, an example for driver writersDevices:Author: dsUpdated: Mon, 18 Mar 2002 15:34:01 -0800Status: worksThis driver is a documented example on how Comedi drivers arewritten.Configuration Options: none*//* * The previous block comment is used to automatically generate * documentation in Comedi and Comedilib. The fields: * * Driver: the name of the driver * Description: a short phrase describing the driver. Don't list boards. * Devices: a full list of the boards that attempt to be supported by * the driver. Format is "(manufacturer) board name [comedi name]", * where comedi_name is the name that is used to configure the board. * See the comment near board_name: in the comedi_driver structure * below. If (manufacturer) or [comedi name] is missing, the previous * value is used. * Author: you * Updated: date when the _documentation_ was last updated. Use 'date -R' * to get a value for this. * Status: a one-word description of the status. Valid values are: * works - driver works correctly on most boards supported, and * passes comedi_test. * unknown - unknown. Usually put there by ds. * experimental - may not work in any particular release. Author * probably wants assistance testing it. * bitrotten - driver has not been update in a long time, probably * doesn't work, and probably is missing support for significant * Comedi interface features. * untested - author probably wrote it "blind", and is believed to * work, but no confirmation. * * These headers should be followed by a blank line, and any comments * you wish to say about the driver. The comment area is the place * to put any known bugs, limitations, unsupported features, supported * command triggers, whether or not commands are supported on particular * subdevices, etc. * * Somewhere in the comment should be information about configuration * options that are used with comedi_config. */#include <linux/comedidev.h>#include <linux/pci.h> /* for PCI devices *//* Imaginary registers for the imaginary board */#define SKEL_SIZE 0#define SKEL_START_AI_CONV 0#define SKEL_AI_READ 0/* * Board descriptions for two imaginary boards. Describing the * boards in this way is optional, and completely driver-dependent. * Some drivers use arrays such as this, other do not. */typedef struct skel_board_struct{ char *name; int ai_chans; int ai_bits; int have_dio;}skel_board;static skel_board skel_boards[] = { { name: "skel-100", ai_chans: 16, ai_bits: 12, have_dio: 1, }, { name: "skel-200", ai_chans: 8, ai_bits: 16, have_dio: 0, },};/* This is used by modprobe to translate PCI IDs to drivers. Should * only be used for PCI and ISA-PnP devices *//* Please add your PCI vendor ID to comedidev.h, and it will be forwarded * upstream. */#define PCI_VENDOR_ID_SKEL 0xdafestatic struct pci_device_id skel_pci_table[] __devinitdata = { { PCI_VENDOR_ID_SKEL, 0x0100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_SKEL, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0 }};MODULE_DEVICE_TABLE(pci, skel_pci_table);/* * Useful for shorthand access to the particular board structure */#define thisboard ((skel_board *)dev->board_ptr)/* this structure is for data unique to this hardware driver. If several hardware drivers keep similar information in this structure, feel free to suggest moving the variable to the comedi_device struct. */typedef struct{ int data; /* would be useful for a PCI device */ struct pci_dev *pci_dev; /* Used for AO readback */ lsampl_t ao_readback[2];}skel_private;/* * most drivers define the following macro to make it easy to * access the private structure. */#define devpriv ((skel_private *)dev->private)/* * The comedi_driver structure tells the Comedi core module * which functions to call to configure/deconfigure (attach/detach) * the board, and also about the kernel module that contains * the device code. */static int skel_attach(comedi_device *dev,comedi_devconfig *it);static int skel_detach(comedi_device *dev);static comedi_driver driver_skel={ driver_name: "dummy", module: THIS_MODULE, attach: skel_attach, detach: skel_detach,/* It is not necessary to implement the following members if you are * writing a driver for a ISA PnP or PCI card */ /* Most drivers will support multiple types of boards by * having an array of board structures. These were defined * in skel_boards[] above. Note that the element 'name' * was first in the structure -- Comedi uses this fact to * extract the name of the board without knowing any details * about the structure except for its length. * When a device is attached (by comedi_config), the name * of the device is given to Comedi, and Comedi tries to * match it by going through the list of board names. If * there is a match, the address of the pointer is put * into dev->board_ptr and driver->attach() is called. * * Note that these are not necessary if you can determine * the type of board in software. ISA PnP, PCI, and PCMCIA * devices are such boards. */ board_name: skel_boards, offset: sizeof(skel_board), num_names: sizeof(skel_boards) / sizeof(skel_board),};static int skel_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);static int skel_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);static int skel_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);static int skel_dio_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data);static int skel_dio_insn_config(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data);static int skel_ai_cmdtest(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);static int skel_ns_to_timer(unsigned int *ns,int round);/* * Attach is called by the Comedi core to configure the driver * for a particular board. If you specified a board_name array * in the driver structure, dev->board_ptr contains that * address. */static int skel_attach(comedi_device *dev,comedi_devconfig *it){ comedi_subdevice *s; printk("comedi%d: skel: ",dev->minor); /* * If you can probe the device to determine what device in a series * it is, this is the place to do it. Otherwise, dev->board_ptr * should already be initialized. */ //dev->board_ptr = skel_probe(dev);/* * Initialize dev->board_name. Note that we can use the "thisboard" * macro now, since we just initialized it in the last line. */ dev->board_name = thisboard->name;/* * Allocate the private structure area. alloc_private() is a * convenient macro defined in comedidev.h. */ if(alloc_private(dev,sizeof(skel_private))<0) return -ENOMEM;/* * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h. */ if(alloc_subdevices(dev, 3)<0) return -ENOMEM; s=dev->subdevices+0; //dev->read_subdev=s; /* analog input subdevice */ s->type=COMEDI_SUBD_AI; /* we support single-ended (ground) and differential */ s->subdev_flags=SDF_READABLE|SDF_GROUND|SDF_DIFF; s->n_chan=thisboard->ai_chans; s->maxdata=(1<<thisboard->ai_bits)-1; s->range_table=&range_bipolar10; s->len_chanlist=16; /* This is the maximum chanlist length that the board can handle */ s->insn_read = skel_ai_rinsn; //s->do_cmd = skel_ai_cmd; s->do_cmdtest = skel_ai_cmdtest; s=dev->subdevices+1; /* analog output subdevice */ s->type=COMEDI_SUBD_AO; s->subdev_flags=SDF_WRITABLE; s->n_chan=1; s->maxdata=0xffff; s->range_table=&range_bipolar5; s->insn_write = skel_ao_winsn; s->insn_read = skel_ao_rinsn; s=dev->subdevices+2; /* digital i/o subdevice */ if(thisboard->have_dio){ s->type=COMEDI_SUBD_DIO; s->subdev_flags=SDF_READABLE|SDF_WRITABLE; s->n_chan=16; s->maxdata=1; s->range_table=&range_digital; s->insn_bits = skel_dio_insn_bits; s->insn_config = skel_dio_insn_config; }else{ s->type = COMEDI_SUBD_UNUSED; } printk("attached\n"); return 1;}/* * _detach is called to deconfigure a device. It should deallocate * resources. * This function is also called when _attach() fails, so it should be * careful not to release resources that were not necessarily * allocated by _attach(). dev->private and dev->subdevices are * deallocated automatically by the core. */static int skel_detach(comedi_device *dev){ printk("comedi%d: skel: remove\n",dev->minor); return 0;}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -