aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Aillet <jonathan.aillet@iot.bzh>2019-09-18 18:04:14 +0200
committerJonathan Aillet <jonathan.aillet@iot.bzh>2019-10-01 10:57:28 +0200
commit002dccbe68aae864f816f53b6ac92528bd42ab6d (patch)
treea15aa9131a0394c8a7e639320503b5017cdaf0d7
parentce13200ec80d667418b796afbb7d55a5f66d1c76 (diff)
Add verb to get PCM availability
Add verb to get PCM availability, this verb will return a boolean json. PCM can be specified using two ways : - card & device & subdevice & stream - pcmName & stream BUG-AGL: SPEC-2834 Change-Id: I176fdc261fa117906a2af069d3ddd07d5941904c Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
-rw-r--r--alsa-binding/Alsa-ApiHat.c1
-rw-r--r--alsa-binding/Alsa-ApiHat.h7
-rw-r--r--alsa-binding/Alsa-SetGet.c145
3 files changed, 152 insertions, 1 deletions
diff --git a/alsa-binding/Alsa-ApiHat.c b/alsa-binding/Alsa-ApiHat.c
index 5575a9a..13c450c 100644
--- a/alsa-binding/Alsa-ApiHat.c
+++ b/alsa-binding/Alsa-ApiHat.c
@@ -42,6 +42,7 @@ static const afb_verb_t api_verbs[] = {
/* VERB'S NAME FUNCTION TO CALL */
{ .verb = "ping", .callback = pingtest, .info="Ping Presence Check on API"},
{ .verb = "infoget", .callback = alsaGetInfo, .info="Return sound cards list"},
+ { .verb = "pcmready", .callback = alsaGetPcmAvailability, .info="Get Pcm availability"},
{ .verb = "ctlget", .callback = alsaGetCtls, .info="Get one or many control values"},
{ .verb = "ctlset", .callback = alsaSetCtls, .info="Set one control or more"},
{ .verb = "subscribe", .callback = alsaEvtSubscribe, .info="subscribe to alsa events"},
diff --git a/alsa-binding/Alsa-ApiHat.h b/alsa-binding/Alsa-ApiHat.h
index 21aaa61..35f96bb 100644
--- a/alsa-binding/Alsa-ApiHat.h
+++ b/alsa-binding/Alsa-ApiHat.h
@@ -103,8 +103,13 @@ PUBLIC queryModeE alsaGetModeFromQuery(json_object *queryJ);
// AlseCoreSetGet exports
PUBLIC int getCardNbFromCardPath(char *cardPath);
PUBLIC json_object *getCardInfo(int card);
-PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, queryModeE queryMode);
PUBLIC void alsaGetInfo (afb_req_t request);
+PUBLIC int alsaGetPcmProcStatusFd(unsigned int card, unsigned int device, unsigned int subdevice, snd_pcm_stream_t pcmStream);
+PUBLIC int alsaIsPcmAvailableUsingPcmProcFd(int fd);
+PUBLIC int alsaIsPcmAvailableUsingId(unsigned int card, unsigned int device, unsigned int subdevice, snd_pcm_stream_t pcmStream);
+PUBLIC int alsaIsPcmAvailableUsingPcmName(char *pcmName, snd_pcm_stream_t pcmStream);
+PUBLIC void alsaGetPcmAvailability(afb_req_t request);
+PUBLIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRequestT *ctlRequest, queryModeE queryMode);
PUBLIC void alsaGetCtls(afb_req_t request);
PUBLIC void alsaSetCtls(afb_req_t request);
diff --git a/alsa-binding/Alsa-SetGet.c b/alsa-binding/Alsa-SetGet.c
index 78ac7e9..af96b86 100644
--- a/alsa-binding/Alsa-SetGet.c
+++ b/alsa-binding/Alsa-SetGet.c
@@ -37,6 +37,9 @@
#define _IOR_HACKED(type,nr,size) _IOC(_IOC_READ,(type),(nr),size)
#define SNDRV_CTL_IOCTL_CARD_INFO(size) _IOR_HACKED('U', 0x01, size)
+#define PCM_PROC_STATUS_STRING "/proc/asound/card%i/pcm%i%c/sub%i/status"
+#define PCM_PROC_AVAILABLE_PCM_STRING "closed"
+#define PCM_PROC_AVAILABLE_PCM_STRING_SIZE (sizeof(PCM_PROC_AVAILABLE_PCM_STRING) - 1)
PUBLIC void NumidsListParse(ActionSetGetT action, controlQueryValuesT *queryControlValues, ctlRequestT *ctlRequest) {
int length;
@@ -999,6 +1002,148 @@ PUBLIC void alsaGetInfo(afb_req_t request) {
afb_req_success(request, toReturnJ, "Found requested sound card(s) properties are available in returned Json");
}
+STATIC char *getAlsaPcmStatusFilePath(unsigned int card, unsigned int device, unsigned int subdevice, snd_pcm_stream_t stream)
+{
+ int err;
+ char *pcmStatusFilePath = NULL;
+
+ if(card > MAX_SND_CARD || device > MAX_CARD_DEVICES || subdevice > MAX_DEVICE_SUBDEVICES)
+ return NULL;
+
+ err = asprintf(&pcmStatusFilePath, PCM_PROC_STATUS_STRING, card, device, (stream == SND_PCM_STREAM_PLAYBACK) ? 'p' : 'c', subdevice);
+ if(err <= 0)
+ return NULL;
+
+ return pcmStatusFilePath;
+}
+
+PUBLIC int alsaGetPcmProcStatusFd(unsigned int card, unsigned int device, unsigned int subdevice, snd_pcm_stream_t pcmStream)
+{
+ int fd;
+
+ char *pcmStatusFilePath = NULL;
+
+ if(card > MAX_SND_CARD || device > MAX_CARD_DEVICES || subdevice > MAX_DEVICE_SUBDEVICES)
+ return -1;
+
+ pcmStatusFilePath = getAlsaPcmStatusFilePath(card, device, subdevice, pcmStream);
+ if(! pcmStatusFilePath)
+ return -2;
+
+ fd = open(pcmStatusFilePath, O_RDONLY | O_NONBLOCK);
+ if(fd < 0)
+ return -3;
+
+ return fd;
+}
+
+PUBLIC int alsaIsPcmAvailableUsingPcmProcFd(int fd)
+{
+ char statusFileContent[PCM_PROC_AVAILABLE_PCM_STRING_SIZE];
+
+ if(fd < 0)
+ return -1;
+
+ if(lseek(fd, 0, SEEK_SET) < 0)
+ return -2;
+
+ if(read(fd, statusFileContent, PCM_PROC_AVAILABLE_PCM_STRING_SIZE) < 0)
+ return -3;
+
+ if(! strncmp(statusFileContent, PCM_PROC_AVAILABLE_PCM_STRING, PCM_PROC_AVAILABLE_PCM_STRING_SIZE))
+ return 1;
+
+ return 0;
+}
+
+PUBLIC int alsaIsPcmAvailableUsingId(unsigned int card, unsigned int device, unsigned int subdevice, snd_pcm_stream_t pcmStream)
+{
+ int fd, pcmIsAvailable;
+
+ if(card > MAX_SND_CARD || device > MAX_CARD_DEVICES || subdevice > MAX_DEVICE_SUBDEVICES)
+ return -1;
+
+ fd = alsaGetPcmProcStatusFd(card, device, subdevice, pcmStream);
+ if(fd < 0)
+ return -2;
+
+ pcmIsAvailable = alsaIsPcmAvailableUsingPcmProcFd(fd);
+ if(pcmIsAvailable < 0) {
+ close(fd);
+ return -3;
+ }
+
+ close(fd);
+ return pcmIsAvailable;
+}
+
+PUBLIC int alsaIsPcmAvailableUsingPcmName(char *pcmName, snd_pcm_stream_t pcmStream)
+{
+ int card = NO_CARD_SELECTED, device = NO_DEVICE_SELECTED, subdevice = NO_SUBDEVICE_SELECTED, pcmIsAvailable;
+
+ if(! pcmName)
+ return -1;
+
+ if(sscanf(pcmName, "hw:%i,%i,%i", &card, &device, &subdevice) != 3)
+ return -2;
+
+ if(card < 0 || card > MAX_SND_CARD ||
+ device < 0 || device > MAX_CARD_DEVICES ||
+ subdevice < 0 || subdevice > MAX_DEVICE_SUBDEVICES)
+ return -3;
+
+ pcmIsAvailable = alsaIsPcmAvailableUsingId(card, device, subdevice, pcmStream);
+ if(pcmIsAvailable < 0)
+ return -4;
+
+ return pcmIsAvailable;
+}
+
+PUBLIC void alsaGetPcmAvailability(afb_req_t request)
+{
+ int wrapRet,
+ pcmIsAvailable,
+ card = NO_CARD_SELECTED,
+ device = NO_DEVICE_SELECTED,
+ subdevice = NO_SUBDEVICE_SELECTED;
+
+ char *pcmName = NULL;
+
+ snd_pcm_stream_t pcmStream;
+
+ json_object *queryJ;
+
+ queryJ = afb_req_json(request);
+ if(! queryJ) {
+ afb_req_fail(request, "invalid_request", "Request json is unavailable");
+ return;
+ }
+
+ wrapRet = wrap_json_unpack(queryJ,
+ "{s?:i, s?:i, s?:i, s?:s, s:i !}",
+ "card", &card,
+ "device", &device,
+ "subdevice", &subdevice,
+ "name", &pcmName,
+ "stream", &pcmStream);
+ if(wrapRet || (! pcmName && (card == NO_CARD_SELECTED || device == NO_DEVICE_SELECTED || subdevice == NO_SUBDEVICE_SELECTED))) {
+ afb_req_fail_f(request, "invalid_request", "Request json is invalid (%s)", json_object_get_string(queryJ));
+ return;
+ }
+
+ if(! pcmName)
+ pcmIsAvailable = alsaIsPcmAvailableUsingId(card, device, subdevice, pcmStream);
+ else
+ pcmIsAvailable = alsaIsPcmAvailableUsingPcmName(pcmName, pcmStream);
+
+ if(pcmIsAvailable < 0) {
+ afb_req_fail_f(request, "invalid_pcm", "Pcm specified in json is invalid (%s)", json_object_get_string(queryJ));
+ return;
+ }
+
+ afb_req_success(request, json_object_new_boolean(pcmIsAvailable), NULL);
+}
+
// pack Alsa element's ACL into a JSON object
STATIC json_object *getControlAcl(snd_ctl_elem_info_t *info) {