【问题标题】:Accessing the parallel port hardware on linux访问linux上的并口硬件
【发布时间】:2012-08-04 08:01:41
【问题描述】:

我写了一个并口 Linux 设备驱动程序,但我无法访问并口硬件

#include <linux/init.h>
#include <linux/autoconf.h>
#include <linux/module.h>
#include <linux/kernel.h> 
#include <linux/slab.h> 
#include <linux/fs.h> 
#include <linux/errno.h> 
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <linux/ioport.h>
#include <asm/system.h> 
#include <asm/uaccess.h> 
#include <asm/io.h> 
#define DRVNAME "parportleds"
#define BASEPORT 0x378

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Ganesh");
MODULE_DESCRIPTION("Parallel port LED driver.");


int parportleds_open(struct inode *inode, struct file *filp);
int parportleds_release(struct inode *inode, struct file *filp);
ssize_t parportleds_read(struct file *filp,char *buf,size_t count, loff_t *f_pos);
ssize_t parportleds_write(struct file *filp, const char *buf,size_t count, loff_t   *f_pos);

void parportleds_exit(void);
int parportleds_init(void);


struct file_operations parportleds_fops = {
  read: parportleds_read,
  write: parportleds_write,
  open: parportleds_open,
  release: parportleds_release
};

int parportleds_major = 61;
int port;

module_init(parportleds_init);
module_exit(parportleds_exit);

int parportleds_init(void) {
  int result;
  result = register_chrdev(parportleds_major, DRVNAME,&parportleds_fops);
  if (result < 0) {
    printk("<1>parport: cannot obtain major number %d\n",parportleds_major);
    return result;
  }
  port = check_region(BASEPORT, 1);
  if (port) {
    printk("<1>parportleds: cannot reserve 0x378 \n");
    result = port;
    goto fail;
  }
  request_region(BASEPORT, 1, DRVNAME);
  printk("<1>Inserting parportled module\n");
  return 0;
  fail:
    parportleds_exit();
    return result;
}
void parportleds_exit(void) {
  unregister_chrdev(parportleds_major, DRVNAME);
  if (!port) {
    release_region(BASEPORT,1);
  }
  printk("<1>Removing module parportleds\n");
}
int parportleds_open(struct inode *inode, struct file *filp) {
  return 0;
}
int parportleds_release(struct inode *inode, struct file *filp) {
  return 0;
}
ssize_t parportleds_read(struct file *filp, char *buf,size_t count, loff_t *f_pos) {
  char parportleds_buffer;
  parportleds_buffer = inb(BASEPORT);
  copy_to_user(buf,&parportleds_buffer,1);
  if (*f_pos == 0) {
    *f_pos+=1;
    return 1;
  } else {
    return 0;
  }
}
ssize_t parportleds_write( struct file *filp, const char *buf, size_t count, loff_t     *f_pos) {
  char *tmp;
  char parportleds_buffer;
  tmp=(char *)buf+count-1;
  copy_from_user(&parportleds_buffer,tmp,1);
  outb(parportleds_buffer,BASEPORT);
  printk("<1>parport write: %d\n",parportleds_buffer);
  return 1;
}

这是我尝试读写 /dev/parportleds 时的代码,我在 dmesg 中获得了成功的消息
但是当我尝试使用echo 3 &gt; /dev/parportleds 使并行端口的引脚高时@
并行端口的数据管脚电压保持不变。
谁能帮我解决这个问题。
这是我第一次尝试编写设备驱动程序。

【问题讨论】:

  • 旁注:如果您使用 echo 3,您发送的是 0x33,而不是 0x03。
  • 我怎么能发送 0xff 我没有看到任何电压变化

标签: c linux-device-driver


【解决方案1】:

先说几点:

1) 请注意 InternetSeriousBusiness 的评论:当您将字符回显到您的 char 设备时,设备将收到 ASCII 编码的位模式。查看ASCII table 以了解您需要发送哪个字符才能获得所需的位模式。

2)您提到当您发送位模式时,输出电压不会改变。另一个方向呢?您读取的值是否准确反映了施加在引脚上的电压,或者是那些关闭的?如果是,那么您知道问题与写作有关。如果不是,那么您甚至可能没有按照您认为的方式连接到端口。

我的回答:

与用户数据交互的缓冲区应该附加 __user 标签。例如,parportleds_write() 的参数列表应如下所示:

ssize_t parportleds_write(struct file *fp, const char __user *buf, ssize_t count, loff_t *f_pos){

您对 copy_from_user() 的调用可能会失败,因为它丢失了。 __user 标签也应该添加到您的读取函数中。

【讨论】:

    猜你喜欢
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 2010-11-01
    • 2013-07-24
    相关资源
    最近更新 更多