• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * \file timer/timer_query.c
3  * \author Jaroslav Kysela <perex@perex.cz>
4  * \date 2001
5  *
6  * Timer Query Interface is designed to obtain identification of timers.
7  */
8 /*
9  *  Timer Query Interface - main file
10  *  Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
11  *
12  *
13  *   This library is free software; you can redistribute it and/or modify
14  *   it under the terms of the GNU Lesser General Public License as
15  *   published by the Free Software Foundation; either version 2.1 of
16  *   the License, or (at your option) any later version.
17  *
18  *   This program is distributed in the hope that it will be useful,
19  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *   GNU Lesser General Public License for more details.
22  *
23  *   You should have received a copy of the GNU Lesser General Public
24  *   License along with this library; if not, write to the Free Software
25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
26  *
27  */
28 
29 #include "timer_local.h"
30 
snd_timer_query_open_conf(snd_timer_query_t ** timer,const char * name,snd_config_t * timer_root,snd_config_t * timer_conf,int mode)31 static int snd_timer_query_open_conf(snd_timer_query_t **timer,
32 				     const char *name, snd_config_t *timer_root,
33 				     snd_config_t *timer_conf, int mode)
34 {
35 	const char *str;
36 	char buf[256], errbuf[256];
37 	int err;
38 	snd_config_t *conf, *type_conf = NULL;
39 	snd_config_iterator_t i, next;
40 	const char *id;
41 	const char *lib = NULL, *open_name = NULL;
42 	int (*open_func)(snd_timer_query_t **, const char *, snd_config_t *, snd_config_t *, int) = NULL;
43 #ifndef PIC
44 	extern void *snd_timer_query_open_symbols(void);
45 #endif
46 	void *h = NULL;
47 	if (snd_config_get_type(timer_conf) != SND_CONFIG_TYPE_COMPOUND) {
48 		if (name)
49 			SNDERR("Invalid type for TIMER %s definition", name);
50 		else
51 			SNDERR("Invalid type for TIMER definition");
52 		return -EINVAL;
53 	}
54 	err = snd_config_search(timer_conf, "type", &conf);
55 	if (err < 0) {
56 		SNDERR("type is not defined");
57 		return err;
58 	}
59 	err = snd_config_get_id(conf, &id);
60 	if (err < 0) {
61 		SNDERR("unable to get id");
62 		return err;
63 	}
64 	err = snd_config_get_string(conf, &str);
65 	if (err < 0) {
66 		SNDERR("Invalid type for %s", id);
67 		return err;
68 	}
69 	err = snd_config_search_definition(timer_root, "timer_query_type", str, &type_conf);
70 	if (err >= 0) {
71 		if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
72 			SNDERR("Invalid type for TIMER type %s definition", str);
73 			err = -EINVAL;
74 			goto _err;
75 		}
76 		snd_config_for_each(i, next, type_conf) {
77 			snd_config_t *n = snd_config_iterator_entry(i);
78 			const char *id;
79 			if (snd_config_get_id(n, &id) < 0)
80 				continue;
81 			if (strcmp(id, "comment") == 0)
82 				continue;
83 			if (strcmp(id, "lib") == 0) {
84 				err = snd_config_get_string(n, &lib);
85 				if (err < 0) {
86 					SNDERR("Invalid type for %s", id);
87 					goto _err;
88 				}
89 				continue;
90 			}
91 			if (strcmp(id, "open") == 0) {
92 				err = snd_config_get_string(n, &open_name);
93 				if (err < 0) {
94 					SNDERR("Invalid type for %s", id);
95 					goto _err;
96 				}
97 				continue;
98 			}
99 			SNDERR("Unknown field %s", id);
100 			err = -EINVAL;
101 			goto _err;
102 		}
103 	}
104 	if (!open_name) {
105 		open_name = buf;
106 		snprintf(buf, sizeof(buf), "_snd_timer_query_%s_open", str);
107 	}
108 #ifndef PIC
109 	snd_timer_query_open_symbols();
110 #endif
111 	h = INTERNAL(snd_dlopen)(lib, RTLD_NOW, errbuf, sizeof(errbuf));
112 	if (h)
113 		open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_TIMER_QUERY_DLSYM_VERSION));
114 	err = 0;
115 	if (!h) {
116 		SNDERR("Cannot open shared library %s (%s)", lib, errbuf);
117 		err = -ENOENT;
118 	} else if (!open_func) {
119 		SNDERR("symbol %s is not defined inside %s", open_name, lib);
120 		snd_dlclose(h);
121 		err = -ENXIO;
122 	}
123        _err:
124 	if (type_conf)
125 		snd_config_delete(type_conf);
126 	if (! err) {
127 		err = open_func(timer, name, timer_root, timer_conf, mode);
128 		if (err < 0)
129 			snd_dlclose(h);
130 		else
131 			(*timer)->dl_handle = h;
132 	}
133 	return err;
134 }
135 
snd_timer_query_open_noupdate(snd_timer_query_t ** timer,snd_config_t * root,const char * name,int mode)136 static int snd_timer_query_open_noupdate(snd_timer_query_t **timer, snd_config_t *root, const char *name, int mode)
137 {
138 	int err;
139 	snd_config_t *timer_conf;
140 	err = snd_config_search_definition(root, "timer_query", name, &timer_conf);
141 	if (err < 0) {
142 		SNDERR("Unknown timer %s", name);
143 		return err;
144 	}
145 	err = snd_timer_query_open_conf(timer, name, root, timer_conf, mode);
146 	snd_config_delete(timer_conf);
147 	return err;
148 }
149 
150 /**
151  * \brief Opens a new connection to the timer query interface.
152  * \param timer Returned handle (NULL if not wanted)
153  * \param name ASCII identifier of the RawMidi handle
154  * \param mode Open mode
155  * \return 0 on success otherwise a negative error code
156  *
157  * Opens a new connection to the RawMidi interface specified with
158  * an ASCII identifier and mode.
159  */
snd_timer_query_open(snd_timer_query_t ** timer,const char * name,int mode)160 int snd_timer_query_open(snd_timer_query_t **timer, const char *name, int mode)
161 {
162 	snd_config_t *top;
163 	int err;
164 
165 	assert(timer && name);
166 	err = snd_config_update_ref(&top);
167 	if (err < 0)
168 		return err;
169 	err = snd_timer_query_open_noupdate(timer, top, name, mode);
170 	snd_config_unref(top);
171 	return err;
172 }
173 
174 /**
175  * \brief Opens a new connection to the timer query interface using local configuration
176  * \param timer Returned handle (NULL if not wanted)
177  * \param name ASCII identifier of the RawMidi handle
178  * \param mode Open mode
179  * \param lconf Local configuration
180  * \return 0 on success otherwise a negative error code
181  *
182  * Opens a new connection to the RawMidi interface specified with
183  * an ASCII identifier and mode.
184  */
snd_timer_query_open_lconf(snd_timer_query_t ** timer,const char * name,int mode,snd_config_t * lconf)185 int snd_timer_query_open_lconf(snd_timer_query_t **timer, const char *name,
186 			       int mode, snd_config_t *lconf)
187 {
188 	assert(timer && name && lconf);
189 	return snd_timer_query_open_noupdate(timer, lconf, name, mode);
190 }
191 
192 /**
193  * \brief close timer query handle
194  * \param timer timer handle
195  * \return 0 on success otherwise a negative error code
196  *
197  * Closes the specified timer handle and frees all associated
198  * resources.
199  */
snd_timer_query_close(snd_timer_query_t * timer)200 int snd_timer_query_close(snd_timer_query_t *timer)
201 {
202 	int err;
203   	assert(timer);
204 	err = timer->ops->close(timer);
205 	if (timer->dl_handle)
206 		snd_dlclose(timer->dl_handle);
207 	free(timer->name);
208 	free(timer);
209 	return err;
210 }
211 
212 /**
213  * \brief obtain the next timer identification
214  * \param timer timer handle
215  * \param tid timer identification
216  * \return 0 on success otherwise a negative error code
217  *
218  * if tid->dev_class is -1, then the first device is returned
219  * if result tid->dev_class is -1, no more devices are left
220  */
snd_timer_query_next_device(snd_timer_query_t * timer,snd_timer_id_t * tid)221 int snd_timer_query_next_device(snd_timer_query_t *timer, snd_timer_id_t *tid)
222 {
223   	assert(timer);
224   	assert(tid);
225 	return timer->ops->next_device(timer, tid);
226 }
227 
228 /**
229  * \brief get size of the snd_timer_ginfo_t structure in bytes
230  * \return size of the snd_timer_ginfo_t structure in bytes
231  */
snd_timer_ginfo_sizeof(void)232 size_t snd_timer_ginfo_sizeof(void)
233 {
234 	return sizeof(snd_timer_ginfo_t);
235 }
236 
237 /**
238  * \brief allocate a new snd_timer_ginfo_t structure
239  * \param info returned pointer
240  * \return 0 on success otherwise a negative error code if fails
241  *
242  * Allocates a new snd_timer_info_t structure using the standard
243  * malloc C library function.
244  */
snd_timer_ginfo_malloc(snd_timer_ginfo_t ** info)245 int snd_timer_ginfo_malloc(snd_timer_ginfo_t **info)
246 {
247 	assert(info);
248 	*info = calloc(1, sizeof(snd_timer_ginfo_t));
249 	if (!*info)
250 		return -ENOMEM;
251 	return 0;
252 }
253 
254 /**
255  * \brief frees the snd_timer_ginfo_t structure
256  * \param info pointer to the snd_timer_ginfo_t structure to free
257  *
258  * Frees the given snd_timer_info_t structure using the standard
259  * free C library function.
260  */
snd_timer_ginfo_free(snd_timer_ginfo_t * info)261 void snd_timer_ginfo_free(snd_timer_ginfo_t *info)
262 {
263 	assert(info);
264 	free(info);
265 }
266 
267 /**
268  * \brief copy one snd_timer_info_t structure to another
269  * \param dst destination snd_timer_info_t structure
270  * \param src source snd_timer_info_t structure
271  */
snd_timer_ginfo_copy(snd_timer_ginfo_t * dst,const snd_timer_ginfo_t * src)272 void snd_timer_ginfo_copy(snd_timer_ginfo_t *dst, const snd_timer_ginfo_t *src)
273 {
274 	assert(dst && src);
275 	*dst = *src;
276 }
277 
278 /**
279  * \brief set timer identification
280  * \param obj pointer to #snd_timer_ginfo_t structure
281  * \param tid pointer to #snd_timer_id_t structure
282  * \return zero on success otherwise a negative error number
283  */
snd_timer_ginfo_set_tid(snd_timer_ginfo_t * obj,snd_timer_id_t * tid)284 int snd_timer_ginfo_set_tid(snd_timer_ginfo_t *obj, snd_timer_id_t *tid)
285 {
286 	obj->tid = *((snd_timer_id_t *)tid);
287 	return 0;
288 }
289 
290 /**
291  * \brief get timer identification
292  * \param obj pointer to #snd_timer_ginfo_t structure
293  * \return pointer to snd_timer_id_t
294  */
snd_timer_ginfo_get_tid(snd_timer_ginfo_t * obj)295 snd_timer_id_t *snd_timer_ginfo_get_tid(snd_timer_ginfo_t *obj)
296 {
297 	return (snd_timer_id_t *)&obj->tid;
298 }
299 
300 /**
301  * \brief get timer flags
302  * \param obj pointer to #snd_timer_ginfo_t structure
303  * \return timer flags
304  */
snd_timer_ginfo_get_flags(snd_timer_ginfo_t * obj)305 unsigned int snd_timer_ginfo_get_flags(snd_timer_ginfo_t *obj)
306 {
307 	return obj->flags;
308 }
309 
310 /**
311  * \brief get associated card with timer
312  * \param obj pointer to #snd_timer_ginfo_t structure
313  * \return associated card
314  */
snd_timer_ginfo_get_card(snd_timer_ginfo_t * obj)315 int snd_timer_ginfo_get_card(snd_timer_ginfo_t *obj)
316 {
317 	return obj->card;
318 }
319 
320 /**
321  * \brief get timer identification
322  * \param obj pointer to #snd_timer_ginfo_t structure
323  * \return timer identification
324  */
snd_timer_ginfo_get_id(snd_timer_ginfo_t * obj)325 char *snd_timer_ginfo_get_id(snd_timer_ginfo_t *obj)
326 {
327 	return (char *)obj->id;
328 }
329 
330 /**
331  * \brief get timer name
332  * \param obj pointer to #snd_timer_ginfo_t structure
333  * \return timer name
334  */
snd_timer_ginfo_get_name(snd_timer_ginfo_t * obj)335 char *snd_timer_ginfo_get_name(snd_timer_ginfo_t *obj)
336 {
337 	return (char *)obj->name;
338 }
339 
340 /**
341  * \brief get timer resolution in ns
342  * \param obj pointer to #snd_timer_ginfo_t structure
343  * \return timer resolution in ns
344  */
snd_timer_ginfo_get_resolution(snd_timer_ginfo_t * obj)345 unsigned long snd_timer_ginfo_get_resolution(snd_timer_ginfo_t *obj)
346 {
347 	return obj->resolution;
348 }
349 
350 /**
351  * \brief get timer minimal resolution in ns
352  * \param obj pointer to #snd_timer_ginfo_t structure
353  * \return timer minimal resolution in ns
354  */
snd_timer_ginfo_get_resolution_min(snd_timer_ginfo_t * obj)355 unsigned long snd_timer_ginfo_get_resolution_min(snd_timer_ginfo_t *obj)
356 {
357 	return obj->resolution_min;
358 }
359 
360 /**
361  * \brief get timer maximal resolution in ns
362  * \param obj pointer to #snd_timer_ginfo_t structure
363  * \return timer maximal resolution in ns
364  */
snd_timer_ginfo_get_resolution_max(snd_timer_ginfo_t * obj)365 unsigned long snd_timer_ginfo_get_resolution_max(snd_timer_ginfo_t *obj)
366 {
367 	return obj->resolution_max;
368 }
369 
370 /**
371  * \brief get current timer clients
372  * \param obj pointer to #snd_timer_ginfo_t structure
373  * \return current timer clients
374  */
snd_timer_ginfo_get_clients(snd_timer_ginfo_t * obj)375 unsigned int snd_timer_ginfo_get_clients(snd_timer_ginfo_t *obj)
376 {
377 	return obj->clients;
378 }
379 
380 /**
381  * \brief obtain the timer global information
382  * \param timer timer handle
383  * \param info timer information
384  * \return 0 on success otherwise a negative error code
385  */
386 #ifndef DOXYGEN
INTERNAL(snd_timer_query_info)387 EXPORT_SYMBOL int INTERNAL(snd_timer_query_info)(snd_timer_query_t *timer, snd_timer_ginfo_t *info)
388 #else
389 int snd_timer_query_info(snd_timer_query_t *timer, snd_timer_ginfo_t *info)
390 #endif
391 {
392   	assert(timer);
393   	assert(info);
394 	return timer->ops->info(timer, info);
395 }
396 use_default_symbol_version(__snd_timer_query_info, snd_timer_query_info, ALSA_0.9.0);
397 
398 /**
399  * \brief set the timer global parameters
400  * \param timer timer handle
401  * \param params timer parameters
402  * \return 0 on success otherwise a negative error code
403  */
404 #ifndef DOXYGEN
INTERNAL(snd_timer_query_params)405 EXPORT_SYMBOL int INTERNAL(snd_timer_query_params)(snd_timer_query_t *timer, snd_timer_gparams_t *params)
406 #else
407 int snd_timer_query_params(snd_timer_query_t *timer, snd_timer_gparams_t *params)
408 #endif
409 {
410   	assert(timer);
411   	assert(params);
412 	return timer->ops->params(timer, params);
413 }
414 use_default_symbol_version(__snd_timer_query_params, snd_timer_query_params, ALSA_0.9.0);
415 
416 /**
417  * \brief get the timer global status
418  * \param timer timer handle
419  * \param status timer status
420  * \return 0 on success otherwise a negative error code
421  */
422 #ifndef DOXYGEN
INTERNAL(snd_timer_query_status)423 EXPORT_SYMBOL int INTERNAL(snd_timer_query_status)(snd_timer_query_t *timer, snd_timer_gstatus_t *status)
424 #else
425 int snd_timer_query_status(snd_timer_query_t *timer, snd_timer_gstatus_t *status)
426 #endif
427 {
428   	assert(timer);
429   	assert(status);
430 	return timer->ops->status(timer, status);
431 }
432 use_default_symbol_version(__snd_timer_query_status, snd_timer_query_status, ALSA_0.9.0);
433 
434 /**
435  * \brief get size of the snd_timer_id_t structure in bytes
436  * \return size of the snd_timer_id_t structure in bytes
437  */
snd_timer_id_sizeof()438 size_t snd_timer_id_sizeof()
439 {
440 	return sizeof(snd_timer_id_t);
441 }
442 
443 /**
444  * \brief allocate a new snd_timer_id_t structure
445  * \param info returned pointer
446  * \return 0 on success otherwise a negative error code if fails
447  *
448  * Allocates a new snd_timer_id_t structure using the standard
449  * malloc C library function.
450  */
snd_timer_id_malloc(snd_timer_id_t ** info)451 int snd_timer_id_malloc(snd_timer_id_t **info)
452 {
453 	assert(info);
454 	*info = calloc(1, sizeof(snd_timer_id_t));
455 	if (!*info)
456 		return -ENOMEM;
457 	return 0;
458 }
459 
460 /**
461  * \brief frees the snd_timer_id_t structure
462  * \param info pointer to the snd_timer_id_t structure to free
463  *
464  * Frees the given snd_timer_id_t structure using the standard
465  * free C library function.
466  */
snd_timer_id_free(snd_timer_id_t * info)467 void snd_timer_id_free(snd_timer_id_t *info)
468 {
469 	assert(info);
470 	free(info);
471 }
472 
473 /**
474  * \brief copy one snd_timer_id_t structure to another
475  * \param dst destination snd_timer_id_t structure
476  * \param src source snd_timer_id_t structure
477  */
snd_timer_id_copy(snd_timer_id_t * dst,const snd_timer_id_t * src)478 void snd_timer_id_copy(snd_timer_id_t *dst, const snd_timer_id_t *src)
479 {
480 	assert(dst && src);
481 	*dst = *src;
482 }
483 
484 /**
485  * \brief set timer class
486  * \param tid pointer to #snd_timer_id_t structure
487  * \param dev_class class of timer device
488  */
snd_timer_id_set_class(snd_timer_id_t * tid,int dev_class)489 void snd_timer_id_set_class(snd_timer_id_t * tid, int dev_class)
490 {
491 	assert(tid);
492 	tid->dev_class = dev_class;
493 }
494 
495 /**
496  * \brief get timer class
497  * \param tid pointer to #snd_timer_id_t structure
498  * \return timer class
499  */
snd_timer_id_get_class(snd_timer_id_t * tid)500 int snd_timer_id_get_class(snd_timer_id_t * tid)
501 {
502 	assert(tid);
503 	return tid->dev_class;
504 }
505 
506 /**
507  * \brief set timer sub-class
508  * \param tid pointer to #snd_timer_id_t structure
509  * \param dev_sclass sub-class of timer device
510  */
snd_timer_id_set_sclass(snd_timer_id_t * tid,int dev_sclass)511 void snd_timer_id_set_sclass(snd_timer_id_t * tid, int dev_sclass)
512 {
513 	assert(tid);
514 	tid->dev_sclass = dev_sclass;
515 }
516 
517 /**
518  * \brief get timer sub-class
519  * \param tid pointer to #snd_timer_id_t structure
520  * \return timer sub-class
521  */
snd_timer_id_get_sclass(snd_timer_id_t * tid)522 int snd_timer_id_get_sclass(snd_timer_id_t * tid)
523 {
524 	assert(tid);
525 	return tid->dev_sclass;
526 }
527 
528 /**
529  * \brief set timer card
530  * \param tid pointer to #snd_timer_id_t structure
531  * \param card card number
532  */
snd_timer_id_set_card(snd_timer_id_t * tid,int card)533 void snd_timer_id_set_card(snd_timer_id_t * tid, int card)
534 {
535 	assert(tid);
536 	tid->card = card;
537 }
538 
539 /**
540  * \brief get timer card
541  * \param tid pointer to #snd_timer_id_t structure
542  * \return timer card number
543  */
snd_timer_id_get_card(snd_timer_id_t * tid)544 int snd_timer_id_get_card(snd_timer_id_t * tid)
545 {
546 	assert(tid);
547 	return tid->card;
548 }
549 
550 /**
551  * \brief set timer device
552  * \param tid pointer to #snd_timer_id_t structure
553  * \param device device number
554  */
snd_timer_id_set_device(snd_timer_id_t * tid,int device)555 void snd_timer_id_set_device(snd_timer_id_t * tid, int device)
556 {
557 	assert(tid);
558 	tid->device = device;
559 }
560 
561 /**
562  * \brief get timer device
563  * \param tid pointer to #snd_timer_id_t structure
564  * \return timer device number
565  */
snd_timer_id_get_device(snd_timer_id_t * tid)566 int snd_timer_id_get_device(snd_timer_id_t * tid)
567 {
568 	assert(tid);
569 	return tid->device;
570 }
571 
572 /**
573  * \brief set timer subdevice
574  * \param tid pointer to #snd_timer_id_t structure
575  * \param subdevice subdevice number
576  */
snd_timer_id_set_subdevice(snd_timer_id_t * tid,int subdevice)577 void snd_timer_id_set_subdevice(snd_timer_id_t * tid, int subdevice)
578 {
579 	assert(tid);
580 	tid->subdevice = subdevice;
581 }
582 
583 /**
584  * \brief get timer subdevice
585  * \param tid pointer to #snd_timer_id_t structure
586  * \return timer subdevice number
587  */
snd_timer_id_get_subdevice(snd_timer_id_t * tid)588 int snd_timer_id_get_subdevice(snd_timer_id_t * tid)
589 {
590 	assert(tid);
591 	return tid->subdevice;
592 }
593