RE: writing integers to the char device driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Howdy Daniel, 

The peripheral is memory mapped.  I probably could use a standalone C++ program and not use a device driver, but the goal is to eventually make more robust peripherals in the future.  
My driver and my C++ program to access it are posted below, though I have figured out that I can open the device as a binary file and write u32s to it and have it be just fine, though I am still having problems reading from it.  Is it possible to put an EOF marker in the read statement?

My device Driver:
--------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <linux/init.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> /* O_ACCMODE */
#include <linux/ioport.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_from/to_user */
#include <asm/io.h> /* inb, outb */

//#define BUF_LEN 80
#define reg_off_1 0x00000004
#define reg_off_2 0x00000008


static char *Message_Ptr;
static u32 conv_to_num;
static u32 conv_to_num2;

MODULE_LICENSE("Dual BSD/GPL");

unsigned phy_add = 0x75600000;
unsigned remapSize = 0x10000;
unsigned virt_add;

int multi_open(struct inode *inode, struct file *filp);
int multi_release(struct inode *inode, struct file *filp);
ssize_t multi_write(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t multi_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);

struct file_operations multi_fops = {
  read: multi_read,
  write: multi_write,
  open: multi_open,
  release: multi_release,
};

int multi_major=66;

int multi_init(void)
{
  int result;
  result = register_chrdev(multi_major, "multi", &multi_fops);
  virt_add = (unsigned) ioremap(phy_add, remapSize);
  //printk("Mapping %x to virtual address %x\n", phy_add, virt_add);
  Message_Ptr=kmalloc(11, GFP_KERNEL);
  return 0;
}

void multi_exit(void)
{
  iounmap((void *)virt_add);
  unregister_chrdev(multi_major, "multi");
  kfree(Message_Ptr);
}

ssize_t multi_read(struct file *filp, char *buf,size_t count, loff_t *f_pos) {
  int bytes_read=0;  
  
  if(*Message_Ptr==0)
    return 0;
  while (count && *Message_Ptr){
    put_user(*(Message_Ptr++), buf++);
    count--;
    bytes_read++;
  }
  return bytes_read;  
}

ssize_t multi_write( struct file *filp, char *buf,  size_t count, loff_t *f_pos) {
  copy_from_user(&conv_to_num, buf, 4);
  copy_from_user(&conv_to_num2, buf+4, 4);

 *(volatile u32*)virt_add=conv_to_num;
  *(volatile u32*)(virt_add+reg_off_1)=conv_to_num2;
/*
  printk("First number is %u\n",*(volatile u32*) (virt_add));
  printk("Conv_to_num is %u\n",conv_to_num);
  printk("Second number is %u\n",*(volatile u32*) (virt_add+reg_off_1));
  printk("Conv_to_num2 is %u\n",conv_to_num2);
  printk("Solution is %u\n",*(volatile u32*)(virt_add+reg_off_2));
*/
  sprintf(Message_Ptr,"%u",*(volatile u32*) (virt_add+reg_off_2));
  return 8;
}
int multi_open(struct inode *inode, struct file *filp) {
  /* Success */
  return 0;
}

int multi_release(struct inode *inode, struct file *filp) {
  /* Success */
  
  return 0;
}

module_init(multi_init);
module_exit(multi_exit);
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

My C++ program 
------------------------------------------------------------------------
#include <iostream>
#include <fstream>

using namespace std;


int main()
{
  unsigned number, number2;
  char *product;
  long size;
  fstream infile;
  infile.open("/dev/multi",ios::out | ios::in | ios::binary);
  cout<<"Enter a number: "<<endl;
  cin>>number;
  cout<<"Enter another number: "<<endl;
  cin>>number2;

  infile.write((char*)&number,4);
  infile.write((char*)&number2,4);
  size=infile.seekg(ios::end);
  infile.seekg(ios::beg);
  infile.read(product, size);
  cout<<"The solution is : ";

  cout<<product;

  cout<<endl;
  infile.close();
  return 0;
}
---------------------------------------------------------------------------
________________________________________
From: kernelnewbies-bounce@xxxxxxxxxxxx [kernelnewbies-bounce@xxxxxxxxxxxx] On Behalf Of Daniel Widyanto [daniel.widyanto@xxxxxxxxxxxx]
Sent: Thursday, February 19, 2009 4:16 AM
To: kernelnewbies@xxxxxxxxxxxx
Subject: Re: writing integers to the char device driver

Hi Willis,

How is your FPGA peripheral accessed ? Is it memory-mapped or you need
special IO command ?

If it is memory mapped, maybe you can ask the kernel to map the
registers into your process (using mmap), so you don't have to design
your own device driver.

Btw, I'm currently driver development from Linux Device Driver book. If
you could share the char source code that you're using, maybe I can help
you --finger crossed of course =)

Regards,
-daniel


On Wed, 2009-02-18 at 13:29 -0600, Troy, Willis wrote:
> Howdy,
>
> I am fairly new to device drivers and this list, but I'm sure someone in here can help me.
>
> First, some background.  I am working on device drivers for a FPGA that is currently running kernel 2.6.28, because it is an FPGA I can add custom hardware.  The custom hardware I currently have is very simple- just a multiplier- for a proof of concept.  Currently I have a char device driver written for it that will take in ascii and multiply its ascii value by another ascii value.  Eg. 0x0=char(0)*char(0)=48*48.  This isn't really what I want, I want a device driver that can read in two 32 bit numbers and return a 32 bit number.
>
> So,  can I write integers/longs to a character device driver?  Is there a better way to do this?
>
> Thanks in advance,
> Willis



--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ


--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux