OSDN Git Service

Merge remote-tracking branch 'cyanogenmod/gb-release-7.2' into jb-x86-monami
[android-x86/external-alsa-lib.git] / aserver / aserver.c
1 /*
2  *  ALSA server
3  *  Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
4  *
5  *   This program is free software; you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *   GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program; if not, write to the Free Software
17  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18  *
19  */
20
21 #include <sys/shm.h>
22 #include <sys/socket.h>
23 #include <sys/poll.h>
24 #include <sys/un.h>
25 #include <sys/uio.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <stddef.h>
30 #include <getopt.h>
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #include <limits.h>
34 #include <signal.h>
35
36 #include "aserver.h"
37
38 char *command;
39
40 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
41 #define ERROR(...) do {\
42         fprintf(stderr, "%s %s:%i:(%s) ", command, __FILE__, __LINE__, __FUNCTION__); \
43         fprintf(stderr, __VA_ARGS__); \
44         putc('\n', stderr); \
45 } while (0)
46 #else
47 #define ERROR(args...) do {\
48         fprintf(stderr, "%s %s:%i:(%s) ", command, __FILE__, __LINE__, __FUNCTION__); \
49         fprintf(stderr, ##args); \
50         putc('\n', stderr); \
51 } while (0)
52 #endif  
53
54 #define SYSERROR(string) ERROR(string ": %s", strerror(errno))
55
56 static int make_local_socket(const char *filename)
57 {
58         size_t l = strlen(filename);
59         size_t size = offsetof(struct sockaddr_un, sun_path) + l;
60         struct sockaddr_un *addr = alloca(size);
61         int sock;
62
63         sock = socket(PF_LOCAL, SOCK_STREAM, 0);
64         if (sock < 0) {
65                 int result = -errno;
66                 SYSERROR("socket failed");
67                 return result;
68         }
69         
70         unlink(filename);
71
72         addr->sun_family = AF_LOCAL;
73         memcpy(addr->sun_path, filename, l);
74
75         if (bind(sock, (struct sockaddr *) addr, size) < 0) {
76                 int result = -errno;
77                 SYSERROR("bind failed");
78                 return result;
79         }
80
81         return sock;
82 }
83
84 static int make_inet_socket(int port)
85 {
86         struct sockaddr_in addr;
87         int sock;
88
89         sock = socket(PF_INET, SOCK_STREAM, 0);
90         if (sock < 0) {
91                 int result = -errno;
92                 SYSERROR("socket failed");
93                 return result;
94         }
95         
96         addr.sin_family = AF_INET;
97         addr.sin_port = htons(port);
98         addr.sin_addr.s_addr = INADDR_ANY;
99
100         if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
101                 int result = -errno;
102                 SYSERROR("bind failed");
103                 return result;
104         }
105
106         return sock;
107 }
108
109 struct pollfd *pollfds;
110 unsigned int pollfds_count = 0;
111 typedef struct waiter waiter_t;
112 typedef int (*waiter_handler_t)(waiter_t *waiter, unsigned short events);
113 struct waiter {
114         int fd;
115         void *private_data;
116         waiter_handler_t handler;
117 };
118 waiter_t *waiters;
119
120 static void add_waiter(int fd, unsigned short events, waiter_handler_t handler,
121                 void *data)
122 {
123         waiter_t *w = &waiters[fd];
124         struct pollfd *pfd = &pollfds[pollfds_count];
125         assert(!w->handler);
126         pfd->fd = fd;
127         pfd->events = events;
128         pfd->revents = 0;
129         w->fd = fd;
130         w->private_data = data;
131         w->handler = handler;
132         pollfds_count++;
133 }
134
135 static void del_waiter(int fd)
136 {
137         waiter_t *w = &waiters[fd];
138         unsigned int k;
139         assert(w->handler);
140         w->handler = 0;
141         for (k = 0; k < pollfds_count; ++k) {
142                 if (pollfds[k].fd == fd)
143                         break;
144         }
145         assert(k < pollfds_count);
146         pollfds_count--;
147         memmove(&pollfds[k], &pollfds[k + 1], pollfds_count - k);
148 }
149
150 typedef struct client client_t;
151
152 typedef struct {
153         int (*open)(client_t *client, int *cookie);
154         int (*cmd)(client_t *client);
155         int (*close)(client_t *client);
156 } transport_ops_t;
157
158 struct client {
159         struct list_head list;
160         int poll_fd;
161         int ctrl_fd;
162         int local;
163         int transport_type;
164         int dev_type;
165         char name[256];
166         int stream;
167         int mode;
168         transport_ops_t *ops;
169         snd_async_handler_t *async_handler;
170         int async_sig;
171         pid_t async_pid;
172         union {
173                 struct {
174                         snd_pcm_t *handle;
175                         int fd;
176                 } pcm;
177                 struct {
178                         snd_ctl_t *handle;
179                         int fd;
180                 } ctl;
181 #if 0
182                 struct {
183                         snd_rawmidi_t *handle;
184                 } rawmidi;
185                 struct {
186                         snd_timer_open_t *handle;
187                 } timer;
188                 struct {
189                         snd_hwdep_t *handle;
190                 } hwdep;
191                 struct {
192                         snd_seq_t *handle;
193                 } seq;
194 #endif
195         } device;
196         int polling;
197         int open;
198         int cookie;
199         union {
200                 struct {
201                         int ctrl_id;
202                         void *ctrl;
203                 } shm;
204         } transport;
205 };
206
207 LIST_HEAD(clients);
208
209 typedef struct {
210         struct list_head list;
211         int fd;
212         uint32_t cookie;
213 } inet_pending_t;
214 LIST_HEAD(inet_pendings);
215
216 #if 0
217 static int pcm_handler(waiter_t *waiter, unsigned short events)
218 {
219         client_t *client = waiter->private_data;
220         char buf[1];
221         ssize_t n;
222         if (events & POLLIN) {
223                 n = write(client->poll_fd, buf, 1);
224                 if (n != 1) {
225                         SYSERROR("write failed");
226                         return -errno;
227                 }
228         } else if (events & POLLOUT) {
229                 n = read(client->poll_fd, buf, 1);
230                 if (n != 1) {
231                         SYSERROR("read failed");
232                         return -errno;
233                 }
234         }
235         del_waiter(waiter->fd);
236         client->polling = 0;
237         return 0;
238 }
239 #endif
240
241 static void pcm_shm_hw_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)
242 {
243         client_t *client = pcm->hw.private_data;
244         volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
245         snd_pcm_t *loop;
246
247         ctrl->hw.changed = 1;
248         if (pcm->hw.fd >= 0) {
249                 ctrl->hw.use_mmap = 1;
250                 ctrl->hw.offset = pcm->hw.offset;
251                 return;
252         }
253         ctrl->hw.use_mmap = 0;
254         ctrl->hw.ptr = pcm->hw.ptr ? *pcm->hw.ptr : 0;
255         for (loop = pcm->hw.master; loop; loop = loop->hw.master)
256                 loop->hw.ptr = &ctrl->hw.ptr;
257         pcm->hw.ptr = &ctrl->hw.ptr;
258 }
259
260 static void pcm_shm_appl_ptr_changed(snd_pcm_t *pcm, snd_pcm_t *src ATTRIBUTE_UNUSED)
261 {
262         client_t *client = pcm->appl.private_data;
263         volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
264         snd_pcm_t *loop;
265
266         ctrl->appl.changed = 1;
267         if (pcm->appl.fd >= 0) {
268                 ctrl->appl.use_mmap = 1;
269                 ctrl->appl.offset = pcm->appl.offset;
270                 return;
271         }
272         ctrl->appl.use_mmap = 0;
273         ctrl->appl.ptr = pcm->appl.ptr ? *pcm->appl.ptr : 0;
274         for (loop = pcm->appl.master; loop; loop = loop->appl.master)
275                 loop->appl.ptr = &ctrl->appl.ptr;
276         pcm->appl.ptr = &ctrl->appl.ptr;
277 }
278
279 static int pcm_shm_open(client_t *client, int *cookie)
280 {
281         int shmid;
282         snd_pcm_t *pcm;
283         int err;
284         int result;
285         err = snd_pcm_open(&pcm, client->name, client->stream, SND_PCM_NONBLOCK);
286         if (err < 0)
287                 return err;
288         client->device.pcm.handle = pcm;
289         client->device.pcm.fd = _snd_pcm_poll_descriptor(pcm);
290         pcm->hw.private_data = client;
291         pcm->hw.changed = pcm_shm_hw_ptr_changed;
292         pcm->appl.private_data = client;
293         pcm->appl.changed = pcm_shm_appl_ptr_changed;
294
295         shmid = shmget(IPC_PRIVATE, PCM_SHM_SIZE, 0666);
296         if (shmid < 0) {
297                 result = -errno;
298                 SYSERROR("shmget failed");
299                 goto _err;
300         }
301         client->transport.shm.ctrl_id = shmid;
302         client->transport.shm.ctrl = shmat(shmid, 0, 0);
303         if (client->transport.shm.ctrl == (void*) -1) {
304                 result = -errno;
305                 shmctl(shmid, IPC_RMID, 0);
306                 SYSERROR("shmat failed");
307                 goto _err;
308         }
309         *cookie = shmid;
310         return 0;
311
312  _err:
313         snd_pcm_close(pcm);
314         return result;
315
316 }
317
318 static int pcm_shm_close(client_t *client)
319 {
320         int err;
321         snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
322         if (client->polling) {
323                 del_waiter(client->device.pcm.fd);
324                 client->polling = 0;
325         }
326         err = snd_pcm_close(client->device.pcm.handle);
327         ctrl->result = err;
328         if (err < 0) 
329                 ERROR("snd_pcm_close");
330         if (client->transport.shm.ctrl) {
331                 err = shmdt((void *)client->transport.shm.ctrl);
332                 if (err < 0)
333                         SYSERROR("shmdt failed");
334                 err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
335                 if (err < 0)
336                         SYSERROR("shmctl IPC_RMID failed");
337                 client->transport.shm.ctrl = 0;
338         }
339         client->open = 0;
340         return 0;
341 }
342
343 static int shm_ack(client_t *client)
344 {
345         struct pollfd pfd;
346         int err;
347         char buf[1];
348         pfd.fd = client->ctrl_fd;
349         pfd.events = POLLHUP;
350         if (poll(&pfd, 1, 0) == 1)
351                 return -EBADFD;
352         err = write(client->ctrl_fd, buf, 1);
353         if (err != 1)
354                 return -EBADFD;
355         return 0;
356 }
357
358 static int shm_ack_fd(client_t *client, int fd)
359 {
360         struct pollfd pfd;
361         int err;
362         char buf[1];
363         pfd.fd = client->ctrl_fd;
364         pfd.events = POLLHUP;
365         if (poll(&pfd, 1, 0) == 1)
366                 return -EBADFD;
367         err = snd_send_fd(client->ctrl_fd, buf, 1, fd);
368         if (err != 1)
369                 return -EBADFD;
370         return 0;
371 }
372
373 static int shm_rbptr_fd(client_t *client, snd_pcm_rbptr_t *rbptr)
374 {
375         if (rbptr->fd < 0)
376                 return -EINVAL;
377         return shm_ack_fd(client, rbptr->fd);
378 }
379
380 static void async_handler(snd_async_handler_t *handler)
381 {
382         client_t *client = snd_async_handler_get_callback_private(handler);
383         /* FIXME: use sigqueue */
384         kill(client->async_pid, client->async_sig);
385 }
386
387 static int pcm_shm_cmd(client_t *client)
388 {
389         volatile snd_pcm_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
390         char buf[1];
391         int err;
392         int cmd;
393         snd_pcm_t *pcm;
394         err = read(client->ctrl_fd, buf, 1);
395         if (err != 1)
396                 return -EBADFD;
397         cmd = ctrl->cmd;
398         ctrl->cmd = 0;
399         pcm = client->device.pcm.handle;
400         switch (cmd) {
401         case SND_PCM_IOCTL_ASYNC:
402                 ctrl->result = snd_pcm_async(pcm, ctrl->u.async.sig, ctrl->u.async.pid);
403                 if (ctrl->result < 0)
404                         break;
405                 if (ctrl->u.async.sig >= 0) {
406                         assert(client->async_sig < 0);
407                         ctrl->result = snd_async_add_pcm_handler(&client->async_handler, pcm, async_handler, client);
408                         if (ctrl->result < 0)
409                                 break;
410                 } else {
411                         assert(client->async_sig >= 0);
412                         snd_async_del_handler(client->async_handler);
413                 }
414                 client->async_sig = ctrl->u.async.sig;
415                 client->async_pid = ctrl->u.async.pid;
416                 break;
417         case SNDRV_PCM_IOCTL_INFO:
418                 ctrl->result = snd_pcm_info(pcm, (snd_pcm_info_t *) &ctrl->u.info);
419                 break;
420         case SNDRV_PCM_IOCTL_HW_REFINE:
421                 ctrl->result = snd_pcm_hw_refine(pcm, (snd_pcm_hw_params_t *) &ctrl->u.hw_refine);
422                 break;
423         case SNDRV_PCM_IOCTL_HW_PARAMS:
424                 ctrl->result = snd_pcm_hw_params(pcm, (snd_pcm_hw_params_t *) &ctrl->u.hw_params);
425                 break;
426         case SNDRV_PCM_IOCTL_HW_FREE:
427                 ctrl->result = snd_pcm_hw_free(pcm);
428                 break;
429         case SNDRV_PCM_IOCTL_SW_PARAMS:
430                 ctrl->result = snd_pcm_sw_params(pcm, (snd_pcm_sw_params_t *) &ctrl->u.sw_params);
431                 break;
432         case SNDRV_PCM_IOCTL_STATUS:
433                 ctrl->result = snd_pcm_status(pcm, (snd_pcm_status_t *) &ctrl->u.status);
434                 break;
435         case SND_PCM_IOCTL_STATE:
436                 ctrl->result = snd_pcm_state(pcm);
437                 break;
438         case SND_PCM_IOCTL_HWSYNC:
439                 ctrl->result = snd_pcm_hwsync(pcm);
440                 break;
441         case SNDRV_PCM_IOCTL_DELAY:
442                 ctrl->result = snd_pcm_delay(pcm, (snd_pcm_sframes_t *) &ctrl->u.delay.frames);
443                 break;
444         case SND_PCM_IOCTL_AVAIL_UPDATE:
445                 ctrl->result = snd_pcm_avail_update(pcm);
446                 break;
447         case SNDRV_PCM_IOCTL_PREPARE:
448                 ctrl->result = snd_pcm_prepare(pcm);
449                 break;
450         case SNDRV_PCM_IOCTL_RESET:
451                 ctrl->result = snd_pcm_reset(pcm);
452                 break;
453         case SNDRV_PCM_IOCTL_START:
454                 ctrl->result = snd_pcm_start(pcm);
455                 break;
456         case SNDRV_PCM_IOCTL_DRAIN:
457                 ctrl->result = snd_pcm_drain(pcm);
458                 break;
459         case SNDRV_PCM_IOCTL_DROP:
460                 ctrl->result = snd_pcm_drop(pcm);
461                 break;
462         case SNDRV_PCM_IOCTL_PAUSE:
463                 ctrl->result = snd_pcm_pause(pcm, ctrl->u.pause.enable);
464                 break;
465         case SNDRV_PCM_IOCTL_CHANNEL_INFO:
466                 ctrl->result = snd_pcm_channel_info(pcm, (snd_pcm_channel_info_t *) &ctrl->u.channel_info);
467                 if (ctrl->result >= 0 &&
468                     ctrl->u.channel_info.type == SND_PCM_AREA_MMAP)
469                         return shm_ack_fd(client, ctrl->u.channel_info.u.mmap.fd);
470                 break;
471         case SNDRV_PCM_IOCTL_REWIND:
472                 ctrl->result = snd_pcm_rewind(pcm, ctrl->u.rewind.frames);
473                 break;
474         case SND_PCM_IOCTL_FORWARD:
475                 ctrl->result = snd_pcm_forward(pcm, ctrl->u.forward.frames);
476                 break;
477         case SNDRV_PCM_IOCTL_LINK:
478         {
479                 /* FIXME */
480                 ctrl->result = -ENOSYS;
481                 break;
482         }
483         case SNDRV_PCM_IOCTL_UNLINK:
484                 ctrl->result = snd_pcm_unlink(pcm);
485                 break;
486         case SNDRV_PCM_IOCTL_RESUME:
487                 ctrl->result = snd_pcm_resume(pcm);
488                 break;
489         case SND_PCM_IOCTL_MMAP:
490         {
491                 ctrl->result = snd_pcm_mmap(pcm);
492         }
493         case SND_PCM_IOCTL_MUNMAP:
494         {
495                 ctrl->result = snd_pcm_munmap(pcm);
496                 break;
497         }
498         case SND_PCM_IOCTL_MMAP_COMMIT:
499                 ctrl->result = snd_pcm_mmap_commit(pcm,
500                                                    ctrl->u.mmap_commit.offset,
501                                                    ctrl->u.mmap_commit.frames);
502                 break;
503         case SND_PCM_IOCTL_POLL_DESCRIPTOR:
504                 ctrl->result = 0;
505                 return shm_ack_fd(client, _snd_pcm_poll_descriptor(pcm));
506         case SND_PCM_IOCTL_CLOSE:
507                 client->ops->close(client);
508                 break;
509         case SND_PCM_IOCTL_HW_PTR_FD:
510                 return shm_rbptr_fd(client, &pcm->hw);
511         case SND_PCM_IOCTL_APPL_PTR_FD:
512                 return shm_rbptr_fd(client, &pcm->appl);
513         default:
514                 ERROR("Bogus cmd: %x", ctrl->cmd);
515                 ctrl->result = -ENOSYS;
516         }
517         return shm_ack(client);
518 }
519
520 transport_ops_t pcm_shm_ops = {
521         .open   = pcm_shm_open,
522         .cmd    = pcm_shm_cmd,
523         .close  = pcm_shm_close,
524 };
525
526 static int ctl_handler(waiter_t *waiter, unsigned short events)
527 {
528         client_t *client = waiter->private_data;
529         char buf[1];
530         ssize_t n;
531         if (events & POLLIN) {
532                 n = write(client->poll_fd, buf, 1);
533                 if (n != 1) {
534                         SYSERROR("write failed");
535                         return -errno;
536                 }
537         }
538         del_waiter(waiter->fd);
539         client->polling = 0;
540         return 0;
541 }
542
543 static int ctl_shm_open(client_t *client, int *cookie)
544 {
545         int shmid;
546         snd_ctl_t *ctl;
547         int err;
548         int result;
549         err = snd_ctl_open(&ctl, client->name, SND_CTL_NONBLOCK);
550         if (err < 0)
551                 return err;
552         client->device.ctl.handle = ctl;
553         client->device.ctl.fd = _snd_ctl_poll_descriptor(ctl);
554
555         shmid = shmget(IPC_PRIVATE, CTL_SHM_SIZE, 0666);
556         if (shmid < 0) {
557                 result = -errno;
558                 SYSERROR("shmget failed");
559                 goto _err;
560         }
561         client->transport.shm.ctrl_id = shmid;
562         client->transport.shm.ctrl = shmat(shmid, 0, 0);
563         if (!client->transport.shm.ctrl) {
564                 result = -errno;
565                 shmctl(shmid, IPC_RMID, 0);
566                 SYSERROR("shmat failed");
567                 goto _err;
568         }
569         *cookie = shmid;
570         add_waiter(client->device.ctl.fd, POLLIN, ctl_handler, client);
571         client->polling = 1;
572         return 0;
573
574  _err:
575         snd_ctl_close(ctl);
576         return result;
577
578 }
579
580 static int ctl_shm_close(client_t *client)
581 {
582         int err;
583         snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
584         if (client->polling) {
585                 del_waiter(client->device.ctl.fd);
586                 client->polling = 0;
587         }
588         err = snd_ctl_close(client->device.ctl.handle);
589         ctrl->result = err;
590         if (err < 0) 
591                 ERROR("snd_ctl_close");
592         if (client->transport.shm.ctrl) {
593                 err = shmdt((void *)client->transport.shm.ctrl);
594                 if (err < 0)
595                         SYSERROR("shmdt failed");
596                 err = shmctl(client->transport.shm.ctrl_id, IPC_RMID, 0);
597                 if (err < 0)
598                         SYSERROR("shmctl failed");
599                 client->transport.shm.ctrl = 0;
600         }
601         client->open = 0;
602         return 0;
603 }
604
605 static int ctl_shm_cmd(client_t *client)
606 {
607         snd_ctl_shm_ctrl_t *ctrl = client->transport.shm.ctrl;
608         char buf[1];
609         int err;
610         int cmd;
611         snd_ctl_t *ctl;
612         err = read(client->ctrl_fd, buf, 1);
613         if (err != 1)
614                 return -EBADFD;
615         cmd = ctrl->cmd;
616         ctrl->cmd = 0;
617         ctl = client->device.ctl.handle;
618         switch (cmd) {
619         case SND_CTL_IOCTL_ASYNC:
620                 ctrl->result = snd_ctl_async(ctl, ctrl->u.async.sig, ctrl->u.async.pid);
621                 if (ctrl->result < 0)
622                         break;
623                 if (ctrl->u.async.sig >= 0) {
624                         assert(client->async_sig < 0);
625                         ctrl->result = snd_async_add_ctl_handler(&client->async_handler, ctl, async_handler, client);
626                         if (ctrl->result < 0)
627                                 break;
628                 } else {
629                         assert(client->async_sig >= 0);
630                         snd_async_del_handler(client->async_handler);
631                 }
632                 client->async_sig = ctrl->u.async.sig;
633                 client->async_pid = ctrl->u.async.pid;
634                 break;
635                 break;
636         case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
637                 ctrl->result = snd_ctl_subscribe_events(ctl, ctrl->u.subscribe_events);
638                 break;
639         case SNDRV_CTL_IOCTL_CARD_INFO:
640                 ctrl->result = snd_ctl_card_info(ctl, &ctrl->u.card_info);
641                 break;
642         case SNDRV_CTL_IOCTL_ELEM_LIST:
643         {
644                 size_t maxsize = CTL_SHM_DATA_MAXLEN;
645                 if (ctrl->u.element_list.space * sizeof(*ctrl->u.element_list.pids) > maxsize) {
646                         ctrl->result = -EFAULT;
647                         break;
648                 }
649                 ctrl->u.element_list.pids = (snd_ctl_elem_id_t*) ctrl->data;
650                 ctrl->result = snd_ctl_elem_list(ctl, &ctrl->u.element_list);
651                 break;
652         }
653         case SNDRV_CTL_IOCTL_ELEM_INFO:
654                 ctrl->result = snd_ctl_elem_info(ctl, &ctrl->u.element_info);
655                 break;
656         case SNDRV_CTL_IOCTL_ELEM_READ:
657                 ctrl->result = snd_ctl_elem_read(ctl, &ctrl->u.element_read);
658                 break;
659         case SNDRV_CTL_IOCTL_ELEM_WRITE:
660                 ctrl->result = snd_ctl_elem_write(ctl, &ctrl->u.element_write);
661                 break;
662         case SNDRV_CTL_IOCTL_ELEM_LOCK:
663                 ctrl->result = snd_ctl_elem_lock(ctl, &ctrl->u.element_lock);
664                 break;
665         case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
666                 ctrl->result = snd_ctl_elem_unlock(ctl, &ctrl->u.element_unlock);
667                 break;
668         case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
669                 ctrl->result = snd_ctl_hwdep_next_device(ctl, &ctrl->u.device);
670                 break;
671         case SNDRV_CTL_IOCTL_HWDEP_INFO:
672                 ctrl->result = snd_ctl_hwdep_info(ctl, &ctrl->u.hwdep_info);
673                 break;
674         case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
675                 ctrl->result = snd_ctl_pcm_next_device(ctl, &ctrl->u.device);
676                 break;
677         case SNDRV_CTL_IOCTL_PCM_INFO:
678                 ctrl->result = snd_ctl_pcm_info(ctl, &ctrl->u.pcm_info);
679                 break;
680         case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
681                 ctrl->result = snd_ctl_pcm_prefer_subdevice(ctl, ctrl->u.pcm_prefer_subdevice);
682                 break;
683         case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
684                 ctrl->result = snd_ctl_rawmidi_next_device(ctl, &ctrl->u.device);
685                 break;
686         case SNDRV_CTL_IOCTL_RAWMIDI_INFO:
687                 ctrl->result = snd_ctl_rawmidi_info(ctl, &ctrl->u.rawmidi_info);
688                 break;
689         case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:
690                 ctrl->result = snd_ctl_rawmidi_prefer_subdevice(ctl, ctrl->u.rawmidi_prefer_subdevice);
691                 break;
692         case SNDRV_CTL_IOCTL_POWER:
693                 ctrl->result = snd_ctl_set_power_state(ctl, ctrl->u.power_state);
694                 break;
695         case SNDRV_CTL_IOCTL_POWER_STATE:
696                 ctrl->result = snd_ctl_get_power_state(ctl, &ctrl->u.power_state);
697                 break;
698         case SND_CTL_IOCTL_READ:
699                 ctrl->result = snd_ctl_read(ctl, &ctrl->u.read);
700                 break;
701         case SND_CTL_IOCTL_CLOSE:
702                 client->ops->close(client);
703                 break;
704         case SND_CTL_IOCTL_POLL_DESCRIPTOR:
705                 ctrl->result = 0;
706                 return shm_ack_fd(client, _snd_ctl_poll_descriptor(ctl));
707         default:
708                 ERROR("Bogus cmd: %x", ctrl->cmd);
709                 ctrl->result = -ENOSYS;
710         }
711         return shm_ack(client);
712 }
713
714 transport_ops_t ctl_shm_ops = {
715         .open   = ctl_shm_open,
716         .cmd    = ctl_shm_cmd,
717         .close  = ctl_shm_close,
718 };
719
720 static int snd_client_open(client_t *client)
721 {
722         int err;
723         snd_client_open_request_t req;
724         snd_client_open_answer_t ans;
725         char *name;
726         memset(&ans, 0, sizeof(ans));
727         err = read(client->ctrl_fd, &req, sizeof(req));
728         if (err < 0) {
729                 SYSERROR("read failed");
730                 exit(1);
731         }
732         if (err != sizeof(req)) {
733                 ans.result = -EINVAL;
734                 goto _answer;
735         }
736         name = alloca(req.namelen);
737         err = read(client->ctrl_fd, name, req.namelen);
738         if (err < 0) {
739                 SYSERROR("read failed");
740                 exit(1);
741         }
742         if (err != req.namelen) {
743                 ans.result = -EINVAL;
744                 goto _answer;
745         }
746
747         switch (req.transport_type) {
748         case SND_TRANSPORT_TYPE_SHM:
749                 if (!client->local) {
750                         ans.result = -EINVAL;
751                         goto _answer;
752                 }
753                 switch (req.dev_type) {
754                 case SND_DEV_TYPE_PCM:
755                         client->ops = &pcm_shm_ops;
756                         break;
757                 case SND_DEV_TYPE_CONTROL:
758                         client->ops = &ctl_shm_ops;
759                         break;
760                 default:
761                         ans.result = -EINVAL;
762                         goto _answer;
763                 }
764                 break;
765         default:
766                 ans.result = -EINVAL;
767                 goto _answer;
768         }
769
770         name[req.namelen] = '\0';
771
772         client->transport_type = req.transport_type;
773         strcpy(client->name, name);
774         client->stream = req.stream;
775         client->mode = req.mode;
776
777         err = client->ops->open(client, &ans.cookie);
778         if (err < 0) {
779                 ans.result = err;
780         } else {
781                 client->open = 1;
782                 ans.result = 0;
783         }
784
785  _answer:
786         err = write(client->ctrl_fd, &ans, sizeof(ans));
787         if (err != sizeof(ans)) {
788                 SYSERROR("write failed");
789                 exit(1);
790         }
791         return 0;
792 }
793
794 static int client_poll_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
795 {
796         client_t *client = waiter->private_data;
797         if (client->open)
798                 client->ops->close(client);
799         close(client->poll_fd);
800         close(client->ctrl_fd);
801         del_waiter(client->poll_fd);
802         del_waiter(client->ctrl_fd);
803         list_del(&client->list);
804         free(client);
805         return 0;
806 }
807
808 static int client_ctrl_handler(waiter_t *waiter, unsigned short events)
809 {
810         client_t *client = waiter->private_data;
811         if (events & POLLHUP) {
812                 if (client->open)
813                         client->ops->close(client);
814                 close(client->ctrl_fd);
815                 del_waiter(client->ctrl_fd);
816                 list_del(&client->list);
817                 free(client);
818                 return 0;
819         }
820         if (client->open)
821                 return client->ops->cmd(client);
822         else
823                 return snd_client_open(client);
824 }
825
826 static int inet_pending_handler(waiter_t *waiter, unsigned short events)
827 {
828         inet_pending_t *pending = waiter->private_data;
829         inet_pending_t *pdata;
830         client_t *client;
831         uint32_t cookie;
832         struct list_head *item;
833         int remove = 0;
834         if (events & POLLHUP)
835                 remove = 1;
836         else {
837                 int err = read(waiter->fd, &cookie, sizeof(cookie));
838                 if (err != sizeof(cookie))
839                         remove = 1;
840                 else {
841                         err = write(waiter->fd, &cookie, sizeof(cookie));
842                         if (err != sizeof(cookie))
843                                 remove = 1;
844                 }
845         }
846         del_waiter(waiter->fd);
847         if (remove) {
848                 close(waiter->fd);
849                 list_del(&pending->list);
850                 free(pending);
851                 return 0;
852         }
853
854         list_for_each(item, &inet_pendings) {
855                 pdata = list_entry(item, inet_pending_t, list);
856                 if (pdata->cookie == cookie)
857                         goto found;
858         }
859         pending->cookie = cookie;
860         return 0;
861
862  found:
863         client = calloc(1, sizeof(*client));
864         client->local = 0;
865         client->poll_fd = pdata->fd;
866         client->ctrl_fd = waiter->fd;
867         add_waiter(client->ctrl_fd, POLLIN | POLLHUP, client_ctrl_handler, client);
868         add_waiter(client->poll_fd, POLLHUP, client_poll_handler, client);
869         client->open = 0;
870         list_add_tail(&client->list, &clients);
871         list_del(&pending->list);
872         list_del(&pdata->list);
873         free(pending);
874         free(pdata);
875         return 0;
876 }
877
878 static int local_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
879 {
880         int sock;
881         sock = accept(waiter->fd, 0, 0);
882         if (sock < 0) {
883                 int result = -errno;
884                 SYSERROR("accept failed");
885                 return result;
886         } else {
887                 client_t *client = calloc(1, sizeof(*client));
888                 client->ctrl_fd = sock;
889                 client->local = 1;
890                 client->open = 0;
891                 add_waiter(sock, POLLIN | POLLHUP, client_ctrl_handler, client);
892                 list_add_tail(&client->list, &clients);
893         }
894         return 0;
895 }
896
897 static int inet_handler(waiter_t *waiter, unsigned short events ATTRIBUTE_UNUSED)
898 {
899         int sock;
900         sock = accept(waiter->fd, 0, 0);
901         if (sock < 0) {
902                 int result = -errno;
903                 SYSERROR("accept failed");
904                 return result;
905         } else {
906                 inet_pending_t *pending = calloc(1, sizeof(*pending));
907                 pending->fd = sock;
908                 pending->cookie = 0;
909                 add_waiter(sock, POLLIN, inet_pending_handler, pending);
910                 list_add_tail(&pending->list, &inet_pendings);
911         }
912         return 0;
913 }
914
915 static int server(const char *sockname, int port)
916 {
917         int err;
918         unsigned int k;
919         long open_max;
920         int result;
921
922         if (!sockname && port < 0)
923                 return -EINVAL;
924         open_max = sysconf(_SC_OPEN_MAX);
925         if (open_max < 0) {
926                 result = -errno;
927                 SYSERROR("sysconf failed");
928                 return result;
929         }
930         pollfds = calloc((size_t) open_max, sizeof(*pollfds));
931         waiters = calloc((size_t) open_max, sizeof(*waiters));
932
933         if (sockname) {
934                 int sock = make_local_socket(sockname);
935                 if (sock < 0)
936                         return sock;
937                 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
938                         result = -errno;
939                         SYSERROR("fcntl O_NONBLOCK failed");
940                         goto _end;
941                 }
942                 if (listen(sock, 4) < 0) {
943                         result = -errno;
944                         SYSERROR("listen failed");
945                         goto _end;
946                 }
947                 add_waiter(sock, POLLIN, local_handler, NULL);
948         }
949         if (port >= 0) {
950                 int sock = make_inet_socket(port);
951                 if (sock < 0)
952                         return sock;
953                 if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
954                         result = -errno;
955                         SYSERROR("fcntl failed");
956                         goto _end;
957                 }
958                 if (listen(sock, 4) < 0) {
959                         result = -errno;
960                         SYSERROR("listen failed");
961                         goto _end;
962                 }
963                 add_waiter(sock, POLLIN, inet_handler, NULL);
964         }
965
966         while (1) {
967                 struct pollfd pfds[open_max];
968                 size_t pfds_count;
969                 do {
970                         err = poll(pollfds, pollfds_count, -1);
971                 } while (err == 0);
972                 if (err < 0) {
973                         SYSERROR("poll failed");
974                         continue;
975                 }
976
977                 pfds_count = pollfds_count;
978                 memcpy(pfds, pollfds, sizeof(*pfds) * pfds_count);
979                 for (k = 0; k < pfds_count; k++) {
980                         struct pollfd *pfd = &pfds[k];
981                         if (pfd->revents) {
982                                 waiter_t *w = &waiters[pfd->fd];
983                                 if (!w->handler)
984                                         continue;
985                                 err = w->handler(w, pfd->revents);
986                                 if (err < 0)
987                                         ERROR("waiter handler failed");
988                         }
989                 }
990         }
991  _end:
992         free(pollfds);
993         free(waiters);
994         return result;
995 }
996                                         
997
998 static void usage(void)
999 {
1000         fprintf(stderr,
1001                 "Usage: %s [OPTIONS] server\n"
1002                 "--help                 help\n",
1003                 command);
1004 }
1005
1006 int main(int argc, char **argv)
1007 {
1008         static const struct option long_options[] = {
1009                 {"help", 0, 0, 'h'},
1010                 { 0 , 0 , 0, 0 }
1011         };
1012         int c;
1013         snd_config_t *conf;
1014         snd_config_iterator_t i, next;
1015         const char *sockname = NULL;
1016         const char *host = NULL;
1017         long port = -1;
1018         int err;
1019         char *srvname;
1020         struct hostent *h;
1021         command = argv[0];
1022         while ((c = getopt_long(argc, argv, "h", long_options, 0)) != -1) {
1023                 switch (c) {
1024                 case 'h':
1025                         usage();
1026                         return 0;
1027                 default:
1028                         fprintf(stderr, "Try `%s --help' for more information\n", command);
1029                         return 1;
1030                 }
1031         }
1032         if (argc - optind != 1) {
1033                 ERROR("you need to specify server name");
1034                 return 1;
1035         }
1036         err = snd_config_update();
1037         if (err < 0) {
1038                 ERROR("cannot read configuration file");
1039                 return 1;
1040         }
1041         srvname = argv[optind];
1042         err = snd_config_search_definition(snd_config, "server", srvname, &conf);
1043         if (err < 0) {
1044                 ERROR("Missing definition for server %s", srvname);
1045                 return 1;
1046         }
1047         if (snd_config_get_type(conf) != SND_CONFIG_TYPE_COMPOUND) {
1048                 SNDERR("Invalid type for server %s definition", srvname);
1049                 return -EINVAL;
1050         }
1051         snd_config_for_each(i, next, conf) {
1052                 snd_config_t *n = snd_config_iterator_entry(i);
1053                 const char *id;
1054                 if (snd_config_get_id(n, &id) < 0)
1055                         continue;
1056                 if (strcmp(id, "comment") == 0)
1057                         continue;
1058                 if (strcmp(id, "host") == 0) {
1059                         err = snd_config_get_string(n, &host);
1060                         if (err < 0) {
1061                                 ERROR("Invalid type for %s", id);
1062                                 return 1;
1063                         }
1064                         continue;
1065                 }
1066                 if (strcmp(id, "socket") == 0) {
1067                         err = snd_config_get_string(n, &sockname);
1068                         if (err < 0) {
1069                                 ERROR("Invalid type for %s", id);
1070                                 return 1;
1071                         }
1072                         continue;
1073                 }
1074                 if (strcmp(id, "port") == 0) {
1075                         err = snd_config_get_integer(n, &port);
1076                         if (err < 0) {
1077                                 ERROR("Invalid type for %s", id);
1078                                 return 1;
1079                         }
1080                         continue;
1081                 }
1082                 ERROR("Unknown field %s", id);
1083                 return 1;
1084         }
1085         if (!host) {
1086                 ERROR("host is not defined");
1087                 return 1;
1088         }
1089         h = gethostbyname(host);
1090         if (!h) {
1091                 ERROR("Cannot resolve %s", host);
1092                 return 1;
1093         }
1094         if (!snd_is_local(h)) {
1095                 ERROR("%s is not the local host", host);
1096                 return 1;
1097         }
1098         if (!sockname && port < 0) {
1099                 ERROR("either socket or port need to be defined");
1100                 return 1;
1101         }
1102         server(sockname, port);
1103         return 0;
1104 }