aboutsummaryrefslogtreecommitdiffstats
path: root/AlsaSound
diff options
context:
space:
mode:
Diffstat (limited to 'AlsaSound')
-rw-r--r--AlsaSound/CMakeLists.txt2
-rw-r--r--AlsaSound/CoreBinding/AlsaAfbBinding.c11
-rw-r--r--AlsaSound/CoreBinding/AlsaLibMapping.c107
-rw-r--r--AlsaSound/CoreBinding/AlsaLibMapping.h3
-rw-r--r--AlsaSound/CoreBinding/README.md3
-rw-r--r--AlsaSound/HALayer/CMakeLists.txt (renamed from AlsaSound/HardAbsLayer/CMakeLists.txt)3
-rw-r--r--AlsaSound/HALayer/IntelHda/CMakeLists.txt (renamed from AlsaSound/HardAbsLayer/IntelHda/CMakeLists.txt)2
-rw-r--r--AlsaSound/HALayer/IntelHda/IntelHdaHAL.c74
-rw-r--r--AlsaSound/HALayer/Shared/CMakeLists.txt30
-rw-r--r--AlsaSound/HALayer/Shared/SharedHalLib.c252
-rw-r--r--AlsaSound/HALayer/include/AlsaHalCtls.h (renamed from AlsaSound/include/AlsaMixerHal.h)30
-rw-r--r--AlsaSound/HALayer/include/AlsaHalIface.h52
-rw-r--r--AlsaSound/HALayer/include/MiscHelpers.h (renamed from AlsaSound/HardAbsLayer/IntelHda/IntelHdaLib.h)24
-rw-r--r--AlsaSound/HardAbsLayer/IntelHda/IntelHdaBinding.c82
-rw-r--r--AlsaSound/HardAbsLayer/IntelHda/IntelHdaLib.c138
15 files changed, 518 insertions, 295 deletions
diff --git a/AlsaSound/CMakeLists.txt b/AlsaSound/CMakeLists.txt
index 7b1d5e9..7356ca4 100644
--- a/AlsaSound/CMakeLists.txt
+++ b/AlsaSound/CMakeLists.txt
@@ -28,5 +28,5 @@ SET(link_libraries
)
ADD_SUBDIRECTORY(CoreBinding)
-ADD_SUBDIRECTORY(HardAbsLayer)
+ADD_SUBDIRECTORY(HALayer)
diff --git a/AlsaSound/CoreBinding/AlsaAfbBinding.c b/AlsaSound/CoreBinding/AlsaAfbBinding.c
index 2c5c789..4ae7ccc 100644
--- a/AlsaSound/CoreBinding/AlsaAfbBinding.c
+++ b/AlsaSound/CoreBinding/AlsaAfbBinding.c
@@ -40,11 +40,12 @@ static void localping(struct afb_req request) {
*/
static const struct afb_verb_desc_v1 binding_verbs[] = {
/* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
- { .name= "ping" , .session= AFB_SESSION_NONE, .callback= localping, .info= "Ping Binding" },
- { .name= "getinfo", .session= AFB_SESSION_NONE, .callback= alsaGetInfo, .info= "List All/One Sound Cards Info" },
- { .name= "getctl", .session= AFB_SESSION_NONE, .callback= alsaGetCtl, .info= "List All/One Controls from selected sndcard" },
- { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= alsaSubcribe, .info= "Subscribe to events from selected sndcard" },
- { .name= "getcardid", .session= AFB_SESSION_NONE, .callback= alsaGetCardId,.info= "Get CardId from its short/long name" },
+ { .name= "ping" , .session= AFB_SESSION_NONE, .callback= localping, .info= "Ping Binding" },
+ { .name= "getinfo", .session= AFB_SESSION_NONE, .callback= alsaGetInfo, .info= "List All/One Sound Cards Info" },
+ { .name= "getctl", .session= AFB_SESSION_NONE, .callback= alsaGetCtl, .info= "List All/One Controls from selected sndcard" },
+ { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= alsaSubcribe, .info= "Subscribe to events from selected sndcard" },
+ { .name= "getcardid", .session= AFB_SESSION_NONE, .callback= alsaGetCardId, .info= "Get CardId from its short/long name" },
+ { .name= "registerHal",.session= AFB_SESSION_NONE,.callback= alsaRegisterHal,.info= "Register Hal CardName/ApiPrefix" },
{ .name= NULL } /* marker for end of the array */
};
diff --git a/AlsaSound/CoreBinding/AlsaLibMapping.c b/AlsaSound/CoreBinding/AlsaLibMapping.c
index 8dc1772..900aa3d 100644
--- a/AlsaSound/CoreBinding/AlsaLibMapping.c
+++ b/AlsaSound/CoreBinding/AlsaLibMapping.c
@@ -52,6 +52,14 @@ typedef struct {
evtHandleT *evtHandle;
} sndHandleT;
+typedef struct {
+ char *apiprefix;
+ char *shortname;
+}cardRegistryT;
+
+cardRegistryT *cardRegistry[MAX_SND_CARD+1];
+
+
STATIC json_object *DB2StringJsonOject (long dB) {
char label [20];
if (dB < 0) {
@@ -511,7 +519,7 @@ PUBLIC void alsaGetCtl(struct afb_req request) {
json_object *query = afb_req_json(request);
afb_req_fail_f (request, "Query=%s NumID not integer &numid=%s&", json_object_to_json_string(query), rqtNumid);
- goto ExitOnError;
+ goto OnErrorExit;
};
const char *rqtQuiet = afb_req_value(request, "quiet");
@@ -520,18 +528,18 @@ PUBLIC void alsaGetCtl(struct afb_req request) {
json_object *query = afb_req_json(request);
afb_req_fail_f (request, "Query=%s NumID not integer &numid=%s&", json_object_to_json_string(query), rqtQuiet);
- goto ExitOnError;
+ goto OnErrorExit;
};
// Open sound we use Alsa high level API like amixer.c
if (!queryValues.devid || (err = snd_hctl_open(&handle, queryValues.devid, 0)) < 0) {
afb_req_fail_f (request, "alsaGetControl devid=[%s] open fail error=%s\n", queryValues.devid, snd_strerror(err));
- goto ExitOnError;
+ goto OnErrorExit;
}
if ((err = snd_hctl_load(handle)) < 0) {
afb_req_fail_f (request, "alsaGetControl devid=[%s] load fail error=%s\n", queryValues.devid, snd_strerror(err));
- goto ExitOnError;
+ goto OnErrorExit;
}
// allocate ram for ALSA elements
@@ -546,7 +554,7 @@ PUBLIC void alsaGetCtl(struct afb_req request) {
json_object_put(sndctrls); // we abandon request let's free response
afb_req_fail_f (request, "alsaGetControl devid=[%s/%s] snd_hctl_elem_info error: %s\n"
, queryValues.devid, snd_hctl_name(handle), snd_strerror(err));
- goto ExitOnError;
+ goto OnErrorExit;
}
// each control is added into a JSON array
@@ -559,7 +567,7 @@ PUBLIC void alsaGetCtl(struct afb_req request) {
return;
// nothing special only for debugger breakpoint
- ExitOnError:
+ OnErrorExit:
return;
}
@@ -587,7 +595,7 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void*
snd_ctl_event_alloca(&ctlEvent); // initialise event structure on stack
err = snd_ctl_read(evtHandle->ctl, ctlEvent);
- if (err < 0) goto ExitOnError;
+ if (err < 0) goto OnErrorExit;
// we only process sndctrl element
if (snd_ctl_event_get_type(ctlEvent) != SND_CTL_EVENT_ELEM) goto ExitOnSucess;
@@ -619,7 +627,7 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void*
ExitOnSucess:
return 0;
- ExitOnError:
+ OnErrorExit:
WARNING (afbIface, "sndCtlEventCB: ignored unsupported event type");
return (0);
}
@@ -636,14 +644,14 @@ PUBLIC void alsaSubcribe (struct afb_req request) {
const char *devid = afb_req_value(request, "devid");
if (devid == NULL) {
afb_req_fail_f (request, "devid-missing", "devid=hw:xxx missing");
- goto ExitOnError;
+ goto OnErrorExit;
}
// open control interface for devid
err = snd_ctl_open(&ctlHandle, devid, SND_CTL_READONLY);
if (err < 0) {
afb_req_fail_f (request, "devid-unknown", "SndCard devid=%s Not Found err=%d", devid, err);
- goto ExitOnError;
+ goto OnErrorExit;
}
// get sound card index use to search existing subscription
@@ -666,7 +674,7 @@ PUBLIC void alsaSubcribe (struct afb_req request) {
if (idxFree == -1) {
afb_req_fail_f (request, "register-toomany", "Cannot register new event Maxcard==%devent name=%s", idx);
snd_ctl_close(ctlHandle);
- goto ExitOnError;
+ goto OnErrorExit;
}
evtHandle = malloc (sizeof(evtHandleT));
@@ -680,7 +688,7 @@ PUBLIC void alsaSubcribe (struct afb_req request) {
if (err < 0) {
afb_req_fail_f (request, "subscribe-fail", "Cannot subscribe events from devid=%s err=%d", devid, err);
snd_ctl_close(ctlHandle);
- goto ExitOnError;
+ goto OnErrorExit;
}
// get pollfd attach to this sound board
@@ -691,7 +699,7 @@ PUBLIC void alsaSubcribe (struct afb_req request) {
if (err < 0) {
afb_req_fail_f (request, "register-mainloop", "Cannot hook events to mainloop devid=%s err=%d", devid, err);
snd_ctl_close(ctlHandle);
- goto ExitOnError;
+ goto OnErrorExit;
}
// create binder event attached to devid name
@@ -699,7 +707,7 @@ PUBLIC void alsaSubcribe (struct afb_req request) {
if (!afb_event_is_valid (evtHandle->afbevt)) {
afb_req_fail_f (request, "register-event", "Cannot register new binder event name=%s", devid);
snd_ctl_close(ctlHandle);
- goto ExitOnError;
+ goto OnErrorExit;
}
// everything looks OK let's move forward
@@ -710,7 +718,7 @@ PUBLIC void alsaSubcribe (struct afb_req request) {
err = afb_req_subscribe(request, evtHandle->afbevt);
if (err != 0) {
afb_req_fail_f (request, "register-eventname", "Cannot subscribe binder event name=%s [invalid channel]", devid, err);
- goto ExitOnError;
+ goto OnErrorExit;
}
// increase usage count and return success
@@ -718,14 +726,15 @@ PUBLIC void alsaSubcribe (struct afb_req request) {
afb_req_success(request, NULL, NULL);
return;
- ExitOnError:
+ OnErrorExit:
return;
}
// Subscribe to every Alsa CtlEvent send by a given board
PUBLIC void alsaGetCardId (struct afb_req request) {
char devid [10];
- int card, err, index;
+ const char *devname, *shortname, *longname;
+ int card, err, index, idx;
json_object *respJson;
snd_ctl_t *ctlHandle;
snd_ctl_card_info_t *cardinfo;
@@ -733,7 +742,7 @@ PUBLIC void alsaGetCardId (struct afb_req request) {
const char *sndname = afb_req_value(request, "sndname");
if (sndname == NULL) {
afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing");
- goto ExitOnError;
+ goto OnErrorExit;
}
// loop on potential card number
@@ -747,31 +756,77 @@ PUBLIC void alsaGetCardId (struct afb_req request) {
err = snd_ctl_open(&ctlHandle, devid, SND_CTL_READONLY);
if (err < 0) continue;
+ // extract sound card information
snd_ctl_card_info(ctlHandle, cardinfo);
index = snd_ctl_card_info_get_card(cardinfo);
-
+ devname = snd_ctl_card_info_get_id(cardinfo);
+ shortname= snd_ctl_card_info_get_name(cardinfo);
+ longname = snd_ctl_card_info_get_longname(cardinfo);
+
// check if short|long name match
- if (!strcmp (sndname, snd_ctl_card_info_get_id(cardinfo))) break;
- if (!strcmp (sndname, snd_ctl_card_info_get_name(cardinfo))) break;
- if (!strcmp (sndname, snd_ctl_card_info_get_longname(cardinfo))) break;
+ if (!strcmp (sndname, devname)) break;
+ if (!strcmp (sndname, shortname)) break;
+ if (!strcmp (sndname, longname)) break;
}
if (card == MAX_SND_CARD) {
afb_req_fail_f (request, "sndcard-notfound", "Fail to find card with name=%s", sndname);
- goto ExitOnError;
+ goto OnErrorExit;
}
// proxy ctlevent as a binder event
respJson = json_object_new_object();
json_object_object_add(respJson, "index" ,json_object_new_int (index));
json_object_object_add(respJson, "devid" ,json_object_new_string (devid));
- json_object_object_add(respJson, "shortname" ,json_object_new_string (snd_ctl_card_info_get_name(cardinfo)));
- json_object_object_add(respJson, "longname" ,json_object_new_string (snd_ctl_card_info_get_longname(cardinfo)));
+ json_object_object_add(respJson, "shortname" ,json_object_new_string (shortname));
+ json_object_object_add(respJson, "longname" ,json_object_new_string (longname));
+ // search for a HAL binder card mapping name to api prefix
+ for (idx=0; idx < MAX_SND_CARD; idx++) {
+ if (!strcmp (cardRegistry[idx]->shortname, shortname)) break;
+ }
+ // if a match if found, then we have an HAL for this board let's return its value
+ if (idx < MAX_SND_CARD) json_object_object_add(respJson, "halapi",json_object_new_string (cardRegistry[idx]->apiprefix));
+
afb_req_success(request, respJson, NULL);
return;
- ExitOnError:
+ OnErrorExit:
+ return;
+}
+
+// Register loaded HAL with board Name and API prefix
+PUBLIC void alsaRegisterHal (struct afb_req request) {
+ static int index=0;
+ const char *shortname, *apiPrefix;
+
+ apiPrefix = afb_req_value(request, "prefix");
+ if (apiPrefix == NULL) {
+ afb_req_fail_f (request, "argument-missing", "prefix=BindingApiPrefix missing");
+ goto OnErrorExit;
+ }
+
+ shortname = afb_req_value(request, "name");
+ if (shortname == NULL) {
+ afb_req_fail_f (request, "argument-missing", "sndname=SndCardName missing");
+ goto OnErrorExit;
+ }
+
+ if (index == MAX_SND_CARD) {
+ afb_req_fail_f (request, "alsahal-toomany", "Fail to register sndname=[%s]", shortname);
+ goto OnErrorExit;
+ }
+
+ cardRegistry[index]= malloc (sizeof(cardRegistry));
+ cardRegistry[index]->apiprefix=strdup(apiPrefix);
+ cardRegistry[index]->shortname=strdup(shortname);
+ index++;cardRegistry[index]=NULL;
+
+ // when OK nothing to return
+ afb_req_success(request, NULL, NULL);
+ return;
+
+ OnErrorExit:
return;
}
diff --git a/AlsaSound/CoreBinding/AlsaLibMapping.h b/AlsaSound/CoreBinding/AlsaLibMapping.h
index cd6b409..e9e3a42 100644
--- a/AlsaSound/CoreBinding/AlsaLibMapping.h
+++ b/AlsaSound/CoreBinding/AlsaLibMapping.h
@@ -36,6 +36,8 @@ typedef int BOOL;
#include <afb/afb-binding.h>
#include <afb/afb-service-itf.h>
+#include "MiscHelpers.h"
+
// import from AlsaAfbBinding
extern const struct afb_binding_interface *afbIface;
@@ -45,6 +47,7 @@ PUBLIC void alsaGetInfo (struct afb_req request);
PUBLIC void alsaGetCtl(struct afb_req request);
PUBLIC void alsaSubcribe (struct afb_req request);
PUBLIC void alsaGetCardId (struct afb_req request);
+PUBLIC void alsaRegisterHal (struct afb_req request);
#endif /* ALSALIBMAPPING_H */
diff --git a/AlsaSound/CoreBinding/README.md b/AlsaSound/CoreBinding/README.md
index 5b6f026..a4b0395 100644
--- a/AlsaSound/CoreBinding/README.md
+++ b/AlsaSound/CoreBinding/README.md
@@ -12,6 +12,9 @@ Testing: (from project directory bindings)
# Get Info on a given Sound Card
http://localhost:1234/api/alsacore/getinfo?devid=hw:0
+ # Get shortname/longname for a given card
+ http://localhost:1234/api/alsacore/getcardid?devid=hw:0
+
# Get all controls from a given sound card
http://localhost:1234/api/alsacore/getctl?devid=hw:0
diff --git a/AlsaSound/HardAbsLayer/CMakeLists.txt b/AlsaSound/HALayer/CMakeLists.txt
index e24a9d9..0b12f62 100644
--- a/AlsaSound/HardAbsLayer/CMakeLists.txt
+++ b/AlsaSound/HALayer/CMakeLists.txt
@@ -18,6 +18,9 @@
PROJECT(hadware-abstraction-layer C)
+# Fulup NOTE: this might have to be change for a formal static/dynamic lib
+set(halsharedlib ${CMAKE_CURRENT_SOURCE_DIR}/Shared/SharedHalLib.c)
ADD_SUBDIRECTORY(IntelHda)
+ADD_SUBDIRECTORY(Shared)
diff --git a/AlsaSound/HardAbsLayer/IntelHda/CMakeLists.txt b/AlsaSound/HALayer/IntelHda/CMakeLists.txt
index 0d3f344..77218e2 100644
--- a/AlsaSound/HardAbsLayer/IntelHda/CMakeLists.txt
+++ b/AlsaSound/HALayer/IntelHda/CMakeLists.txt
@@ -22,7 +22,7 @@ INCLUDE_DIRECTORIES(${include_dirs})
##################################################
# Inte-HDA sound card Hardware Abstraction Layer
##################################################
-ADD_LIBRARY(intel-hda-hal MODULE IntelHdaBinding.c IntelHdaLib.c)
+ADD_LIBRARY(intel-hda-hal MODULE IntelHdaHAL.c ${halsharedlib})
SET_TARGET_PROPERTIES(intel-hda-hal PROPERTIES
PREFIX ""
diff --git a/AlsaSound/HALayer/IntelHda/IntelHdaHAL.c b/AlsaSound/HALayer/IntelHda/IntelHdaHAL.c
new file mode 100644
index 0000000..b04b545
--- /dev/null
+++ b/AlsaSound/HALayer/IntelHda/IntelHdaHAL.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define _GNU_SOURCE
+#include "AlsaHalIface.h" // Include Share Interface to Alsa Sound Card HAL
+
+/*****************************************************************************
+ * alsaCtlsMap link hight level sound control with low level Alsa numid ctls.
+ *
+ * To find out which control your sound card uses
+ * aplay -l
+ * amixer -D hw:xx controls
+ * amixer -D hw:xx contents
+ * amixer -D "hw:3" cget numid=xx
+ *****************************************************************************/
+STATIC alsaHalCtlMapT alsaHalCtlsMap[]= {
+ { .control=Master_Playback_Volume, .numid=16, .group=OUTVOL, .values=1, .minval=0, .maxval= 87 , .step=0, .acl=RW, .info= "Master Playback Volume" },
+ { .control=PCM_Playback_Volume , .numid=27, .group=PCMVOL, .values=2, .minval=0, .maxval= 255, .step=0, .acl=RW, .info= "PCM Playback Volume" },
+ { .control=PCM_Playback_Switch , .numid=17, .group=SWITCH, .values=1, .minval=0, .maxval= 1 , .step=0, .acl=RW, .info= "Master Playback Switch" },
+ { .control=Capture_Volume , .numid=12, .group=INVOL , .values=2, .minval=0, .maxval= 31 , .step=0, .acl=RW, .info= "Capture Volume" },
+ { .numid=0 } /* marker for end of the array */
+} ;
+
+/***********************************************************************************
+ * AlsaHalSndT provides
+ * - cardname used to map a given card to its HAL
+ * - ctls previously defined AlsaHalMapT control maps
+ * - info free text
+ *
+ * WARNING: name should fit with 'aplay -l' as it used to map from devid to HAL
+ * you may also retreive shortname when AudioBinder is running from a browser
+ * http://localhost:1234/api/alsacore/getcardid?devid=hw:xxx
+ *
+ ***********************************************************************************/
+PUBLIC alsaHalSndCardT alsaHalSndCard = {
+ .name = "HDA Intel PCH",
+ .info = "Hardware Abstraction Layer for IntelHDA sound card",
+ .ctls = alsaHalCtlsMap,
+};
+
+/***********************************************************************************
+ * AlsaHalSndT provides
+ * - cardname used to map a given card to its HAL
+ * - ctls previously defined AlsaHalMapT control maps
+ * - info free text
+ *
+ * WARNING: name should fit with 'aplay -l' as it used to map from devid to HAL
+ * you may also retreive shortname when AudioBinder is running from a browser
+ * http://localhost:1234/api/alsacore/getcardid?devid=hw:xxx
+ *
+ ***********************************************************************************/
+PUBLIC struct afb_binding alsaHalBinding = {
+ /* description conforms to VERSION 1 */
+ .type= AFB_BINDING_VERSION_1,
+ .v1= {
+ .prefix= "intel-hda",
+ .info = "Hardware Abstraction Layer for IntelHDA sound card",
+ }
+};
+
+
diff --git a/AlsaSound/HALayer/Shared/CMakeLists.txt b/AlsaSound/HALayer/Shared/CMakeLists.txt
new file mode 100644
index 0000000..27d93e0
--- /dev/null
+++ b/AlsaSound/HALayer/Shared/CMakeLists.txt
@@ -0,0 +1,30 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: Fulup Ar Foll <fulup@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###########################################################################
+
+
+INCLUDE_DIRECTORIES(${include_dirs})
+
+##################################################
+# Shared HAL(Hardware Abstraction Layer)
+##################################################
+ADD_LIBRARY(shared-hal MODULE SharedHalLib.c)
+
+TARGET_LINK_LIBRARIES(shared-hal ${link_libraries})
+INSTALL(TARGETS shared-hal LIBRARY DESTINATION ${binding_install_dir})
+
+
diff --git a/AlsaSound/HALayer/Shared/SharedHalLib.c b/AlsaSound/HALayer/Shared/SharedHalLib.c
new file mode 100644
index 0000000..ffa25e0
--- /dev/null
+++ b/AlsaSound/HALayer/Shared/SharedHalLib.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2016 "IoT.bzh"
+ * Author Fulup Ar Foll <fulup@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * reference:
+ * amixer contents; amixer controls;
+ * http://www.tldp.org/HOWTO/Alsa-sound-6.html
+ */
+#define _GNU_SOURCE // needed for vasprintf
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <json-c/json.h>
+#include <afb/afb-binding.h>
+#include <afb/afb-service-itf.h>
+
+#include "MiscHelpers.h"
+#include "AlsaHalIface.h"
+
+typdef struct {
+ int numid;
+} shareHallMap_T;
+
+static struct afb_service srvitf;
+static const struct afb_binding_interface *afbIface;
+static shareHallMap_T *shareHallMap;
+
+
+STATIC void localping(struct afb_req request) {
+ json_object *query = afb_req_json(request);
+ afb_req_success(request, query, NULL);
+}
+
+// This callback when api/alsacore/subscribe returns
+STATIC void alsaSubcribeCB (void *handle, int iserror, struct json_object *result) {
+ struct afb_req request = afb_req_unstore(handle);
+ struct json_object *x, *resp = NULL;
+ const char *info = NULL;
+
+ if (result) {
+ INFO (afbIface, "result=[%s]\n", json_object_to_json_string (result));
+ if (json_object_object_get_ex(result, "request", &x) && json_object_object_get_ex(x, "info", &x))
+ info = json_object_get_string(x);
+ if (!json_object_object_get_ex(result, "response", &resp)) resp = NULL;
+ }
+
+ // push message respond
+ if (iserror) afb_req_fail_f(request, "Fail", info);
+ else afb_req_success(request, resp, info);
+
+ // free calling request
+ afb_req_unref(request);
+}
+
+// Create and subscribe to alsacore ctl events
+STATIC void halMonitor(struct afb_req request) {
+
+ // save request in session as it might be used after return by callback
+ struct afb_req *handle = afb_req_store(request);
+
+ // push request to low level binding
+ if (!handle) afb_req_fail(request, "error", "out of memory");
+ else afb_service_call(srvitf, "alsacore", "subctl", json_object_get(afb_req_json(request)), alsaSubcribeCB, handle);
+
+ // success/failure messages return from callback
+}
+
+// Subscribe to AudioBinding events
+STATIC void halSubscribe (struct afb_req request) {
+ const char *devid = afb_req_value(request, "devid");
+ if (devid == NULL) {
+ afb_req_fail_f (request, "devid-missing", "devid=hw:xxx missing");
+ }
+}
+
+// Call when all bindings are loaded and ready to accept request
+STATIC void halGetVol(struct afb_req request) {
+
+ // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
+ afb_req_success (request, NULL, NULL);
+ return;
+
+}
+
+STATIC void halSetVol(struct afb_req request) {
+ const char *arg;
+ const char *pcm;
+
+ arg = afb_req_value(request, "vol");
+ if (arg == NULL) {
+ afb_req_fail_f (request, "argument-missing", "vol=[0,100] missing");
+ goto OnErrorExit;
+ }
+
+ pcm = afb_req_value(request, "pcm");
+ if (pcm == NULL) pcm="Master";
+
+ // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
+ afb_req_success (request, NULL, NULL);
+ return;
+
+ OnErrorExit:
+ return;
+
+}
+
+// this is call when after all bindings are loaded
+STATIC int halGetControl(struct afb_service service) {
+ srvitf = service;
+ struct json_object *queryin, *queryout, *ctls, *devid;
+
+ // get query from request
+ queryin = afb_req_json(request);
+
+ // check devid was given
+ devid= json_object_object_get(queryin,"devid");
+ if (!ctls) {
+ afb_req_fail_f(request, "devid-notfound", "No DevID given query=[%s]", json_object_get_string(queryin));
+ goto OnErrorExit;
+ }
+
+ // loop on requested controls
+ ctls= json_object_object_get(queryin,"ctls");
+ if (!ctls || json_object_array_length(ctls) <= 0) {
+ afb_req_fail_f(request, "ctls-notfound", "No Controls given query=[%s]", json_object_get_string(queryin));
+ goto OnErrorExit;
+ }
+
+ for (int idx=0; idx< json_object_array_length(ctls), idx++) {
+ struct json_object *ctl;
+ halControlEnumT control;
+ int value;
+
+ // each controls should be halControlEnumT+value
+ ctl = json_object_array_get_idx(ctls, idx);
+ if (json_object_array_length(ctl != 2)) {
+ afb_req_fail_f(request, "ctl-invalid", "Invalid Control devid=%s ctl=[%s]"json_object_get_string(devid), json_object_get_string(cls));
+ goto OnErrorExit;
+ }
+
+ // As HAL and Business logic use the same AlsaMixerHal.h direct conversion is not an issue
+ control = (halControlEnumT)json_object_get_int(json_object_array_get_idx(ctl,0));
+ value = json_object_get_int(json_object_array_get_idx(ctl,0));
+
+ if (control >= EndHalCrlTag || control <= StartHalCrlTag) {
+ afb_req_fail_f(request, "ctl-invalid", "Invalid Control devid=%s ctl=[%s] should be [%d=%d]"
+ , json_object_get_string(devid), json_object_get_string(cls)), StartHalCrlTag, EndHalCrlTag;
+ goto OnErrorExit;
+ }
+
+
+ default:
+ NOTICE (afbIface, "audioLogicOpenCB2 unknown HAL control=[%s]", json_object_get_string(ctl)):
+ }
+ }
+
+
+ // register HAL with Alsa Low Level Binder devid=hw:0&numid=1&quiet=0
+ queryurl=json_object_new_object();
+ json_object_object_add(queryurl, "prefix",json_object_new_string(alsaHalBinding.v1.prefix));
+ json_object_object_add(queryurl, "name" ,json_object_new_string(alsaHalSndCard.name));
+ afb_service_call(srvitf, "alsacore", "registerHal", queryurl, halGetControlCB, queryurl);
+
+
+ afb_req_success (request, sndctrls, NULL);
+ return;
+
+OnErrorExit:
+
+};
+
+STATIC void halInitCB (void *handle, int iserror, struct json_object *result) {
+ struct json_object *queryurl = (json_object*)handle;
+
+ if (iserror) NOTICE (afbIface, "halInitCB: registration alsaHAL query=[%s] Fail", json_object_to_json_string(queryurl));
+ else DEBUG(afbIface, "halInitCB: registration alsaHAL card=[%s] Success", json_object_to_json_string(queryurl));
+}
+
+// This receive all event this binding subscribe to
+PUBLIC void afbBindingV1ServiceEvent(const char *evtname, struct json_object *object) {
+
+ NOTICE (afbIface, "afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object));
+}
+
+// this is call when after all bindings are loaded
+PUBLIC int afbBindingV1ServiceInit(struct afb_service service) {
+ srvitf = service;
+ struct json_object *queryurl;
+
+ // API prefix is used as sndcard halname
+ alsaHalBinding.v1.prefix= prefix;
+
+ // register HAL with Alsa Low Level Binder
+ queryurl=json_object_new_object();
+ json_object_object_add(ctx->queryurl, "prefix",json_object_new_string(alsaHalBinding.v1.prefix));
+ json_object_object_add(ctx->queryurl, "name" ,json_object_new_string(alsaHalSndCard.name));
+ afb_service_call(srvitf, "alsacore", "registerHal", queryurl, halInitCB, NULL);
+
+ return 0;
+};
+
+
+// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT
+STATIC const struct afb_verb_desc_v1 halSharedApi[] = {
+ /* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
+ { .name= "ping" , .session= AFB_SESSION_NONE, .callback= localping, .info= "Ping Binding" },
+ { .name= "getcontrol", .session= AFB_SESSION_NONE, .callback= halGetControl,.info= "Get Control" },
+ { .name= "setvolume", .session= AFB_SESSION_NONE, .callback= halSetVol, .info= "Set Volume" },
+ { .name= "getvolume", .session= AFB_SESSION_NONE, .callback= halGetVol, .info= "Get Volume" },
+ { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= halSubscribe, .info= "Subscribe AudioBinding Events" },
+ { .name= NULL } /* marker for end of the array */
+};
+
+// Process HAL mapping from alsaHalSndCardT before registering HAL binder
+PUBLIC const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf) {
+ int count;
+ afbIface= itf; // need to keep a static trace of binder interface for avances functions
+ alsaHalBinding.verbs=halSharedApi; // complete sndcard specific alsaHalBinding with standard HAL APIs
+ alsaHalCtlMapT *alsaHalCtls = MapalsaHalSndCard.alsaHalCtlsMap; // Get sndcard specific HAL control mapping
+
+ if (alsaHalCtls == NULL) {
+ ERROR (afbIface, "afbBindingV1Register Fail alsaHalCtlsMap==NULL");
+ return NULL;
+ }
+
+ // Create a zone to store HAL high/low level mapping
+ shareHallMap = calloc (EndHalCrlTag * sizeof(shareHallMap_T));
+ for (int idx= 0; alsaHalCtlsMap[idx].numid != 0; idx++) {
+ shareHallMap[alsaHalCtlsMap[idx].]->numid = alsaHalCtlsMap[idx].numid;
+ }
+
+ return alsaHalBinding; /* returns the description of the binding */
+}
diff --git a/AlsaSound/include/AlsaMixerHal.h b/AlsaSound/HALayer/include/AlsaHalCtls.h
index 399f8ab..a17315a 100644
--- a/AlsaSound/include/AlsaMixerHal.h
+++ b/AlsaSound/HALayer/include/AlsaHalCtls.h
@@ -20,6 +20,7 @@
*/
+
#ifndef ALSAMIXERMAP_H
#define ALSAMIXERMAP_H
@@ -31,41 +32,26 @@ typedef enum {
SWITCH,
ROUTE,
CARD,
-} groupEnum;
+} halGroupEnumT;
typedef enum {
READ,
WRITE,
RW,
-} aclEnum;
+} halAclEnumT;
typedef enum {
+ StartHalCrlTag=0,
+
+ // HighLevel Audio Control List
Master_Playback_Volume,
PCM_Playback_Volume,
PCM_Playback_Switch,
Capture_Volume,
-} actionEnum;
-typedef const struct {
- actionEnum action;
- int numid;
- groupEnum group;
- int values;
- int minval;
- int maxval;
- int step;
- char* info;
- aclEnum acl;
-
-} AlsaHalMapT;
+ EndHalCrlTag // used to compute number of ctls
+} halControlEnumT;
-typedef struct {
- const char *halname;
- const char *longname;
- const char *info;
- AlsaHalMapT *ctls;
-
-} AlsaHalSndT;
#endif /* ALSAMIXERMAP_H */
diff --git a/AlsaSound/HALayer/include/AlsaHalIface.h b/AlsaSound/HALayer/include/AlsaHalIface.h
new file mode 100644
index 0000000..83ab57c
--- /dev/null
+++ b/AlsaSound/HALayer/include/AlsaHalIface.h
@@ -0,0 +1,52 @@
+/*
+ * AlsaLibMapping -- provide low level interface with AUDIO lib (extracted from alsa-json-gateway code)
+ * Copyright (C) 2015,2016,2017, Fulup Ar Foll fulup@iot.bzh
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SHAREDHALLIB_H
+#define SHAREDHALLIB_H
+
+#include <stdio.h>
+#include <afb/afb-binding.h>
+
+#include "MiscHelpers.h"
+#include "AlsaHalCtls.h"
+
+typedef const struct {
+ halControlEnumT control;
+ int numid;
+ halGroupEnumT group;
+ int values;
+ int minval;
+ int maxval;
+ int step;
+ char* info;
+ halAclEnumT acl;
+
+} alsaHalCtlMapT;
+
+typedef struct {
+ const char *prefix;
+ const char *name;
+ const char *info;
+ alsaHalCtlMapT *ctls;
+
+} alsaHalSndCardT;
+
+PUBLIC alsaHalSndCardT alsaHalSndCard;
+PUBLIC struct afb_binding alsaHalBinding;
+
+#endif /* SHAREDHALLIB_H */
+
diff --git a/AlsaSound/HardAbsLayer/IntelHda/IntelHdaLib.h b/AlsaSound/HALayer/include/MiscHelpers.h
index edf9474..0181847 100644
--- a/AlsaSound/HardAbsLayer/IntelHda/IntelHdaLib.h
+++ b/AlsaSound/HALayer/include/MiscHelpers.h
@@ -15,9 +15,9 @@
* limitations under the License.
*/
+#ifndef MISCHELPER_H
+#define MISCHELPER_H
-// few coding convention
-typedef int BOOL;
#ifndef PUBLIC
#define PUBLIC
#endif
@@ -27,23 +27,7 @@ typedef int BOOL;
#ifndef TRUE
#define TRUE 1
#endif
-#define STATIC static
-
-#ifndef AUDIOLIBMAPPING_H
-#define AUDIOLIBMAPPING_H
+#define STATIC static
-#include <json-c/json.h>
-#include <afb/afb-binding.h>
-#include <afb/afb-service-itf.h>
-
-// import from AlsaAfbBinding
-extern const struct afb_binding_interface *afbIface;
-
-// import from AlsaAfbMapping
-PUBLIC void intelHdaSetVol (struct afb_req request);
-PUBLIC void intelHdaGetVol(struct afb_req request);
-PUBLIC void intelHdaSubscribe(struct afb_req request);
-PUBLIC int intelHdaInit (struct afb_service service, const char *cardname);
-
-#endif /* AUDIOLIBMAPPING_H */
+#endif /* MISCHELPER_H */
diff --git a/AlsaSound/HardAbsLayer/IntelHda/IntelHdaBinding.c b/AlsaSound/HardAbsLayer/IntelHda/IntelHdaBinding.c
deleted file mode 100644
index 0452314..0000000
--- a/AlsaSound/HardAbsLayer/IntelHda/IntelHdaBinding.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <math.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include "IntelHdaLib.h"
-
-PUBLIC const struct afb_binding_interface *afbIface;
-
-STATIC void localping(struct afb_req request) {
- json_object *query = afb_req_json(request);
- afb_req_success(request, query, NULL);
-}
-
-/*
- * array of the verbs exported to afb-daemon
- */
-STATIC const struct afb_verb_desc_v1 binding_verbs[] = {
- /* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
- { .name= "ping" , .session= AFB_SESSION_NONE, .callback= localping, .info= "Ping Binding" },
- { .name= "setvolume", .session= AFB_SESSION_NONE, .callback= intelHdaSetVol, .info= "Set Volume" },
- { .name= "getvolume", .session= AFB_SESSION_NONE, .callback= intelHdaGetVol, .info= "Get Volume" },
- { .name= "subscribe", .session= AFB_SESSION_NONE, .callback= intelHdaSubscribe, .info= "Subscribe AudioBinding Events" },
- { .name= NULL } /* marker for end of the array */
-};
-
-/*
- * description of the binding for afb-daemon
- */
-STATIC const struct afb_binding binding_description = {
- /* description conforms to VERSION 1 */
- .type= AFB_BINDING_VERSION_1,
- .v1= {
- .prefix= "intel-hda",
- .info= "Hardware Abstraction Layer for IntelHDA sound card",
- .verbs = binding_verbs
- }
-};
-
-// This receive all event this binding subscribe to
-PUBLIC void afbBindingV1ServiceEvent(const char *evtname, struct json_object *object) {
-
- NOTICE (afbIface, "afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object));
-}
-
-// this is call when after all bindings are loaded
-PUBLIC int afbBindingV1ServiceInit(struct afb_service service) {
-
- return (intelHdaInit(service, binding_description.v1.prefix));
-};
-
-/*
- * activation function for registering the binding called by afb-daemon
- */
-PUBLIC const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf) {
- afbIface= itf;
- return &binding_description; /* returns the description of the binding */
-}
-
diff --git a/AlsaSound/HardAbsLayer/IntelHda/IntelHdaLib.c b/AlsaSound/HardAbsLayer/IntelHda/IntelHdaLib.c
deleted file mode 100644
index ad4fcf4..0000000
--- a/AlsaSound/HardAbsLayer/IntelHda/IntelHdaLib.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * reference:
- * amixer contents; amixer controls;
- * http://www.tldp.org/HOWTO/Alsa-sound-6.html
- */
-#define _GNU_SOURCE // needed for vasprintf
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <math.h>
-#include <sys/time.h>
-#include <sys/types.h>
-
-#include "IntelHdaLib.h"
-#include "AlsaMixerHal.h"
-
-static struct afb_service srvitf;
-
-// Normalise Intel-HDA numid
-static AlsaHalMapT alsaCtlsMap[]= { // check with amixer -D hw:xx controls; amixer -D "hw:3" cget numid=xx
- /* ACTION(enum) NUMID(int) IFACE(enum) VALUES(int) MinVal(int) MaxVal(int) Step(int) ACL=READ|WRITE|RW INFO=comment */
- { .action=Master_Playback_Volume, .numid=16, .group=OUTVOL, .values=1, .minval=0, .maxval= 87 , .step=0, .acl=RW, .info= "Master Playback Volume" },
- { .action=PCM_Playback_Volume , .numid=27, .group=PCMVOL, .values=2, .minval=0, .maxval= 255, .step=0, .acl=RW, .info= "PCM Playback Volume" },
- { .action=PCM_Playback_Switch , .numid=17, .group=SWITCH, .values=1, .minval=0, .maxval= 1 , .step=0, .acl=RW, .info= "Master Playback Switch" },
- { .action=Capture_Volume , .numid=12, .group=INVOL , .values=2, .minval=0, .maxval= 31 , .step=0, .acl=RW, .info= "Capture Volume" },
- { .numid=0 } /* marker for end of the array */
-} ;
-
-// Warning: Longname is used to locate board on the system
-static AlsaHalSndT alsaSndCard = {
- .longname= "HDA Intel PCH",
- .info = "Hardware Abstraction Layer for IntelHDA sound card",
- .ctls = alsaCtlsMap,
-};
-
-
-// This callback is fired when afb_service_call for api/alsacore/subctl returns
-STATIC void alsaSubcribeCB (void *handle, int iserror, struct json_object *result) {
- struct afb_req request = afb_req_unstore(handle);
- struct json_object *x, *resp = NULL;
- const char *info = NULL;
-
- if (result) {
- INFO (afbIface, "result=[%s]\n", json_object_to_json_string (result));
- if (json_object_object_get_ex(result, "request", &x) && json_object_object_get_ex(x, "info", &x))
- info = json_object_get_string(x);
- if (!json_object_object_get_ex(result, "response", &resp)) resp = NULL;
- }
-
- // push message respond
- if (iserror) afb_req_fail_f(request, "Fail", info);
- else afb_req_success(request, resp, info);
-
- // free calling request
- afb_req_unref(request);
-}
-
-// Create and subscribe to alsacore ctl events
-PUBLIC void intelHdaMonitor(struct afb_req request) {
-
- // save request in session as it might be used after return by callback
- struct afb_req *handle = afb_req_store(request);
-
- // push request to low level binding
- if (!handle) afb_req_fail(request, "error", "out of memory");
- else afb_service_call(srvitf, "alsacore", "subctl", json_object_get(afb_req_json(request)), alsaSubcribeCB, handle);
-
- // success/failure messages return from callback
-}
-
-// Subscribe to AudioBinding events
-PUBLIC void intelHdaSubscribe (struct afb_req request) {
- const char *devid = afb_req_value(request, "devid");
- if (devid == NULL) {
- afb_req_fail_f (request, "devid-missing", "devid=hw:xxx missing");
- }
-
-}
-
-
-// Call when all bindings are loaded and ready to accept request
-PUBLIC void intelHdaGetVol(struct afb_req request) {
-
- // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
- afb_req_success (request, NULL, NULL);
- return;
-
-}
-
-PUBLIC void intelHdaSetVol(struct afb_req request) {
- const char *arg;
- char *pcm;
-
- arg = afb_req_value(request, "vol");
- if (arg == NULL) {
- afb_req_fail_f (request, "argument-missing", "vol=[0,100] missing");
- goto ExitOnError;
- }
-
- arg = afb_req_value(request, "pcm");
- if (arg == NULL) pcm="Master";
-
- // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card
- afb_req_success (request, NULL, NULL);
- return;
-
- ExitOnError:
- return;
-
-}
-
-
-// this function is call after all binder are loaded and initialised
-PUBLIC int intelHdaInit (struct afb_service service, const char *cardname) {
- srvitf = service;
-
- // API prefix is used as sndcard halname
- alsaSndCard.halname= cardname;
- return 0;
-} \ No newline at end of file