summaryrefslogtreecommitdiffstats
path: root/HAL-afb
diff options
context:
space:
mode:
Diffstat (limited to 'HAL-afb')
-rw-r--r--HAL-afb/CMakeLists.txt2
-rw-r--r--HAL-afb/HAL-interface/hal-interface.c112
-rw-r--r--HAL-afb/HAL-interface/hal-interface.h12
-rw-r--r--HAL-afb/HDA-intel/IntelHdaHAL.c73
-rw-r--r--HAL-afb/Scarlett-Focusrite/CMakeLists.txt42
-rw-r--r--HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c74
6 files changed, 198 insertions, 117 deletions
diff --git a/HAL-afb/CMakeLists.txt b/HAL-afb/CMakeLists.txt
index 1b8cc0e..b0c2e6a 100644
--- a/HAL-afb/CMakeLists.txt
+++ b/HAL-afb/CMakeLists.txt
@@ -19,5 +19,5 @@
# Include any directory starting with a Capital letter
# -----------------------------------------------------
-PROJECT_SUBDIRS_ADD("*")
+PROJECT_SUBDIRS_ADD(${PROJECT_SRC_DIR_PATTERN})
diff --git a/HAL-afb/HAL-interface/hal-interface.c b/HAL-afb/HAL-interface/hal-interface.c
index 2c6595f..29c5e88 100644
--- a/HAL-afb/HAL-interface/hal-interface.c
+++ b/HAL-afb/HAL-interface/hal-interface.c
@@ -37,31 +37,11 @@ typedef struct {
} shareHallMap_T;
static shareHallMap_T *shareHallMap;
+static alsaHalMapT *halCtls;
// Force specific HAL to depend on ShareHalLib
PUBLIC char* SharedHalLibVersion="1.0";
-// This callback when api/alsacore/subscribe returns
-STATIC void alsaSubcribeCB(void *handle, int iserror, struct json_object *result) {
- afb_req request = afb_req_unstore(handle);
- struct json_object *x, *resp = NULL;
- const char *info = NULL;
-
- if (result) {
- INFO( "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);
-}
-
// Subscribe to AudioBinding events
STATIC void halSubscribe(afb_req request) {
const char *devid = afb_req_value(request, "devid");
@@ -125,7 +105,6 @@ STATIC int NormaliseValue(const alsaHalCtlMapT *halCtls, int valuein) {
// receive controls for LowLevel remap them to hight level before returning them
STATIC void halGetControlCB(void *handle, int iserror, struct json_object *result) {
- alsaHalMapT *halCtls = alsaHalSndCard.ctls;
struct json_object *response;
// retrieve request and check for errors
@@ -218,8 +197,8 @@ STATIC void halGetCtls(afb_req request) {
ctl = json_object_array_get_idx(ctlsin, idx);
control = (halCtlsEnumT) json_object_get_int(ctl);
if (control >= EndHalCrlTag || control <= StartHalCrlTag) {
- afb_req_fail_f(request, "ctl-invalid", "Invalid Control devid=%s sndcard=%s ctl=[%s] should be [%d-%d]"
- , json_object_get_string(devid), alsaHalSndCard.name, json_object_get_string(ctl), StartHalCrlTag, EndHalCrlTag);
+ 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(ctl), StartHalCrlTag, EndHalCrlTag);
goto OnExit;
}
@@ -241,60 +220,69 @@ OnExit:
// This receive all event this binding subscribe to
-PUBLIC void afbServiceEvent(const char *evtname, struct json_object *object) {
+PUBLIC void halServiceEvent(const char *evtname, struct json_object *object) {
- NOTICE("afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object));
+ AFB_NOTICE("afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object));
}
// this is call when after all bindings are loaded
-STATIC int afbServiceInit() {
- int rc=0, err;
- struct json_object *queryurl, *jResponse;
- alsaHalMapT *halCtls = alsaHalSndCard.ctls; // Get sndcard specific HAL control mapping
+PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard) {
+ int ok, err;
+ struct json_object *queryurl, *responseJ, *devidJ, *tmpJ;
+ halCtls = alsaHalSndCard->ctls; // Get sndcard specific HAL control mapping
- if (alsaHalSndCard.initCB) {
- rc= (alsaHalSndCard.initCB)();
- if (rc != 0) goto OnErrorExit;
- }
-
err= afb_daemon_require_api("alsacore", 1);
+ if (err) {
+ AFB_ERROR ("AlsaCore missing cannot use AlsaHAL");
+ goto OnErrorExit;
+ }
// register HAL with Alsa Low Level Binder
queryurl = json_object_new_object();
- json_object_object_add(queryurl, "prefix", json_object_new_string(sndCardApiPrefix));
- json_object_object_add(queryurl, "name", json_object_new_string(alsaHalSndCard.name));
+ json_object_object_add(queryurl, "prefix", json_object_new_string(apiPrefix));
+ json_object_object_add(queryurl, "sndname", json_object_new_string(alsaHalSndCard->name));
- afb_service_call_sync("alsacore", "registerHal", queryurl, &jResponse);
- err= afb_service_call_sync ("alsacore", "registerHal", queryurl, &jResponse);
- if (err) {
- ERROR ("Fail to register HAL to ALSA lowlevel binding");
+ ok= afb_service_call_sync ("alsacore", "registerHal", queryurl, &responseJ);
+ json_object_put(queryurl);
+ if (!ok) {
+ NOTICE ("Fail to register HAL to ALSA lowlevel binding Response=[%s]", json_object_to_json_string(responseJ));
goto OnErrorExit;
}
- json_object_put(queryurl);
-
+
+ // extract sound devid from HAL registration
+ if (!json_object_object_get_ex(responseJ, "response", &tmpJ) || !json_object_object_get_ex(tmpJ, "devid", &devidJ)) {
+ AFB_ERROR ("Ooops: Internal error no devid return from HAL registration Response=[%s]", json_object_to_json_string(responseJ));
+ goto OnErrorExit;
+ }
+
// for each Non Alsa Control callback create a custom control
for (int idx = 0; halCtls[idx].alsa.numid != 0; idx++) {
if (halCtls[idx].cb.callback != NULL) {
queryurl = json_object_new_object();
- if (halCtls[idx].alsa.name) json_object_object_add(queryurl, "name" , json_object_new_string(halCtls[idx].alsa.name));
- if (halCtls[idx].alsa.numid) json_object_object_add(queryurl, "numid" , json_object_new_int(halCtls[idx].alsa.numid));
- if (halCtls[idx].alsa.minval) json_object_object_add(queryurl, "minval", json_object_new_int(halCtls[idx].alsa.minval));
- if (halCtls[idx].alsa.maxval) json_object_object_add(queryurl, "maxval", json_object_new_int(halCtls[idx].alsa.maxval));
- if (halCtls[idx].alsa.step) json_object_object_add(queryurl, "step" , json_object_new_int(halCtls[idx].alsa.step));
- if (halCtls[idx].alsa.type) json_object_object_add(queryurl, "type" , json_object_new_int(halCtls[idx].alsa.type));
+ json_object_object_add(queryurl, "devid",devidJ);
+ tmpJ = json_object_new_object();
+ if (halCtls[idx].alsa.name) json_object_object_add(tmpJ, "name" , json_object_new_string(halCtls[idx].alsa.name));
+ if (halCtls[idx].alsa.numid) json_object_object_add(tmpJ, "numid" , json_object_new_int(halCtls[idx].alsa.numid));
+ if (halCtls[idx].alsa.minval) json_object_object_add(tmpJ, "minval", json_object_new_int(halCtls[idx].alsa.minval));
+ if (halCtls[idx].alsa.maxval) json_object_object_add(tmpJ, "maxval", json_object_new_int(halCtls[idx].alsa.maxval));
+ if (halCtls[idx].alsa.step) json_object_object_add(tmpJ, "step" , json_object_new_int(halCtls[idx].alsa.step));
+ if (halCtls[idx].alsa.type) json_object_object_add(tmpJ, "type" , json_object_new_int(halCtls[idx].alsa.type));
+ json_object_object_add(queryurl, "ctls",tmpJ);
- err= afb_service_call_sync ("alsacore", "addUserCtl", queryurl, &jResponse);
- if (err) {
- ERROR ("Fail to register Callback for ctrl=[%s]", halCtls[idx].alsa.name);
+ AFB_NOTICE("QUERY=%s", json_object_to_json_string(queryurl));
+
+ ok= afb_service_call_sync ("alsacore", "addcustomctl", queryurl, &responseJ);
+ if (!ok) {
+ AFB_ERROR ("Fail to add Customer Sound Control for ctrl=[%s] Response=[%s]", halCtls[idx].alsa.name, json_object_to_json_string(responseJ));
goto OnErrorExit;
- }
+ }
}
}
// finally register for alsa lowlevel event
- err= afb_service_call_sync ("alsacore", "subscribe", queryurl, &jResponse);
+ err= afb_service_call_sync ("alsacore", "subscribe", queryurl, &responseJ);
if (err) {
- ERROR ("Fail subscribing to ALSA lowlevel events");
+ AFB_ERROR ("Fail subscribing to ALSA lowlevel events");
goto OnErrorExit;
}
@@ -305,24 +293,12 @@ STATIC int afbServiceInit() {
};
// Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT
-STATIC afb_verb_v2 halSharedApi[] = {
+PUBLIC afb_verb_v2 halServiceApi[] = {
/* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */
{ .verb = "ping", .callback = pingtest},
{ .verb = "getctls", .callback = halGetCtls},
{ .verb = "setvol", .callback = halSetVol},
{ .verb = "getvol", .callback = halGetVol},
{ .verb = "subscribe", .callback = halSubscribe},
- { .verb = "monitor", .callback = halMonitor},
{ .verb = NULL} /* marker for end of the array */
};
-
-
-PUBLIC const struct afb_binding_v2 afbBindingV2 = {
- .api = sndCardApiPrefix,
- .specification = NULL,
- .verbs = halSharedApi,
- .preinit = NULL,
- .init = afbServiceInit,
- .onevent = afbServiceEvent,
- .noconcurrency = 0
-};
diff --git a/HAL-afb/HAL-interface/hal-interface.h b/HAL-afb/HAL-interface/hal-interface.h
index e08ec18..16da901 100644
--- a/HAL-afb/HAL-interface/hal-interface.h
+++ b/HAL-afb/HAL-interface/hal-interface.h
@@ -39,9 +39,6 @@ typedef struct {
// avoid compiler warning [Jose does not like typedef :) ]
typedef struct afb_service alsaHalServiceT;
-// static value for HAL sound card API prefix
-extern const char sndCardApiPrefix[];
-
typedef struct {
struct json_object* (*callback)(alsaHalCtlMapT *control, void* handle);
void* handle;
@@ -57,12 +54,13 @@ typedef struct {
typedef const struct {
const char *name;
const char *info;
- alsaHalMapT *ctls;
- int (*initCB) (void);
-
+ alsaHalMapT *ctls;
} alsaHalSndCardT;
-PUBLIC alsaHalSndCardT alsaHalSndCard;
+extern afb_verb_v2 halServiceApi[];
+PUBLIC void halServiceEvent(const char *evtname, struct json_object *object);
+PUBLIC int halServiceInit (const char *apiPrefix, alsaHalSndCardT *alsaHalSndCard);
+
#endif /* SHAREHALLIB_H */
diff --git a/HAL-afb/HDA-intel/IntelHdaHAL.c b/HAL-afb/HDA-intel/IntelHdaHAL.c
index 98ac442..f394fd6 100644
--- a/HAL-afb/HDA-intel/IntelHdaHAL.c
+++ b/HAL-afb/HDA-intel/IntelHdaHAL.c
@@ -13,42 +13,33 @@
* 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.
+ *
+ *
+ * To find out which control your sound card uses
+ * aplay -l # Check sndcard name name in between []
+ * amixer -D hw:xx controls # get supported controls
+ * amixer -D "hw:3" cget numid=xx # get control settings
+ *
*/
#define _GNU_SOURCE
#include "hal-interface.h"
#include "audio-interface.h"
-// Init is call after all binding are loaded
-STATIC int IntelHalInit (void) {
- DEBUG ("IntelHalBinding Initialised");
-
- return 0; // 0=OK
-}
-
-STATIC void MasterOnOff (alsaHalCtlMapT *control, void* handle) {
+STATIC struct json_object* MasterOnOff (alsaHalCtlMapT *control, void* handle) {
static int powerStatus=0;
if (! powerStatus) {
powerStatus = 1;
- DEBUG ("Power Set to On");
+ AFB_DEBUG ("Power Set to On");
} else {
powerStatus = 0;
- DEBUG ("Power Set to Off");
+ AFB_DEBUG ("Power Set to Off");
}
+
+ return NULL;
}
-/******************************************************************************************
- * 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
- *
- * When automatic mapping to Alsa numid is not enough a custom callback might be used
- * .cb={.handle=xxxx, .callback=(json_object)MyCtlFunction(struct afb_service service, int controle, int value, const struct alsaHalCtlMapS *map)};
- ********************************************************************************************/
+// Map HAL hight sndctl with Alsa numid and optionally with a custom callback for non Alsa supported functionalities.
STATIC alsaHalMapT alsaHalMap[]= {
{ .alsa={.control=Master_Playback_Volume,.numid=16, .name="Master-Vol" , .values=1,.minval=0,.maxval= 87 ,.step=0}, .info= "Master Playback Volume" },
{ .alsa={.control=PCM_Playback_Volume ,.numid=27, .name="Play-Vol" , .values=2,.minval=0,.maxval= 255,.step=0}, .info= "PCM Playback Volume" },
@@ -58,26 +49,26 @@ STATIC alsaHalMapT alsaHalMap[]= {
{ .alsa={.numid=0}, .cb={.callback=NULL, .handle=NULL}} /* 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
- *
- ***********************************************************************************/
-
-// API prefix should be unique for each snd card
-PUBLIC const char sndCardApiPrefix[] = "intel-hda";
-
-// HAL sound card controls mapping
-PUBLIC alsaHalSndCardT alsaHalSndCard = {
- .name = "HDA Intel PCH",
+// HAL sound card mapping info
+STATIC alsaHalSndCardT alsaHalSndCard = {
+ .name = "HDA Intel PCH", // WARNING: name MUST match with 'aplay -l'
.info = "Hardware Abstraction Layer for IntelHDA sound card",
.ctls = alsaHalMap,
- .initCB=IntelHalInit, // if NULL no initcallback
};
+
+STATIC int sndServiceInit () {
+ int err;
+ AFB_DEBUG ("IntelHalBinding Init");
+
+ err = halServiceInit (afbBindingV2.api, &alsaHalSndCard);
+ return err;
+}
+
+// API prefix should be unique for each snd card
+PUBLIC const struct afb_binding_v2 afbBindingV2 = {
+ .api = "intel-hda",
+ .init = sndServiceInit,
+ .verbs = halServiceApi,
+ .onevent = halServiceEvent,
+};
diff --git a/HAL-afb/Scarlett-Focusrite/CMakeLists.txt b/HAL-afb/Scarlett-Focusrite/CMakeLists.txt
new file mode 100644
index 0000000..a2ca912
--- /dev/null
+++ b/HAL-afb/Scarlett-Focusrite/CMakeLists.txt
@@ -0,0 +1,42 @@
+###########################################################################
+# 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.
+###########################################################################
+
+
+# Add target to project dependency list
+PROJECT_TARGET_ADD(hal-scalett-usb)
+
+ # Define project Targets
+ ADD_LIBRARY(hal-scalett-usb MODULE ScarlettUsbHAL.c)
+
+ # Binder exposes a unique public entry point
+ SET_TARGET_PROPERTIES(hal-scalett-usb PROPERTIES
+ PREFIX "afb-"
+ LABELS "BINDING"
+ LINK_FLAGS ${BINDINGS_LINK_FLAG}
+ OUTPUT_NAME ${TARGET_NAME}
+ )
+
+ # Library dependencies (include updates automatically)
+ TARGET_LINK_LIBRARIES(hal-scalett-usb
+ hal-interface
+ audio-interface
+ )
+
+ # installation directory
+ INSTALL(TARGETS hal-scalett-usb
+ LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR}) \ No newline at end of file
diff --git a/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c b/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.c
new file mode 100644
index 0000000..1ff5320
--- /dev/null
+++ b/HAL-afb/Scarlett-Focusrite/ScarlettUsbHAL.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.
+ *
+ *
+ * To find out which control your sound card uses
+ * aplay -l # Check sndcard name name in between []
+ * amixer -D hw:xx controls # get supported controls
+ * amixer -D "hw:3" cget numid=xx # get control settings
+ *
+ */
+#define _GNU_SOURCE
+#include "hal-interface.h"
+#include "audio-interface.h"
+
+STATIC struct json_object* MasterOnOff (alsaHalCtlMapT *control, void* handle) {
+ static int powerStatus=0;
+
+ if (! powerStatus) {
+ powerStatus = 1;
+ AFB_DEBUG ("Power Set to On");
+ } else {
+ powerStatus = 0;
+ AFB_DEBUG ("Power Set to Off");
+ }
+
+ return NULL;
+}
+
+// Map HAL hight sndctl with Alsa numid and optionally with a custom callback for non Alsa supported functionalities.
+STATIC alsaHalMapT alsaHalMap[]= {
+ { .alsa={.control=Master_Playback_Volume,.numid=16, .name="Master-Vol" , .values=1,.minval=0,.maxval= 87 ,.step=0}, .info= "Master Playback Volume" },
+ { .alsa={.control=PCM_Playback_Volume ,.numid=27, .name="Play-Vol" , .values=2,.minval=0,.maxval= 255,.step=0}, .info= "PCM Playback Volume" },
+ { .alsa={.control=PCM_Playback_Switch ,.numid=17, .name="Play-Switch" , .values=1,.minval=0,.maxval= 1 ,.step=0}, .info= "Master Playback Switch" },
+ { .alsa={.control=Capture_Volume ,.numid=12, .name="Capt-vol" , .values=2,.minval=0,.maxval= 31 ,.step=0}, .info= "Capture Volume" },
+ { .alsa={.control=Master_OnOff_Switch ,.numid=99, .name="Power-Switch"}, .cb={.callback=MasterOnOff, .handle=NULL}, .info= "OnOff Global Switch"},
+ { .alsa={.numid=0}, .cb={.callback=NULL, .handle=NULL}} /* marker for end of the array */
+} ;
+
+// HAL sound card mapping info
+STATIC alsaHalSndCardT alsaHalSndCard = {
+ .name = "Scarlett 18i8 USB", // WARNING: name MUST match with 'aplay -l'
+ .info = "Hardware Abstraction Layer for Scarlett Focusrite USB professional music sound card",
+ .ctls = alsaHalMap,
+};
+
+
+STATIC int sndServiceInit () {
+ int err;
+ AFB_DEBUG ("IntelHalBinding Init");
+
+ err = halServiceInit (afbBindingV2.api, &alsaHalSndCard);
+ return err;
+}
+
+// API prefix should be unique for each snd card
+PUBLIC const struct afb_binding_v2 afbBindingV2 = {
+ .api = "scarlett-usb",
+ .init = sndServiceInit,
+ .verbs = halServiceApi,
+ .onevent = halServiceEvent,
+};