1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/init.h>
23#include <sound/core.h>
24#include "seq_system.h"
25#include "seq_timer.h"
26#include "seq_queue.h"
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
60static int sysclient = -1;
61
62
63static int announce_port = -1;
64
65
66
67
68static int setheader(struct snd_seq_event * ev, int client, int port)
69{
70 if (announce_port < 0)
71 return -ENODEV;
72
73 memset(ev, 0, sizeof(struct snd_seq_event));
74
75 ev->flags &= ~SNDRV_SEQ_EVENT_LENGTH_MASK;
76 ev->flags |= SNDRV_SEQ_EVENT_LENGTH_FIXED;
77
78 ev->source.client = sysclient;
79 ev->source.port = announce_port;
80 ev->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
81
82
83
84 ev->data.addr.client = client;
85 ev->data.addr.port = port;
86
87 return 0;
88}
89
90
91
92void snd_seq_system_broadcast(int client, int port, int type)
93{
94 struct snd_seq_event ev;
95
96 if (setheader(&ev, client, port) < 0)
97 return;
98 ev.type = type;
99 snd_seq_kernel_client_dispatch(sysclient, &ev, 0, 0);
100}
101
102
103int snd_seq_system_notify(int client, int port, struct snd_seq_event *ev)
104{
105 ev->flags = SNDRV_SEQ_EVENT_LENGTH_FIXED;
106 ev->source.client = sysclient;
107 ev->source.port = announce_port;
108 ev->dest.client = client;
109 ev->dest.port = port;
110 return snd_seq_kernel_client_dispatch(sysclient, ev, 0, 0);
111}
112
113
114static int event_input_timer(struct snd_seq_event * ev, int direct, void *private_data, int atomic, int hop)
115{
116 return snd_seq_control_queue(ev, atomic, hop);
117}
118
119
120int __init snd_seq_system_client_init(void)
121{
122 struct snd_seq_port_callback pcallbacks;
123 struct snd_seq_port_info *port;
124
125 port = kzalloc(sizeof(*port), GFP_KERNEL);
126 if (!port)
127 return -ENOMEM;
128
129 memset(&pcallbacks, 0, sizeof(pcallbacks));
130 pcallbacks.owner = THIS_MODULE;
131 pcallbacks.event_input = event_input_timer;
132
133
134 sysclient = snd_seq_create_kernel_client(NULL, 0, "System");
135
136
137 strcpy(port->name, "Timer");
138 port->capability = SNDRV_SEQ_PORT_CAP_WRITE;
139 port->capability |= SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ;
140 port->kernel = &pcallbacks;
141 port->type = 0;
142 port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
143 port->addr.client = sysclient;
144 port->addr.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
145 snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
146
147
148 strcpy(port->name, "Announce");
149 port->capability = SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ;
150 port->kernel = NULL;
151 port->type = 0;
152 port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
153 port->addr.client = sysclient;
154 port->addr.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
155 snd_seq_kernel_client_ctl(sysclient, SNDRV_SEQ_IOCTL_CREATE_PORT, port);
156 announce_port = port->addr.port;
157
158 kfree(port);
159 return 0;
160}
161
162
163
164void __exit snd_seq_system_client_done(void)
165{
166 int oldsysclient = sysclient;
167
168 if (oldsysclient >= 0) {
169 sysclient = -1;
170 announce_port = -1;
171 snd_seq_delete_kernel_client(oldsysclient);
172 }
173}
174