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