aboutsummaryrefslogtreecommitdiffstats
path: root/alsa-binding
diff options
context:
space:
mode:
authorFulup Ar Foll <fulup@iot.bzh>2017-11-04 15:03:58 +0100
committerFulup Ar Foll <fulup@iot.bzh>2017-11-04 15:03:58 +0100
commit665073e727623ac7228a86b003004956bf774adb (patch)
tree2557181f3d631a834fe7055893e1b42c47a7b618 /alsa-binding
parenteac54aceceb2b465340fb6beb4ef635cb46d8237 (diff)
Added PcmInfo API
Change HAL register to fallback to driver name when not direct match found
Diffstat (limited to 'alsa-binding')
-rw-r--r--alsa-binding/Alsa-ApiHat.c1
-rw-r--r--alsa-binding/Alsa-ApiHat.h12
-rw-r--r--alsa-binding/Alsa-RegEvt.c188
-rw-r--r--alsa-binding/CMakeLists.txt1
4 files changed, 188 insertions, 14 deletions
diff --git a/alsa-binding/Alsa-ApiHat.c b/alsa-binding/Alsa-ApiHat.c
index 14ab903..a5220e2 100644
--- a/alsa-binding/Alsa-ApiHat.c
+++ b/alsa-binding/Alsa-ApiHat.c
@@ -48,6 +48,7 @@ static const struct afb_verb_v2 api_verbs[] = {
{ .verb = "cardidget", .callback = alsaGetCardId, .info="get sound card id"},
{ .verb = "halregister", .callback = alsaRegisterHal, .info="register a new HAL in alsacore"},
{ .verb = "hallist", .callback = alsaActiveHal, .info="Get list of currently active HAL"},
+ { .verb = "pcminfo", .callback = alsaPcmInfo, .info="Get Alsa Info About a given PCM"},
{ .verb = "ucmquery", .callback = alsaUseCaseQuery,.info="Use Case Manager Query"},
{ .verb = "ucmset", .callback = alsaUseCaseSet,.info="Use Case Manager set"},
{ .verb = "ucmget", .callback = alsaUseCaseGet,.info="Use Case Manager Get"},
diff --git a/alsa-binding/Alsa-ApiHat.h b/alsa-binding/Alsa-ApiHat.h
index c0e1a1a..97517f3 100644
--- a/alsa-binding/Alsa-ApiHat.h
+++ b/alsa-binding/Alsa-ApiHat.h
@@ -26,8 +26,6 @@
#define AFB_BINDING_VERSION 2
#include <afb/afb-binding.h>
#include <json-c/json.h>
-#include <filescan-utils.h>
-#include <wrap-json.h>
// Waiting for official macro from José
#define AFB_GET_VERBOSITY afb_get_verbosity_v2()
@@ -35,6 +33,15 @@
// Soft control have dynamically allocated numid
#define CTL_AUTO -1
+#ifndef PUBLIC
+ #define PUBLIC
+#endif
+#define STATIC static
+
+#ifndef CONTROL_MAXPATH_LEN
+ #define CONTROL_MAXPATH_LEN 255
+#endif
+
typedef enum {
QUERY_QUIET =0,
QUERY_COMPACT =1,
@@ -87,6 +94,7 @@ PUBLIC void alsaEvtSubcribe (struct afb_req request);
PUBLIC void alsaGetCardId (struct afb_req request);
PUBLIC void alsaRegisterHal (struct afb_req request);
PUBLIC void alsaActiveHal (struct afb_req request);
+PUBLIC void alsaPcmInfo (struct afb_req request);
#endif /* ALSALIBMAPPING_H */
diff --git a/alsa-binding/Alsa-RegEvt.c b/alsa-binding/Alsa-RegEvt.c
index ce81721..be46c17 100644
--- a/alsa-binding/Alsa-RegEvt.c
+++ b/alsa-binding/Alsa-RegEvt.c
@@ -37,8 +37,10 @@ typedef struct {
} sndHandleT;
typedef struct {
+ int cardid;
char *devid;
char *apiprefix;
+ char *drivername;
char *shortname;
char *longname;
} cardRegistryT;
@@ -247,20 +249,32 @@ OnErrorExit:
STATIC json_object *alsaProbeCardId(afb_req request) {
char devid [10];
- const char *ctlName, *shortname, *longname;
- int card, err, index, idx;
- json_object *responseJ;
+ const char *ctlName, *shortname, *longname, *mixername, *drivername;
+ int done, mode, card, err, index, idx;
+ json_object *responseJ, *tmpJ;
snd_ctl_t *ctlDev;
snd_ctl_card_info_t *cardinfo;
- const char *sndname = afb_req_value(request, "sndname");
- if (sndname == NULL) {
+ json_object* queryJ = afb_req_json(request);
+
+ done = json_object_object_get_ex(queryJ, "sndname", &tmpJ);
+ if (!done || json_object_get_type(tmpJ) != json_type_string) {
afb_req_fail_f(request, "argument-missing", "sndname=SndCardName missing");
goto OnErrorExit;
}
+ const char *sndname = json_object_get_string(tmpJ);
+
+ done = json_object_object_get_ex(queryJ, "mode", &tmpJ);
+ if (!done) {
+ mode = 0;
+ } else {
+ mode = json_object_get_int(tmpJ);
+ }
+
// loop on potential card number
snd_ctl_card_info_alloca(&cardinfo);
+ char *driverId = NULL; // when not name match use drivername as backup plan
for (card = 0; card < MAX_SND_CARD; card++) {
// build card devid and probe it
@@ -276,26 +290,60 @@ STATIC json_object *alsaProbeCardId(afb_req request) {
ctlName = snd_ctl_card_info_get_id(cardinfo);
shortname = snd_ctl_card_info_get_name(cardinfo);
longname = snd_ctl_card_info_get_longname(cardinfo);
+ mixername = snd_ctl_card_info_get_mixername(cardinfo);
+ drivername = snd_ctl_card_info_get_driver(cardinfo);
snd_ctl_close(ctlDev);
// check if short|long name match
- if (!strcmp(sndname, ctlName)) break;
- if (!strcmp(sndname, shortname)) break;
- if (!strcmp(sndname, longname)) break;
+ if (!strcasecmp(sndname, ctlName)) break;
+ if (!strcasecmp(sndname, shortname)) break;
+ if (!strcasecmp(sndname, drivername) && driverId==NULL) {
+ driverId=strdup(devid);
+ }
+ if (!strcasecmp(sndname, longname)) break;
}
if (card == MAX_SND_CARD) {
- afb_req_fail_f(request, "ctlDev-notfound", "Fail to find card with name=%s", sndname);
- goto OnErrorExit;
+ if (!driverId) {
+ afb_req_fail_f(request, "ctlDev-notfound", "Fail to find card with name=%s", sndname);
+ goto OnErrorExit;
+ }
+
+
+ err = snd_ctl_open(&ctlDev, driverId, SND_CTL_READONLY);
+ if (err < 0) {
+ afb_req_fail_f(request, "ctlDev-notfound", "Fail to find card with name=%s devid=%s", sndname, devid);
+ goto OnErrorExit;
+ }
+
+
+ // Sound not found by name, backup to driver name
+ snd_ctl_card_info(ctlDev, cardinfo);
+ index = snd_ctl_card_info_get_card(cardinfo);
+ ctlName = snd_ctl_card_info_get_id(cardinfo);
+ shortname = snd_ctl_card_info_get_name(cardinfo);
+ longname = snd_ctl_card_info_get_longname(cardinfo);
+ mixername = snd_ctl_card_info_get_mixername(cardinfo);
+ drivername = snd_ctl_card_info_get_driver(cardinfo);
+ AFB_WARNING("alsaProbeCardId Fallbak to HAL=%s ==> devid=%s name=%s long=%s\n ", drivername, driverId, shortname, longname);
+ free(driverId);
+ snd_ctl_close(ctlDev);
}
// proxy ctlevent as a binder event
responseJ = json_object_new_object();
json_object_object_add(responseJ, "index", json_object_new_int(index));
+ json_object_object_add(responseJ, "cardid", json_object_new_int(card));
json_object_object_add(responseJ, "devid", json_object_new_string(devid));
json_object_object_add(responseJ, "shortname", json_object_new_string(shortname));
- json_object_object_add(responseJ, "longname", json_object_new_string(longname));
+
+ if (mode > 0) {
+ json_object_object_add(responseJ, "longname", json_object_new_string(longname));
+ json_object_object_add(responseJ, "mixername", json_object_new_string(mixername));
+ json_object_object_add(responseJ, "drivername", json_object_new_string(drivername));
+
+ }
// search for a HAL binder card mapping name to api prefix
for (idx = 0; (idx < MAX_SND_CARD && cardRegistry[idx]); idx++) {
@@ -319,6 +367,29 @@ PUBLIC void alsaGetCardId(afb_req request) {
if (responseJ) afb_req_success(request, responseJ, NULL);
}
+
+// Return HAL information about a given sound card ID
+
+STATIC int getHalFromCardId(int cardid, json_object *responseJ) {
+
+ for (int idx = 0; idx < MAX_SND_CARD; idx++) {
+ if (!cardRegistry[idx]) goto OnErrorExit;
+
+ if (cardRegistry[idx]->cardid == cardid) {
+ json_object_object_add(responseJ, "api", json_object_new_string(cardRegistry[idx]->apiprefix));
+ if (cardRegistry[idx]->shortname)json_object_object_add(responseJ, "shortname", json_object_new_string(cardRegistry[idx]->shortname));
+ if (cardRegistry[idx]->longname) json_object_object_add(responseJ, "longname", json_object_new_string(cardRegistry[idx]->longname));
+ break;
+ }
+ }
+
+ return 0;
+
+OnErrorExit:
+ return -1;
+}
+
+
// Return list of active resgistrated HAL with corresponding sndcard
PUBLIC void alsaActiveHal(afb_req request) {
@@ -331,6 +402,7 @@ PUBLIC void alsaActiveHal(afb_req request) {
json_object_object_add(haldevJ, "api", json_object_new_string(cardRegistry[idx]->apiprefix));
if (cardRegistry[idx]->devid) json_object_object_add(haldevJ, "devid", json_object_new_string(cardRegistry[idx]->devid));
if (cardRegistry[idx]->shortname)json_object_object_add(haldevJ, "shortname", json_object_new_string(cardRegistry[idx]->shortname));
+ if (cardRegistry[idx]->drivername)json_object_object_add(haldevJ, "drivername", json_object_new_string(cardRegistry[idx]->drivername));
if (cardRegistry[idx]->longname) json_object_object_add(haldevJ, "longname", json_object_new_string(cardRegistry[idx]->longname));
json_object_array_add(responseJ, haldevJ);
}
@@ -372,11 +444,18 @@ PUBLIC void alsaRegisterHal(afb_req request) {
cardRegistry[index] = malloc(sizeof (cardRegistry));
cardRegistry[index]->apiprefix = strdup(apiPrefix);
cardRegistry[index]->shortname = strdup(shortname);
+
+ json_object_object_get_ex(responseJ, "cardid", &tmpJ);
+ cardRegistry[index]->cardid = json_object_get_int(tmpJ);
done = json_object_object_get_ex(responseJ, "devid", &tmpJ);
if (done) cardRegistry[index]->devid = strdup(json_object_get_string(tmpJ));
else cardRegistry[index]->devid = NULL;
+ done = json_object_object_get_ex(responseJ, "drivername", &tmpJ);
+ if (done) cardRegistry[index]->drivername = strdup(json_object_get_string(tmpJ));
+ else cardRegistry[index]->drivername = NULL;
+
done = json_object_object_get_ex(responseJ, "longname", &tmpJ);
if (done) cardRegistry[index]->longname = strdup(json_object_get_string(tmpJ));
else cardRegistry[index]->longname = NULL;
@@ -395,3 +474,90 @@ OnErrorExit:
return;
}
+PUBLIC void alsaPcmInfo (struct afb_req request) {
+ int done, mode, err;
+ json_object *tmpJ, *responseJ = NULL;
+ snd_pcm_t *pcmHandle = NULL;
+ snd_pcm_info_t * pcmInfo = NULL;
+
+ json_object* queryJ = afb_req_json(request);
+
+ done = json_object_object_get_ex(queryJ, "name", &tmpJ);
+ if (!done || json_object_get_type(tmpJ) != json_type_string) {
+ afb_req_fail_f(request, "name:invalid", "PCM 'name:xxx' missing or not a string query='%s'", json_object_get_string(queryJ));
+ goto OnErrorExit;
+ }
+ const char *pcmName = json_object_get_string(tmpJ);
+
+ done = json_object_object_get_ex(queryJ, "stream", &tmpJ);
+ if (done && json_object_get_type(tmpJ) != json_type_int) {
+ afb_req_fail_f(request, "stream:invalid", "PCM 'stream:SND_PCM_STREAM_PLAYBACK/SND_PCM_STREAM_CAPTURE' should be integer query='%s'", json_object_get_string(queryJ));
+ goto OnErrorExit;
+ }
+ snd_pcm_stream_t pcmStream = json_object_get_int(tmpJ);
+
+ done = json_object_object_get_ex(queryJ, "mode", &tmpJ);
+ if (!done) {
+ mode = 0;
+ } else {
+ mode = json_object_get_int(tmpJ);
+ }
+
+ // open PCM from its name
+ err= snd_pcm_open(&pcmHandle, pcmName, pcmStream, 0);
+ if (err < 0) {
+ afb_req_fail_f(request, "pcm:invalid", "PCM 'name:%s' does cannot open error=%s", pcmName, snd_strerror(err));
+ goto OnErrorExit;
+ }
+
+ // get pcm info
+ snd_pcm_info_alloca(&pcmInfo);
+ err = snd_pcm_info(pcmHandle,pcmInfo);
+ if (err < 0) {
+ afb_req_fail_f(request, "pcm:error", "PCM 'name:%s' fail to retrieve info error=%s", pcmName, snd_strerror(err));
+ goto OnErrorExit;
+ }
+
+ // get sub-device number
+ int cardId = snd_pcm_info_get_card(pcmInfo);
+ if (cardId < 0 ) {
+ afb_req_fail_f(request, "pcm:error", "PCM 'name:%s' fail to retrieve sndcard device error=%s", pcmName, snd_strerror(cardId));
+ goto OnErrorExit;
+ }
+
+ // prepare an object for response
+ responseJ = json_object_new_object();
+
+ err = getHalFromCardId (cardId, responseJ);
+ if (err < 0 ) {
+ afb_req_fail_f(request, "pcm:error", "PCM 'name:%s' snddev=hw:%d fail to retrieve hal API", pcmName, cardId);
+ goto OnErrorExit;
+ }
+
+ json_object_object_add(responseJ, "type", json_object_new_int(snd_pcm_type(pcmHandle)));
+
+ // in mode mode we return full info about PCM
+ if (mode > 0) {
+ json_object_object_add(responseJ, "stream", json_object_new_int(snd_pcm_info_get_stream (pcmInfo)));
+ json_object_object_add(responseJ, "cardid", json_object_new_int(snd_pcm_info_get_card(pcmInfo)));
+ json_object_object_add(responseJ, "devid" , json_object_new_int(snd_pcm_info_get_device (pcmInfo)));
+ json_object_object_add(responseJ, "subid" , json_object_new_int(snd_pcm_info_get_subdevice (pcmInfo)));
+ }
+
+ // in super mode we also return information about snd card
+ if (mode > 1) {
+
+ json_object_object_add(responseJ, "id" , json_object_new_string(snd_pcm_info_get_id (pcmInfo)));
+ json_object_object_add(responseJ, "name" , json_object_new_string(snd_pcm_info_get_name (pcmInfo)));
+ json_object_object_add(responseJ, "subdev" , json_object_new_string(snd_pcm_info_get_subdevice_name (pcmInfo)));
+ }
+
+ afb_req_success(request, responseJ, NULL);
+ snd_pcm_close (pcmHandle);
+ return;
+
+OnErrorExit:
+ if (responseJ) json_object_put (responseJ);
+ if (pcmHandle) snd_pcm_close (pcmHandle);
+ return;
+}
diff --git a/alsa-binding/CMakeLists.txt b/alsa-binding/CMakeLists.txt
index 9e3129c..5f683d6 100644
--- a/alsa-binding/CMakeLists.txt
+++ b/alsa-binding/CMakeLists.txt
@@ -32,7 +32,6 @@ PROJECT_TARGET_ADD(alsa-4a)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
- afb-utilities
${link_libraries}
)