diff options
Diffstat (limited to 'alsa-binding')
-rw-r--r-- | alsa-binding/Alsa-ApiHat.h | 5 | ||||
-rw-r--r-- | alsa-binding/Alsa-SetGet.c | 90 |
2 files changed, 75 insertions, 20 deletions
diff --git a/alsa-binding/Alsa-ApiHat.h b/alsa-binding/Alsa-ApiHat.h index 97517f3..f5feacd 100644 --- a/alsa-binding/Alsa-ApiHat.h +++ b/alsa-binding/Alsa-ApiHat.h @@ -50,6 +50,11 @@ typedef enum { } queryModeE; typedef enum { + INFO_BY_DEVID, + INFO_BY_PATH +} InfoGetT; + +typedef enum { ACTION_SET, ACTION_GET } ActionSetGetT; diff --git a/alsa-binding/Alsa-SetGet.c b/alsa-binding/Alsa-SetGet.c index 1b7d4a8..6681415 100644 --- a/alsa-binding/Alsa-SetGet.c +++ b/alsa-binding/Alsa-SetGet.c @@ -26,8 +26,16 @@ */ #define _GNU_SOURCE // needed for vasprintf + +#include <sys/ioctl.h> + #include "Alsa-ApiHat.h" +// extracted IOCTLs from <alsa/asoundlib.h> +#define _IOR_HACKED(type,nr,size) _IOC(_IOC_READ,(type),(nr),size) +#define SNDRV_CTL_IOCTL_CARD_INFO(size) _IOR_HACKED('U', 0x01, size) + + PUBLIC void NumidsListParse(ActionSetGetT action, queryValuesT *queryValues, ctlRequestT *ctlRequest) { int length; @@ -332,45 +340,79 @@ STATIC json_object *decodeTlv(unsigned int *tlv, unsigned int tlv_size, int mode // retreive info for one given card -STATIC json_object* alsaCardProbe(const char *rqtSndId) { +STATIC json_object* alsaCardProbe(const char *rqt, InfoGetT infoType) { const char *info, *name; - const char *devid, *driver; + const char *driver; + char devid[6]; json_object *ctlDev; snd_ctl_t *handle; snd_ctl_card_info_t *cardinfo; - int err; - - if ((err = snd_ctl_open(&handle, rqtSndId, 0)) < 0) { - AFB_INFO("alsaCardProbe '%s' Not Found", rqtSndId); - return NULL; - } + int err, open_dev; snd_ctl_card_info_alloca(&cardinfo); - if ((err = snd_ctl_card_info(handle, cardinfo)) < 0) { - snd_ctl_close(handle); - AFB_WARNING("SndCard '%s' info error: %s", rqtSndId, snd_strerror(err)); - return NULL; + + switch(infoType) { + case INFO_BY_DEVID: + if((snd_ctl_open(&handle, rqt, 0)) < 0) { + AFB_INFO("%s: '%s' Not Found", __func__, rqt); + return NULL; + } + + err = snd_ctl_card_info(handle, cardinfo); + + snd_ctl_close(handle); + + if(err < 0) { + AFB_WARNING("%s: SndCard '%s' info error: %s", __func__, rqt, snd_strerror(err)); + return NULL; + } + + break; + + case INFO_BY_PATH: + if(! rqt) { + AFB_INFO("%s: no dev path specified", __func__); + return NULL; + } + + open_dev = open(rqt, O_RDONLY); + if(open_dev < 0) { + AFB_WARNING("%s: DevPath '%s' open error: %i", __func__, rqt, open_dev); + return NULL; + } + + err = ioctl(open_dev, SNDRV_CTL_IOCTL_CARD_INFO(snd_ctl_card_info_sizeof()), cardinfo); + + close(open_dev); + + if(err < 0) { + AFB_WARNING("%s: DevPath '%s' ioctl error: %i", __func__, rqt, err); + return NULL; + } + + break; } // start a new json object to store card info ctlDev = json_object_new_object(); - devid = snd_ctl_card_info_get_id(cardinfo); + snprintf(devid, 6, "hw:%i", snd_ctl_card_info_get_card(cardinfo)); json_object_object_add(ctlDev, "devid", json_object_new_string(devid)); name = snd_ctl_card_info_get_name(cardinfo); json_object_object_add(ctlDev, "name", json_object_new_string(name)); if (AFB_GET_VERBOSITY > 1) { - json_object_object_add(ctlDev, "devid", json_object_new_string(rqtSndId)); driver = snd_ctl_card_info_get_driver(cardinfo); json_object_object_add(ctlDev, "driver", json_object_new_string(driver)); info = strdup(snd_ctl_card_info_get_longname(cardinfo)); json_object_object_add(ctlDev, "info", json_object_new_string(info)); - AFB_INFO("AJG: Soundcard Devid=%-5s devid=%-7s Name=%s\n", rqtSndId, devid, info); + if(infoType == INFO_BY_DEVID) + AFB_INFO("AJG: Soundcard Devid=%-5s devid=%-7s Name=%s\n", rqt, devid, info); + else if(infoType == INFO_BY_DEVID) + AFB_INFO("AJG: Soundcard DevPath=%-5s devid=%-7s Name=%s\n", rqt, devid, info); } - // free card handle and return info - snd_ctl_close(handle); + // return info return (ctlDev); } @@ -382,16 +424,24 @@ PUBLIC void alsaGetInfo(afb_req request) { char devid[32]; const char *rqtSndId = afb_req_value(request, "devid"); + const char *rqtDevPath = afb_req_value(request, "devpath"); // if no specific card requested loop on all if (rqtSndId != NULL) { // only one card was requested let's probe it - ctlDev = alsaCardProbe(rqtSndId); + ctlDev = alsaCardProbe(rqtSndId, INFO_BY_DEVID); if (ctlDev != NULL) afb_req_success(request, ctlDev, NULL); else afb_req_fail_f(request, "sndscard-notfound", "SndCard '%s' Not Found", rqtSndId); - } else { + } + else if (rqtDevPath != NULL) { + // only one card was requested let's probe it + ctlDev = alsaCardProbe(rqtDevPath, INFO_BY_PATH); + if (ctlDev != NULL) afb_req_success(request, ctlDev, NULL); + else afb_req_fail_f(request, "sndscard-notfound", "SndCard '%s' Not Found", rqtSndId); + } + else { // return an array of ctlDev ctlDevs = json_object_new_array(); @@ -400,7 +450,7 @@ PUBLIC void alsaGetInfo(afb_req request) { // build card devid and probe it snprintf(devid, sizeof (devid), "hw:%i", card); - ctlDev = alsaCardProbe(devid); + ctlDev = alsaCardProbe(devid, INFO_BY_DEVID); // Alsa has hole within card list [ignore them] if (ctlDev != NULL) { |