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

📄 serial2002.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    comedi/drivers/serial2002.c    Skeleton code for a Comedi driver    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se>    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: serial2002.oDescription: Driver for serial connected hardwareDevices:Author: Anders BlomdellUpdated: Fri,  7 Jun 2002 12:56:45 -0700Status: in development*/#include <linux/comedidev.h>#include <linux/delay.h>#include <linux/ioport.h>/* * 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 serial2002_board_struct {	char *name;} serial2002_board;serial2002_board serial2002_boards[] = {  {    name:		"serial2002"  }};/* * Useful for shorthand access to the particular board structure */#define thisboard ((serial2002_board *)dev->board_ptr)typedef struct {   // HACK...  int length;  comedi_krange range;} serial2002_range_table_t;typedef struct {  int port;  		// /dev/ttyS<port>  int speed; 		// baudrate  struct file *tty;  lsampl_t ao_readback[32];  unsigned char digital_in_mapping[32];  unsigned char digital_out_mapping[32];  unsigned char analog_in_mapping[32];  unsigned char analog_out_mapping[32];  serial2002_range_table_t in_range[32], out_range[32];} serial2002_private;/* * most drivers define the following macro to make it easy to * access the private structure. */#define devpriv ((serial2002_private *)dev->private)static int serial2002_attach(comedi_device *dev,comedi_devconfig *it);static int serial2002_detach(comedi_device *dev);comedi_driver driver_serial2002={	driver_name:	"serial2002",	module:		THIS_MODULE,	attach:		serial2002_attach,	detach:		serial2002_detach,	board_name:	serial2002_boards,	offset:		sizeof(serial2002_board),	num_names:	sizeof(serial2002_boards) / sizeof(serial2002_board),};static int serial2002_di_rinsn(comedi_device *dev, comedi_subdevice *s,			       comedi_insn *insn, lsampl_t *data);static int serial2002_do_winsn(comedi_device *dev, comedi_subdevice *s,			       comedi_insn *insn, lsampl_t *data);static int serial2002_ai_rinsn(comedi_device *dev, comedi_subdevice *s,			       comedi_insn *insn,lsampl_t *data);static int serial2002_ao_winsn(comedi_device *dev, comedi_subdevice *s,			       comedi_insn *insn, lsampl_t *data);static int serial2002_ao_rinsn(comedi_device *dev, comedi_subdevice *s,			       comedi_insn *insn, lsampl_t *data);struct serial_data {  enum { is_invalid, is_digital, is_channel } kind;  int index;  unsigned long value;};static int tty_write(struct file *f, unsigned char *buf, int count) {  int result;  mm_segment_t oldfs;  oldfs = get_fs();  set_fs(KERNEL_DS);  f->f_pos = 0;  result = f->f_op->write(f, buf, count, &f->f_pos);  set_fs(oldfs);  return result;}static int tty_available(struct file *f) {  long result = 0;  mm_segment_t oldfs;  oldfs = get_fs();  set_fs(KERNEL_DS);  f->f_op->ioctl(f->f_dentry->d_inode, f, FIONREAD, (int)&result);  set_fs(oldfs);  return result;}static int tty_read(struct file *f, int timeout) {  int result, retries;  mm_segment_t oldfs;  result = -1;  if (!IS_ERR(f)) {    retries = 0;    oldfs = get_fs();    set_fs(KERNEL_DS);    while (retries < timeout) {      retries++;      if (tty_available(f) > 0) {	int count;	unsigned char ch; 	f->f_pos = 0;	count = f->f_op->read(f, &ch, 1, &f->f_pos);	if (count == 1) {	result = ch; }	break;      }      comedi_udelay(100);    }    set_fs(oldfs);  }  return result;}static void tty_setspeed(struct file *f, int speed){  mm_segment_t        oldfs;  oldfs = get_fs();  set_fs(KERNEL_DS);  {    // Set speed    struct termios settings;        f->f_op->ioctl(f->f_dentry->d_inode, f, TCGETS, (int)&settings);//    printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX));    settings.c_iflag = 0;    settings.c_oflag = 0;    settings.c_lflag = 0;    settings.c_cflag = CLOCAL | CS8 | CREAD;    settings.c_cc[VMIN] = 1;    settings.c_cc[VTIME] = 0;    switch (speed) {      case   2400: { settings.c_cflag |=   B2400; } break;      case   4800: { settings.c_cflag |=   B4800; } break;      case   9600: { settings.c_cflag |=   B9600; } break;      case  19200: { settings.c_cflag |=  B19200; } break;      case  38400: { settings.c_cflag |=  B38400; } break;      case  57600: { settings.c_cflag |=  B57600; } break;      case 115200: { settings.c_cflag |= B115200; } break;      default:     { settings.c_cflag |=   B9600; } break;    }    f->f_op->ioctl(f->f_dentry->d_inode, f, TCSETS, (int)&settings);//    printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX));  }  {    // Set low latency    struct serial_struct settings;    int i;    f->f_op->ioctl(f->f_dentry->d_inode, f, TIOCGSERIAL, (int)&settings);    settings.flags |= ASYNC_LOW_LATENCY;    f->f_op->ioctl(f->f_dentry->d_inode, f, TIOCSSERIAL, (int)&settings);  }    set_fs(oldfs);}static void poll_digital(struct file *f, int channel) {  char cmd;  cmd = 0x40 | (channel & 0x1f);  tty_write(f, &cmd, 1);}static void poll_channel(struct file *f, int channel) {  char cmd;  cmd = 0x60 | (channel & 0x1f);  tty_write(f, &cmd, 1);}static struct serial_data serial_read(struct file *f, int timeout) {  struct serial_data result;  int length;  result.kind = is_invalid;  result.index = 0;  result.value = 0;  length = 0;  while (1) {    int data = tty_read(f, timeout);    length++;    if (data < 0) {      break;    } else if (data & 0x80) {      result.value = (result.value << 7) | (data & 0x7f);    } else {      if (length == 1) { 	switch ((data>>5) & 0x03) {	  case 0: { result.value = 0; result.kind = is_digital; } break;	  case 1: { result.value = 1; result.kind = is_digital; } break;	}      } else {	result.value = (result.value << 2) | ((data & 0x60) >> 5);	result.kind = is_channel;      }      result.index = data & 0x1f;      break;    }  }  return result;}static void serial_write(struct file *f, struct serial_data data) {  if (data.kind == is_digital) {    unsigned char ch = ((data.value<<5) & 0x20) | (data.index & 0x1f);    tty_write(f, &ch, 1);  } else {    unsigned char ch[6];    int i = 0;    if (data.value >= (1L<<30)) { ch[i] =  0x80|((data.value>>30)&0x03); i++; }    if (data.value >= (1L<<23)) { ch[i] =  0x80|((data.value>>23)&0x7f); i++; }    if (data.value >= (1L<<16)) { ch[i] =  0x80|((data.value>>16)&0x7f); i++; }    if (data.value >= (1L<< 9)) { ch[i] =  0x80|((data.value>> 9)&0x7f); i++; }    ch[i] =  0x80|((data.value>> 2)&0x7f); i++;     ch[i] =  ((data.value<< 5)&0x60)|(data.index & 0x1f); i++;     tty_write(f, ch, i);  }}static int serial_2002_open(comedi_device *dev) {  char port[20];  sprintf(port, "/dev/ttyS%d", devpriv->port);  devpriv->tty = filp_open(port, 0, O_RDWR);  if (IS_ERR(devpriv->tty)) {    printk("serial_2002: file open error = %x\n", (int)devpriv->tty);  } else {    typedef struct {       int kind;       int bits;       int min;       int max;     } config_t;    config_t dig_in_config[32];    config_t dig_out_config[32];    config_t chan_in_config[32];    config_t chan_out_config[32];    int i;    for (i = 0 ; i < 32 ; i++) {      dig_in_config[i].kind = 0; dig_in_config[i].bits = 0;       dig_in_config[i].min = 0; dig_in_config[i].max = 0;      dig_out_config[i].kind = 0; dig_out_config[i].bits = 0;       dig_out_config[i].min = 0; dig_out_config[i].max = 0;      chan_in_config[i].kind = 0; chan_in_config[i].bits = 0;       chan_in_config[i].min = 0; chan_in_config[i].max = 0;      chan_out_config[i].kind = 0; chan_out_config[i].bits = 0;       chan_out_config[i].min = 0; chan_out_config[i].max = 0;    }    tty_setspeed(devpriv->tty, devpriv->speed);    poll_channel(devpriv->tty, 31); // Start reading configuration    while (1) {      struct serial_data data;

⌨️ 快捷键说明

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