Thanks a bunch, this is really cool! willis ________________________________________ From: kernelnewbies-bounce@xxxxxxxxxxxx [kernelnewbies-bounce@xxxxxxxxxxxx] On Behalf Of Daniel Widyanto [daniel.widyanto@xxxxxxxxxxxx] Sent: Friday, February 20, 2009 10:28 AM To: Troy, Willis Cc: kernelnewbies@xxxxxxxxxxxx Subject: RE: writing integers to the char device driver Hi Willis, To get EOF in the application program, you just need to return 0 at your driver's read function. IMHO, I think that you can use IOCTL to do your driver easily. Like this: ------------------------------------------------ multi.h #ifndef MULTI_H #define MULTI_H #include <linux/ioctl.h> #define MAJOR_NUM 66 /* * Set the values of parameters */ #define IOCTL_SET_VALUES _IOW(MAJOR_NUM, 0, unsigned int *) /* * Get the result value */ #define IOCTL_GET_VALUES _IOR(MAJOR_NUM, 1, unsigned int *) #endif ------------------------------------------------ multi.c #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 */ #include "multi.h" /* IOCTL cmds */ #define reg_off_1 0x00000004 #define reg_off_2 0x00000008 MODULE_LICENSE("Dual BSD/GPL"); static const unsigned phy_add = 0x75600000; static const unsigned remapSize = 0x10000; static unsigned virt_add; //static u32 dummyArg[3]; //static u32 *virt_add = &dummyArg[0]; static int multi_ioctl(struct inode *inode, /* see include/linux/fs.h */ struct file *file, /* ditto */ unsigned int ioctl_num, /* number and param for ioctl */ unsigned long ioctl_param); static struct file_operations multi_fops = { .ioctl = multi_ioctl }; static int multi_major = MAJOR_NUM; static 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); return result; } static void multi_exit(void) { iounmap((void *)virt_add); unregister_chrdev(multi_major, "multi"); } static int multi_ioctl(struct inode *inode, /* see include/linux/fs.h */ struct file *file, /* ditto */ unsigned int ioctl_num, /* number and param for ioctl */ unsigned long ioctl_param) { u32 conv_to_num = 0; u32 conv_to_num2 = 0; u32 result = 0; /* * Switch according to the ioctl called */ switch (ioctl_num) { case IOCTL_SET_VALUES: /* * Receive pointer to two u32 values */ copy_from_user(&conv_to_num, (u32 *)ioctl_param, 4); copy_from_user(&conv_to_num2, ((u32 *)ioctl_param + 1), 4); *(volatile u32*) virt_add = conv_to_num; *(volatile u32*)(virt_add+reg_off_1) = conv_to_num2; printk(KERN_DEBUG " conv_to_num = %x\n", conv_to_num); printk(KERN_DEBUG " conv_to_num2 = %x\n", conv_to_num2); break; case IOCTL_GET_VALUES: /* * Receive pointer to user buffer to hold u32 value */ result = *(volatile u32*) (virt_add+reg_off_2); copy_to_user((void *)ioctl_param, (void *)&result, sizeof(u32)); printk(KERN_DEBUG " result = %x\n", result); break; } return 0; } module_init(multi_init); module_exit(multi_exit); ------------------------------------------------ user_app.c #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <errno.h> #include <fcntl.h> /* open */ #include <unistd.h> /* exit */ #include <sys/ioctl.h> /* ioctl */ #include "multi.h" /* * Functions for the ioctl calls */ void ioctl_set_values(int file_desc, uint32_t *param) { int ret_val = ioctl(file_desc, IOCTL_SET_VALUES, param); if (ret_val < 0) { printf("ioctl_set_values failed:%d\n", ret_val); exit(EXIT_FAILURE); } } void ioctl_get_values(int file_desc, uint32_t *result) { /* * Warning − this is dangerous because we don't tell * the kernel how far it's allowed to write, so it * might overflow the buffer. In a real production * program, we would have used two ioctls − one to tell * the kernel the buffer length and another to give * it the buffer to fill */ int ret_val = ioctl(file_desc, IOCTL_GET_VALUES, result); if (ret_val < 0) { printf("ioctl_get_values failed:%d\n", ret_val); exit(EXIT_FAILURE); } } /* * Main − Call the ioctl functions */ uint32_t u32_param[2]; uint32_t u32_result; int main(int argc, char *argv[]) { if (argc != 4) { fprintf(stdout, "Usage: %s <dev file> <uint32_t 1> <uint32_t 2>\n", argv[0]); exit(EXIT_FAILURE); } int fd = open(argv[1], O_RDWR); if (fd < 0) { fprintf(stderr,"Error : %x",errno); exit(EXIT_FAILURE); } u32_param[0] = atoi(argv[2]); u32_param[1] = atoi(argv[3]); fprintf(stdout, "First val: %d\n", u32_param[0]); fprintf(stdout, "Second val: %d\n", u32_param[1]); ioctl_set_values(fd, &u32_param[0]); ioctl_get_values(fd, &u32_result); fprintf(stdout, "Result: %d\n", u32_result); close(fd); exit(EXIT_SUCCESS); } ------------------------------------------------ Hope that helps. Sorry, I'm a bit blind with C++. Regards, -daniel On Thu, 2009-02-19 at 13:12 -0600, Troy, Willis wrote: > 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; > } > --------------------------------------------------------------------------- -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ��.n��������+%����w�j)p���{.n����z�ޖw�n'���q���b�������v��m�����Y�����