aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/miropcm20-rds.c
blob: c93490ec96bb7b2f5a4145047e5730fefbf29c9b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* MiroSOUND PCM20 radio rds interface driver
 * (c) 2001 Robert Siemer <Robert.Siemer@gmx.de>
 * Thanks to Fred Seidel. See miropcm20-rds-core.c for further information.
 */

/* Revision history:
 *
 *   2001-04-18  Robert Siemer <Robert.Siemer@gmx.de>
 *        separate file for user interface driver
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>	/* current, TASK_*, schedule_timeout() */
#include <linux/delay.h>
#include <asm/uaccess.h>
#include "miropcm20-rds-core.h"

static char * text_buffer;
static int rds_users = 0;


static int rds_f_open(struct inode *in, struct file *fi)
{
	if (rds_users)
		return -EBUSY;

	rds_users++;
	if ((text_buffer=kmalloc(66, GFP_KERNEL)) == 0) {
		rds_users--;
		printk(KERN_NOTICE "aci-rds: Out of memory by open()...\n");
		return -ENOMEM;
	}

	return 0;
}

static int rds_f_release(struct inode *in, struct file *fi)
{
	kfree(text_buffer);

	rds_users--;
	return 0;
}

static void print_matrix(char *ch, char out[])
{
	int j;

	for (j=7; j>=0; j--) {
		 out[7-j] = ((*ch >> j) & 0x1) + '0';
	}
}

static ssize_t rds_f_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
//	i = sprintf(text_buffer, "length: %d, offset: %d\n", length, *offset);

	char c;
	char bits[8];

	msleep(2000);
	aci_rds_cmd(RDS_STATUS, &c, 1);
	print_matrix(&c, bits);
	if (copy_to_user(buffer, bits, 8))
		return -EFAULT;

/*	if ((c >> 3) & 1) {
		aci_rds_cmd(RDS_STATIONNAME, text_buffer+1, 8);
		text_buffer[0]  = ' ' ;
		text_buffer[9]  = '\n';
		return copy_to_user(buffer+8, text_buffer, 10) ? -EFAULT: 18;
	}
*/
/*	if ((c >> 6) & 1) {
		aci_rds_cmd(RDS_PTYTATP, &c, 1);
		if ( c & 1)
			sprintf(text_buffer, " M");
		else
			sprintf(text_buffer, " S");
		if ((c >> 1) & 1)
			sprintf(text_buffer+2, " TA");
		else
			sprintf(text_buffer+2, " --");
		if ((c >> 7) & 1)
			sprintf(text_buffer+5, " TP");
		else
			sprintf(text_buffer+5, " --");
		sprintf(text_buffer+8, " %2d\n", (c >> 2) & 0x1f);
		return copy_to_user(buffer+8, text_buffer, 12) ? -EFAULT: 20;
	}
*/

	if ((c >> 4) & 1) {
		aci_rds_cmd(RDS_TEXT, text_buffer, 65);
		text_buffer[0]  = ' ' ;
		text_buffer[65] = '\n';
		return copy_to_user(buffer+8, text_buffer,66) ? -EFAULT : 66+8;
	} else {
		put_user('\n', buffer+8);
		return 9;
	}
}

static const struct file_operations rds_fops = {
	.owner		= THIS_MODULE,
	.read		= rds_f_read,
	.open		= rds_f_open,
	.release	= rds_f_release
};

static struct miscdevice rds_miscdev = {
	.minor		= MISC_DYNAMIC_MINOR,
	.name		= "radiotext",
	.fops		= &rds_fops,
};

static int __init miropcm20_rds_init(void)
{
	return misc_register(&rds_miscdev);
}

static void __exit miropcm20_rds_cleanup(void)
{
	misc_deregister(&rds_miscdev);
}

module_init(miropcm20_rds_init);
module_exit(miropcm20_rds_cleanup);
MODULE_LICENSE("GPL");