2012-08-04 40 views
1

並行端口硬件我寫了一個並行端口的Linux設備驅動程序,但我不能訪問並行端口硬件訪問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我得到一個sucess msg in dmesg
但是,當我嘗試使用高位並行端口使用echo 3 > /dev/parportleds
並行端口的數據平臺的電壓保持不變。
任何人都可以幫助我解決這個問題。
它是我第一次嘗試編寫設備驅動程序。

+0

備註:如果使用echo 3,則發送0x33而不是0x03。 – InternetSeriousBusiness 2012-08-04 08:15:18

+0

我怎麼發送0xff的方式,我沒有看到任何電壓變化 – ganeshredcobra 2012-08-05 12:17:36

回答

0

有兩點要注意第一:

1)注意InternetSeriousBusiness'評論:當你回顯字符的字符設備,該設備將收到的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標籤也應該添加到您的閱讀功能中。