1/* MiroSOUND PCM20 radio rds interface driver 2 * (c) 2001 Robert Siemer <Robert.Siemer@gmx.de> 3 * Thanks to Fred Seidel. See miropcm20-rds-core.c for further information. 4 */ 5 6/* Revision history: 7 * 8 * 2001-04-18 Robert Siemer <Robert.Siemer@gmx.de> 9 * separate file for user interface driver 10 */ 11 12#include <linux/module.h> 13#include <linux/init.h> 14#include <linux/slab.h> 15#include <linux/fs.h> 16#include <linux/miscdevice.h> 17#include <linux/delay.h> 18#include <asm/uaccess.h> 19#include "miropcm20-rds-core.h" 20 21static char * text_buffer; 22static int rds_users = 0; 23 24 25static int rds_f_open(struct inode *in, struct file *fi) 26{ 27 if (rds_users) 28 return -EBUSY; 29 30 rds_users++; 31 if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) { 32 rds_users--; 33 printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n"); 34 return -ENOMEM; 35 } 36 37 return 0; 38} 39 40static int rds_f_release(struct inode *in, struct file *fi) 41{ 42 kfree(text_buffer); 43 44 rds_users--; 45 return 0; 46} 47 48static void print_matrix(char *ch, char out[]) 49{ 50 int j; 51 52 for (j=7; j>=0; j--) { 53 out[7-j] = ((*ch >> j) & 0x1) + '0'; 54 } 55} 56 57static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length, loff_t *offset) 58{ 59// i = sprintf(text_buffer, "length: %d, offset: %d\n", length, *offset); 60 61 char c; 62 char bits[8]; 63 64 msleep(2000); 65 aci_rds_cmd(RDS_STATUS, &c, 1); 66 print_matrix(&c, bits); 67 if (copy_to_user(buffer, bits, 8)) 68 return -EFAULT; 69 70/* if ((c >> 3) & 1) { 71 aci_rds_cmd(RDS_STATIONNAME, text_buffer+1, 8); 72 text_buffer[0] = ' ' ; 73 text_buffer[9] = '\n'; 74 return copy_to_user(buffer+8, text_buffer, 10) ? -EFAULT: 18; 75 } 76*/ 77/* if ((c >> 6) & 1) { 78 aci_rds_cmd(RDS_PTYTATP, &c, 1); 79 if ( c & 1) 80 sprintf(text_buffer, " M"); 81 else 82 sprintf(text_buffer, " S"); 83 if ((c >> 1) & 1) 84 sprintf(text_buffer+2, " TA"); 85 else 86 sprintf(text_buffer+2, " --"); 87 if ((c >> 7) & 1) 88 sprintf(text_buffer+5, " TP"); 89 else 90 sprintf(text_buffer+5, " --"); 91 sprintf(text_buffer+8, " %2d\n", (c >> 2) & 0x1f); 92 return copy_to_user(buffer+8, text_buffer, 12) ? -EFAULT: 20; 93 } 94*/ 95 96 if ((c >> 4) & 1) { 97 aci_rds_cmd(RDS_TEXT, text_buffer, 65); 98 text_buffer[0] = ' ' ; 99 text_buffer[65] = '\n'; 100 return copy_to_user(buffer+8, text_buffer,66) ? -EFAULT : 66+8; 101 } else { 102 put_user('\n', buffer+8); 103 return 9; 104 } 105} 106 107static const struct file_operations rds_fops = { 108 .owner = THIS_MODULE, 109 .read = rds_f_read, 110 .open = rds_f_open, 111 .release = rds_f_release 112}; 113 114static struct miscdevice rds_miscdev = { 115 .minor = MISC_DYNAMIC_MINOR, 116 .name = "radiotext", 117 .fops = &rds_fops, 118}; 119 120static int __init miropcm20_rds_init(void) 121{ 122 return misc_register(&rds_miscdev); 123} 124 125static void __exit miropcm20_rds_cleanup(void) 126{ 127 misc_deregister(&rds_miscdev); 128} 129 130module_init(miropcm20_rds_init); 131module_exit(miropcm20_rds_cleanup); 132MODULE_LICENSE("GPL"); 133