/* thumboard.c : thumboard driver module */ /* $Id: thumboard.c,v 1.1 2001/12/08 01:19:58 cse466_p Exp cse466_p $ */ /* $Log: thumboard.c,v $ * Revision 1.1 2001/12/08 01:19:58 cse466_p * Initial revision * */ #define MODULE #define __KERNEL__ /* Useful GPIO macros are defined in linux/include/asm-arm/arch/SA-1100.h */ #include #include #include #include #include #include #include #include #define TRUE 1 #define FALSE 0 #define THUMBOARD_DEV_MAJOR 23 #define THUMBOARD_IDENT "Thumboard Device Driver" #define THUMBOARD "Thumboard" #define BUF_LENGTH 4 /* lengths of buffer of input characters and buffer of their frequencies */ #define NUM_POLLS 8 /* number of times dirver polls input */ #define POLLING_DELAY 20 /* delays in ms */ int init_module(void); void cleanup_module(void); int thumboard_open (struct inode* inode, struct file* file); int thumboard_release(struct inode* inode, struct file* file); static ssize_t thumboard_read(struct file * file, char * buffer, size_t count, loff_t *ppos); static ssize_t thumboard_write(struct file* file, const char* buffer, size_t count, loff_t *ppos); static struct file_operations thumboard_file_ops = {NULL, NULL, thumboard_read, thumboard_write, NULL, NULL, NULL, NULL, thumboard_open, NULL, thumboard_release, NULL, NULL}; int init_module(void) { printk("<1>Loading %s ...\n", THUMBOARD_IDENT); if (register_chrdev(THUMBOARD_DEV_MAJOR, THUMBOARD, &thumboard_file_ops)) { printk("<1>%s, cannot register major device %d\n", THUMBOARD_IDENT, THUMBOARD_DEV_MAJOR); return -1; } GPDR = 0; /* set whole GPIO port to input */ printk("<1>%s, Done.\n", THUMBOARD_IDENT); return 0; } void cleanup_module(void) { unregister_chrdev(THUMBOARD_DEV_MAJOR, THUMBOARD); printk("<1>Goodbye cruel world\n"); } int thumboard_open (struct inode* inode, struct file* file) { /* Grab any resources our driver needs, including interrupt lines, memory ranges, ports, etc. */ return 0; } int thumboard_release(struct inode* inode, struct file* file) { /* Release any resources, etc. */ return 0; } static ssize_t thumboard_read(struct file * file, char * buffer, size_t count, loff_t *ppos) { unsigned int i; /* counters */ unsigned int j; unsigned char buf[BUF_LENGTH]; /* holds input characters */ unsigned int freq[BUF_LENGTH]; /* parallel array: holds their frequencies */ unsigned char c; /* input character */ unsigned int f; /* frequency of c */ unsigned int max; /* index of the most frequent char */ int copy_to_user_ret; /* captures the value of __copy_to_user() */ /* Initialize locals */ f = 0; max = 0; for(j = 0; j < BUF_LENGTH; j++){ buf[j] = 0; freq[j] = 0; } /* Collect several input bytes */ for(i = 0; i < NUM_POLLS; i++){ c = GPLR & 0xFF; /* get the input byte */ /* Compute frequencies of input characters. * Notice that if there are too many different input characters * (which is unlikely, is not it...), we run out of buffer * and drop the rest. */ for(j = 0; j < BUF_LENGTH; j++){ if(buf[j] == c){ /* If we've seen c before, */ freq[j]++; /* just increment its frequency; */ break; } else if(buf[j] == 0){ /* else if there is empty space in buffer, */ buf[j] = c; /* put c there */ freq[j]++; /* and increment its frequency. */ break; } } mdelay(POLLING_DELAY); /* sleep some time */ } /* Compute the most agreeable value. */ for(j = 0; j < BUF_LENGTH; j++){ if(freq[j] == 0){ break; } /* we've looked over all saved characters--break out */ else if(f < freq[j]){ /* basic algorithm to find maximum */ f = freq[j]; max = j; } } /* Output the most agreeable value: buf[max], well, it it's not 0 */ copy_to_user_ret = __copy_to_user(buffer, &(buf[max]), sizeof(unsigned char)); if(copy_to_user_ret){ printk("thumboard: error not all bytes copied to user space\n"); } return 0; } static ssize_t thumboard_write(struct file* file, const char* buffer, size_t count, loff_t *ppos) { printk("<1>%s does NOT support writing!\n", THUMBOARD_IDENT); return -2; }