From 6c0d556e956eaf1f4eea734d7313d258dd75b878 Mon Sep 17 00:00:00 2001 From: fulup Date: Tue, 27 Jun 2017 14:24:38 +0200 Subject: Work in Progress --- ALSA-afb/Alsa-AddCtl.c | 180 ++++++++++++++++++++++++++++++++++ ALSA-afb/Alsa-ApiHat.c | 1 + ALSA-afb/Alsa-ApiHat.h | 1 + ALSA-afb/Alsa-SetGet.c | 2 +- ALSA-afb/CMakeLists.txt | 2 +- Common/AudioCommonLib.c | 102 +++++++++++++++++++ Common/AudioCommonLib.h | 68 +++++++++++++ Common/CMakeLists.txt | 31 ++++++ HAL-afb/HAL-interface/hal-interface.c | 111 +++++++++++---------- HAL-afb/HAL-interface/hal-interface.h | 2 + HAL-afb/HDA-intel/CMakeLists.txt | 2 +- HAL-afb/HDA-intel/IntelHdaHAL.c | 21 +++- HighLevel-afb/CMakeLists.txt | 14 +-- Shared-Interface/CMakeLists.txt | 3 +- Shared-Interface/audio-interface.h | 3 +- conf.d/app-templates | 2 +- htdocs/CMakeLists.txt | 22 +++-- nbproject/configurations.xml | 63 +++++++----- 18 files changed, 529 insertions(+), 101 deletions(-) create mode 100644 ALSA-afb/Alsa-AddCtl.c create mode 100644 Common/AudioCommonLib.c create mode 100644 Common/AudioCommonLib.h create mode 100644 Common/CMakeLists.txt diff --git a/ALSA-afb/Alsa-AddCtl.c b/ALSA-afb/Alsa-AddCtl.c new file mode 100644 index 0000000..e30ebea --- /dev/null +++ b/ALSA-afb/Alsa-AddCtl.c @@ -0,0 +1,180 @@ +/* + * AlsaUseCase -- provide low level interface with ALSA 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. + +*/ +#define _GNU_SOURCE // needed for vasprintf + +#include +#include +#include "Alsa-ApiHat.h" + +STATIC int addOneSndCtl(struct afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ) { + snd_ctl_elem_info_t *cinfo; + int err; + int i; + unsigned int def_val; + json_object *jName, *jNumid, *jTmp; + const char *ctlName; + int ctlNumid, ctlMax, ctlMin, ctlStep, ctlCount, ctlSubDev; + snd_ctl_elem_type_t ctlType; + snd_ctl_elem_info_t *elemInfo; + + // parse json ctl object + json_object_object_get_ex (ctlJ, "name" , &jName); + json_object_object_get_ex (ctlJ, "numid", &jNumid); + if (!jName || !jNumid) { + afb_req_fail_f (request, "ctl-invalid", "crl=%s name/numid missing", json_object_to_json_string(ctlJ)); + goto OnErrorExit; + } + + ctlName = json_object_to_json_string(jName); + ctlNumid = json_object_get_int(jNumid); + + // default for json_object_get_int is zero + json_object_object_get_ex (ctlJ, "min" , &jTmp); + ctlMin = json_object_get_int(jTmp); + + json_object_object_get_ex (ctlJ, "max" , &jTmp); + if (!jTmp) ctlMax=1; + else ctlMax = json_object_get_int(jTmp); + + json_object_object_get_ex (ctlJ, "step" , &jTmp); + if (!jTmp) ctlStep=1; + else ctlStep = json_object_get_int(jTmp); + + json_object_object_get_ex (ctlJ, "count" , &jTmp); + if (!jTmp) ctlCount=2; + else ctlCount = json_object_get_int(jTmp); + + json_object_object_get_ex (ctlJ, "subdev" , &jTmp); + ctlSubDev = json_object_get_int(jTmp); + + json_object_object_get_ex (ctlJ, "type" , &jTmp); + if (!jTmp) ctlType=SND_CTL_ELEM_TYPE_INTEGER; + else ctlType = json_object_get_int(jTmp); + + // set info event ID and get value + snd_ctl_elem_info_alloca(&elemInfo); + snd_ctl_elem_info_set_name (elemInfo, ctlName); // map ctlInfo to ctlId elemInfo is updated !!! + snd_ctl_elem_info_set_numid(elemInfo, ctlNumid); // map ctlInfo to ctlId elemInfo is updated !!! + + if (snd_ctl_elem_info(ctlDev, elemInfo) >= 0) { + afb_req_fail_f (request, "ctl-already-exist", "crl=%s name/numid not unique", json_object_to_json_string(ctlJ)); + goto OnErrorExit; + } + + snd_ctl_elem_info_set_subdevice(elemInfo, ctlSubDev); + + switch (ctlType) { + case SND_CTL_ELEM_TYPE_BOOLEAN: + err = snd_ctl_add_boolean_elem_set(ctlDev, cinfo, 1, ctlCount); + if (err) { + afb_req_fail_f (request, "ctl-invalid-bool", "crl=%s invalid boolean data", json_object_to_json_string(ctlJ)); + goto OnErrorExit; + } + break; + + case SND_CTL_ELEM_TYPE_INTEGER: + break; + + case SND_CTL_ELEM_TYPE_INTEGER64: + break; + + case SND_CTL_ELEM_TYPE_ENUMERATED: + break; + + case SND_CTL_ELEM_TYPE_BYTES: + break; + + default: + afb_req_fail_f (request, "ctl-invalid-type", "crl=%s invalid/unknown type", json_object_to_json_string(ctlJ)); + goto OnErrorExit; + } + + + snd_ctl_elem_write(ctlDev, &ctlElem); + + return 0; + + OnErrorExit: + return -1; +} + +// Subscribe to every Alsa CtlEvent send by a given board +PUBLIC void alsaAddCustomCtl (struct afb_req request) { + snd_ctl_t *ctlDev; + int err; + const char *devid, *ctls; + json_object *ctlsJ; + + devid = afb_req_value(request, "devid"); + if (!devid) { + afb_req_fail_f (request, "missing-devid", "devid=xxx missing"); + goto OnErrorExit; + } + + // open control interface for devid + err = snd_ctl_open(&ctlDev, devid, 0); + if (err < 0) { + ctlDev=NULL; + afb_req_fail_f (request, "devid-unknown", "SndCard devid=%s Not Found err=%s", queryValues.devid, snd_strerror(err)); + goto OnErrorExit; + } + + ctls = afb_req_value(request, "ctls"); + if (!ctls) { + afb_req_fail_f (request, "missing-ctls", "ctls=[{name:xxx, numdid=xx, ...}] missing"); + goto OnErrorExit; + } + + ctlsJ = json_tokener_parse(ctls); + if (!ctlsJ) { + afb_req_fail_f (request, "ctls-notjson","ctls=%s not a valid json entry", ctls); + goto OnErrorExit; + }; + + enum json_type jtype= json_object_get_type(ctlsJ); + switch (jtype) { + int error; + json_object *ctlJ; + + case json_type_array: + int count = json_object_array_length (ctlsJ); + for (int idx=0; idx < count; idx ++) { + ctlJ = json_object_array_get_idx (ctlsJ, idx); + error = alsaAddCtrl (request, ctlDev, ctlsJ); + if (error) goto OnErrorExit; + } + break; + + case json_type_object: + error = alsaAddCtrl (request, ctlDev, ctlsJ); + if (error) goto OnErrorExit; + break; + + default: + afb_req_fail_f (request, "ctls-notarray","ctls=%s not valid JSON control object", ctls); + goto OnErrorExit; + } + + snd_ctl_close(ctlDev); + return; + + OnErrorExit: + if (ctlDev) snd_ctl_close(ctlDev); + return; +} + diff --git a/ALSA-afb/Alsa-ApiHat.c b/ALSA-afb/Alsa-ApiHat.c index 261b54d..9520ce7 100644 --- a/ALSA-afb/Alsa-ApiHat.c +++ b/ALSA-afb/Alsa-ApiHat.c @@ -47,6 +47,7 @@ static const struct afb_verb_desc_v1 binding_verbs[] = { { .name= "ucmget", .session= AFB_SESSION_NONE, .callback= alsaUseCaseGet, .info= "Use Case Get" }, { .name= "ucmreset", .session= AFB_SESSION_NONE, .callback= alsaUseCaseReset,.info= "Use Case Reset to Default" }, { .name= "ucmclose", .session= AFB_SESSION_NONE, .callback= alsaUseCaseClose,.info= "Use Case Close Manager" }, + { .name= "addctl", .session= AFB_SESSION_NONE, .callback= alsaAddCustomCtl ,.info= "Add User Custom Sound Control" }, { .name= NULL } /* marker for end of the array */ }; diff --git a/ALSA-afb/Alsa-ApiHat.h b/ALSA-afb/Alsa-ApiHat.h index c0fd51f..44ef26f 100644 --- a/ALSA-afb/Alsa-ApiHat.h +++ b/ALSA-afb/Alsa-ApiHat.h @@ -53,6 +53,7 @@ PUBLIC void alsaUseCaseSet(struct afb_req request); PUBLIC void alsaUseCaseGet(struct afb_req request); PUBLIC void alsaUseCaseClose(struct afb_req request); PUBLIC void alsaUseCaseReset(struct afb_req request); +PUBLIC void alsaAddCustomCtl(struct afb_req request); diff --git a/ALSA-afb/Alsa-SetGet.c b/ALSA-afb/Alsa-SetGet.c index abf1a6a..025846f 100644 --- a/ALSA-afb/Alsa-SetGet.c +++ b/ALSA-afb/Alsa-SetGet.c @@ -896,7 +896,7 @@ PUBLIC void alsaSubcribe (struct afb_req request) { if (err) goto OnErrorExit; - // open control interface for devid + // open control interface for devid err = snd_ctl_open(&ctlDev, queryValues.devid, SND_CTL_READONLY); if (err < 0) { ctlDev=NULL; diff --git a/ALSA-afb/CMakeLists.txt b/ALSA-afb/CMakeLists.txt index 8ba1a78..5c62149 100644 --- a/ALSA-afb/CMakeLists.txt +++ b/ALSA-afb/CMakeLists.txt @@ -20,7 +20,7 @@ PROJECT_TARGET_ADD(alsa-lowlevel) # Define project Targets - ADD_LIBRARY(alsa-lowlevel MODULE Alsa-ApiHat.c Alsa-SetGet.c Alsa-Ucm.c) + ADD_LIBRARY(alsa-lowlevel MODULE Alsa-ApiHat.c Alsa-SetGet.c Alsa-Ucm.c Alsa-AddCtl.c) # Binder exposes a unique public entry point SET_TARGET_PROPERTIES(alsa-lowlevel PROPERTIES diff --git a/Common/AudioCommonLib.c b/Common/AudioCommonLib.c new file mode 100644 index 0000000..0055896 --- /dev/null +++ b/Common/AudioCommonLib.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * 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 // needed for vasprintf + +#include +#include +#include +#include +#include + +#include "AudioCommonLib.h" + +typedef struct { + int index; + int numid; +} shareHallMap_T; + + +PUBLIC int cbCheckResponse(struct afb_req request, int iserror, struct json_object *result) { + struct json_object *response, *status, *info; + + if (iserror) { // on error proxy information we got from lower layer + if (result) { + if (json_object_object_get_ex(result, "request", &response)) { + json_object_object_get_ex(response, "info", &info); + json_object_object_get_ex(response, "status", &status); + afb_req_fail(request, json_object_get_string(status), json_object_get_string(info)); + goto OnErrorExit; + } + } else { + afb_req_fail(request, "cbCheckFail", "No Result inside API response"); + } + goto OnErrorExit; + } + return (0); + +OnErrorExit: + return (-1); +} + + +// This function should be part of Generic AGL Framework +PUBLIC json_object* afb_service_call_sync(struct afb_service srvitf, struct afb_req request, char* api, char* verb, struct json_object* queryurl) { + json_object* response = NULL; + int status = 0; + sem_t semid; + + // Nested procedure are allow in GNU and allow us to keep caller stack valid + + void callback(void *handle, int iserror, struct json_object *result) { + + // Process Basic Error + if (!cbCheckResponse(request, iserror, result)) { + status = -1; + goto OnExitCB; + } + + // Get response from object + json_object_object_get_ex(result, "response", &response); + if (!response) { + afb_req_fail_f(request, "response-notfound", "No Controls return from alsa/getcontrol result=[%s]", json_object_get_string(result)); + goto OnExitCB; + } + +OnExitCB: + sem_post(&semid); + } + + // Create an exclusive semaphore + status = sem_init(&semid, 0, 0); + if (status < 0) { + afb_req_fail_f(request, "error:seminit", "Fail to allocate semaphore err=[%s]", strerror(status)); + goto OnExit; + } + + // Call service and wait for call back to finish before moving any further + afb_service_call(srvitf, api, verb, queryurl, callback, NULL); + sem_wait(&semid); + +OnExit: + return (response); +} + +PUBLIC void pingtest(struct afb_req request) { + json_object *query = afb_req_json(request); + afb_req_success(request, query, NULL); +} diff --git a/Common/AudioCommonLib.h b/Common/AudioCommonLib.h new file mode 100644 index 0000000..ffefbfc --- /dev/null +++ b/Common/AudioCommonLib.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2016 "IoT.bzh" + * Author Fulup Ar Foll + * + * 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 + */ + +#ifndef AUDIOCOMMON_H +#define AUDIOCOMMON_H + +#include +#include +#include + +#ifndef PUBLIC + #define PUBLIC +#endif +#define STATIC static + +// Most controls are MIXER but some vendor specific are possible +typedef enum { + OUTVOL, + PCMVOL, + INVOL, + SWITCH, + ROUTE, + CARD, + ENUM, +} halGroupEnumT; + +typedef enum { + READ, + WRITE, + RW, +} halAclEnumT; + +typedef enum { + StartHalCrlTag=0, + + // HighLevel Audio Control List + Master_Playback_Volume, + PCM_Playback_Volume, + PCM_Playback_Switch, + Capture_Volume, + + EndHalCrlTag // used to compute number of ctls +} halCtlsEnumT; + +PUBLIC int cbCheckResponse(struct afb_req request, int iserror, struct json_object *result) ; +PUBLIC json_object* afb_service_call_sync(struct afb_service srvitf, struct afb_req request, char* api, char* verb, struct json_object* queryurl); +PUBLIC void pingtest(struct afb_req request); + +#endif /* AUDIOCOMMON_H */ + diff --git a/Common/CMakeLists.txt b/Common/CMakeLists.txt new file mode 100644 index 0000000..79ee8ac --- /dev/null +++ b/Common/CMakeLists.txt @@ -0,0 +1,31 @@ +########################################################################### +# Copyright 2015, 2016, 2017 IoT.bzh +# +# author: Fulup Ar Foll +# +# 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. +########################################################################### + +PROJECT(audio-common C) + +INCLUDE_DIRECTORIES(${include_dirs}) + +################################################## +# AudioCommon is a local static Library +################################################## +ADD_LIBRARY(audiocommon STATIC AudioCommonLib.c) +SET_TARGET_PROPERTIES(audiocommon PROPERTIES OUTPUT_NAME audiocommon) +SET(link_libraries ${libefence_LIBRARIES} ${json-c_LIBRARIES}) +TARGET_LINK_LIBRARIES(audiocommon ${link_libraries}) + + diff --git a/HAL-afb/HAL-interface/hal-interface.c b/HAL-afb/HAL-interface/hal-interface.c index 7876715..510ed2a 100644 --- a/HAL-afb/HAL-interface/hal-interface.c +++ b/HAL-afb/HAL-interface/hal-interface.c @@ -36,6 +36,7 @@ typedef struct { int numid; } shareHallMap_T; + static struct afb_service srvitf; static const struct afb_binding_interface *afbIface; static shareHallMap_T *shareHallMap; @@ -267,75 +268,85 @@ STATIC void halInitCB(void *handle, int iserror, struct json_object *result) { } // This receive all event this binding subscribe to -PUBLIC void afbBindingV1ServiceEvent(const char *evtname, struct json_object *object) { +PUBLIC void afbServiceEvent(const char *evtname, struct json_object *object) { - NOTICE(afbIface, "afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object)); + NOTICE(daemon, "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) { - int rc=0; +STATIC int afbServiceInit(struct afb_service service) { + int rc=0, err; srvitf = service; - struct json_object *queryurl; + struct json_object *queryurl, jResponse; + alsaHalMapT *halCtls = alsaHalSndCard.ctls; // Get sndcard specific HAL control mapping if (alsaHalSndCard.initCB) { rc= (alsaHalSndCard.initCB) (afbIface, service); - if (rc != 0) goto OnExit; + if (rc != 0) goto OnErrorExit; } // register HAL with Alsa Low Level Binder queryurl = json_object_new_object(); json_object_object_add(queryurl, "prefix", json_object_new_string(alsaHalSndCard.prefix)); json_object_object_add(queryurl, "name", json_object_new_string(alsaHalSndCard.name)); - afb_service_call(srvitf, "alsacore", "registerHal", queryurl, halInitCB, queryurl); + err= afb_req_subcall_sync (request, "alsacore", "registerHal", queryurl, &jResponse); + if (err) { + ERROR (daemon, "Fail to register HAL to ALSA lowlevel binding"); + goto OnErrorExit; + } + json_object_put(queryurl); + + // 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 (json_object_new_string(halCtls[idx].alsa.name) json_object_object_add(queryurl, "name" , json_object_new_string(halCtls[idx].alsa.name)); + if (json_object_new_string(halCtls[idx].alsa.numid) json_object_object_add(queryurl, "numid" , json_object_new_int(halCtls[idx].alsa.numid)); + if (json_object_new_string(halCtls[idx].alsa.minval) json_object_object_add(queryurl, "minval", json_object_new_int(halCtls[idx].alsa.minval)); + if (json_object_new_string(halCtls[idx].alsa.maxval) json_object_object_add(queryurl, "maxval", json_object_new_int(halCtls[idx].alsa.maxval)); + if (json_object_new_string(halCtls[idx].alsa.step) json_object_object_add(queryurl, "step" , json_object_new_int(halCtls[idx].alsa.step)); + if (json_object_new_string(halCtls[idx].alsa.type) json_object_object_add(queryurl, "type" , json_object_new_int(halCtls[idx].alsa.type)); + + err= afb_req_subcall_sync (request, "alsacore", "addUserCtl", queryurl, &jResponse); + if (err) { + ERROR (daemon, "Fail to register Callback for ctrl=[%s]", halCtls[idx].alsa.name); + goto OnErrorExit; + } + } + } + + // finally register for alsa lowlevel event + err= afb_req_subcall_sync (request, "alsacore", "subscribe", queryurl, &jResponse); + if (err) { + ERROR (daemon, "Fail subscribing to ALSA lowlevel events"); + goto OnErrorExit; + } + - OnExit: - return (rc); + return (0); + + OnErrorExit: + return (1); }; // 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 = pingtest, .info = "Ping Binding"}, - { .name = "getctls", .session = AFB_SESSION_NONE, .callback = halGetCtls, .info = "Get Control"}, - { .name = "setvol", .session = AFB_SESSION_NONE, .callback = halSetVol, .info = "Set Volume"}, - { .name = "getvol", .session = AFB_SESSION_NONE, .callback = halGetVol, .info = "Get Volume"}, - { .name = "subscribe", .session = AFB_SESSION_NONE, .callback = halSubscribe,.info = "Subscribe Alsa Events"}, - { .name = "monitor", .session = AFB_SESSION_NONE, .callback = halMonitor ,.info = "Monitor Alsa Events"}, - { .name = NULL} /* marker for end of the array */ +static const struct afb_verb_v2 halSharedApi[] = { + /* VERB'S NAME FUNCTION TO CALL SHORT DESCRIPTION */ + { .verb = "ping", .callback = pingtest, .info = "Ping Binding"}, + { .verb = "getctls", .callback = halGetCtls, .info = "Get Control"}, + { .verb = "setvol", .callback = halSetVol, .info = "Set Volume"}, + { .verb = "getvol", .callback = halGetVol, .info = "Get Volume"}, + { .verb = "subscribe", .callback = halSubscribe,.info = "Subscribe Alsa Events"}, + { .verb = "monitor", .callback = halMonitor ,.info = "Monitor Alsa Events"}, + { .verb = NULL} /* marker for end of the array */ }; - -static struct afb_binding alsaHalBinding = { - /* description conforms to VERSION 1 */ - .type= AFB_BINDING_VERSION_1, - .v1= { - .prefix= NULL, - .info = NULL, +const struct afb_binding_v2 afbBindingV2 = { + .api = "audio-hal", + .specification = "", .verbs = halSharedApi, - } -}; - -// Process HAL mapping from alsaHalSndCardT before registering HAL binder -PUBLIC const struct afb_binding *afbBindingV1Register(const struct afb_binding_interface *itf) { - - afbIface = itf; // need to keep a static trace of binder interface for avances functions - // alsaHalBinding.v1.verbs = halSharedApi; // complete sndcard specific alsaHalBinding with standard HAL APIs - alsaHalMapT *halCtls = alsaHalSndCard.ctls; // Get sndcard specific HAL control mapping - - if (halCtls == NULL) { - ERROR(afbIface, "afbBindingV1Register Fail alsaHalCtlsMap==NULL"); - return NULL; - } - - // Create a zone to store HAL high/low level mapping - shareHallMap = malloc(EndHalCrlTag * sizeof (shareHallMap_T)); - for (int idx = 0; (halCtls[idx].alsa.numid != 0 || halCtls[idx].cb.callback != NULL); idx++) { - if (halCtls[idx].alsa.numid == 0) halCtls[idx].alsa.numid =-1; - shareHallMap[halCtls[idx].alsa.control].numid = halCtls[idx].alsa.numid; - } - - alsaHalBinding.v1.prefix= alsaHalSndCard.prefix; - alsaHalBinding.v1.info = alsaHalSndCard.info; - return &alsaHalBinding; /* returns the description of the binding */ + .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 cebbd21..6aebb6e 100644 --- a/HAL-afb/HAL-interface/hal-interface.h +++ b/HAL-afb/HAL-interface/hal-interface.h @@ -23,12 +23,14 @@ typedef struct { halCtlsEnumT control; + char* name; int numid; halGroupEnumT group; int values; int minval; int maxval; int step; + snd_ctl_elem_type_t type; halAclEnumT acl; } alsaHalCtlMapT; diff --git a/HAL-afb/HDA-intel/CMakeLists.txt b/HAL-afb/HDA-intel/CMakeLists.txt index 08a39dd..4a12aee 100644 --- a/HAL-afb/HDA-intel/CMakeLists.txt +++ b/HAL-afb/HDA-intel/CMakeLists.txt @@ -39,4 +39,4 @@ PROJECT_TARGET_ADD(hal-intel-hda) # installation directory INSTALL(TARGETS hal-intel-hda - LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR}) + LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR}) \ No newline at end of file diff --git a/HAL-afb/HDA-intel/IntelHdaHAL.c b/HAL-afb/HDA-intel/IntelHdaHAL.c index bc8fc43..6967c1f 100644 --- a/HAL-afb/HDA-intel/IntelHdaHAL.c +++ b/HAL-afb/HDA-intel/IntelHdaHAL.c @@ -28,6 +28,18 @@ STATIC int IntelHalInit (const struct afb_binding_interface *itf, struct afb_ser return 0; // 0=OK } +STATIC void MasterOnOff (void * handle) { + static powerStatus=0; + + if (! powerStatus) { + powerStatus = 1; + DEBUG (itf, "Power Set to On"); + } else { + powerStatus = 0; + DEBUG (itf, "Power Set to Off"); + } +} + /****************************************************************************************** * alsaCtlsMap link hight level sound control with low level Alsa numid ctls. * @@ -41,10 +53,11 @@ STATIC int IntelHalInit (const struct afb_binding_interface *itf, struct afb_ser * .cb={.handle=xxxx, .callback=(json_object)MyCtlFunction(struct afb_service service, int controle, int value, const struct alsaHalCtlMapS *map)}; ********************************************************************************************/ STATIC alsaHalMapT alsaHalMap[]= { - { .alsa={.control=Master_Playback_Volume,.numid=16,.group=OUTVOL,.values=1,.minval=0,.maxval= 87 ,.step=0,.acl=RW}, .info= "Master Playback Volume" }, - { .alsa={.control=PCM_Playback_Volume ,.numid=27,.group=PCMVOL,.values=2,.minval=0,.maxval= 255,.step=0,.acl=RW}, .info= "PCM Playback Volume" }, - { .alsa={.control=PCM_Playback_Switch ,.numid=17,.group=SWITCH,.values=1,.minval=0,.maxval= 1 ,.step=0,.acl=RW}, .info= "Master Playback Switch" }, - { .alsa={.control=Capture_Volume ,.numid=12,.group=INVOL ,.values=2,.minval=0,.maxval= 31 ,.step=0,.acl=RW}, .info= "Capture Volume" }, + { .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=1000, .name="Power-Switch"}, .cb={.callback=MasterOnOff, .handle=NULL}} /* marker for end of the array */ { .alsa={.numid=0}, .cb={.callback=NULL, .handle=NULL}} /* marker for end of the array */ } ; diff --git a/HighLevel-afb/CMakeLists.txt b/HighLevel-afb/CMakeLists.txt index 9b540e3..9d7af4c 100644 --- a/HighLevel-afb/CMakeLists.txt +++ b/HighLevel-afb/CMakeLists.txt @@ -16,26 +16,28 @@ # limitations under the License. ########################################################################### + # Add target to project dependency list -PROJECT_TARGET_ADD(audio-afb) +PROJECT_TARGET_ADD(audio) # Define project Targets - ADD_LIBRARY(audio-afb MODULE HighLevelApiConf.c HighLevelBinding.c) + ADD_LIBRARY(audio MODULE HighLevelApiConf.c HighLevelBinding.c) # Binder exposes a unique public entry point - SET_TARGET_PROPERTIES(audio-afb PROPERTIES + SET_TARGET_PROPERTIES(audio PROPERTIES PREFIX "afb-" LABELS "BINDING" LINK_FLAGS ${BINDINGS_LINK_FLAG} OUTPUT_NAME ${TARGET_NAME} + ) # Library dependencies (include updates automatically) - TARGET_LINK_LIBRARIES(audio-afb - audio-interface + TARGET_LINK_LIBRARIES(audio + audio-inter ${link_libraries} ) # installation directory - INSTALL(TARGETS audio-afb + INSTALL(TARGETS audio LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR}) diff --git a/Shared-Interface/CMakeLists.txt b/Shared-Interface/CMakeLists.txt index 87018c9..9a5c74d 100644 --- a/Shared-Interface/CMakeLists.txt +++ b/Shared-Interface/CMakeLists.txt @@ -35,5 +35,4 @@ PROJECT_TARGET_ADD(audio-interface) # Define target includes TARGET_INCLUDE_DIRECTORIES(audio-interface PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - ) - +) \ No newline at end of file diff --git a/Shared-Interface/audio-interface.h b/Shared-Interface/audio-interface.h index 24fcfaa..ee681aa 100644 --- a/Shared-Interface/audio-interface.h +++ b/Shared-Interface/audio-interface.h @@ -23,7 +23,7 @@ #define AUDIOCOMMON_H #include -#define AFB_BINDING_VERSION 1 +#define AFB_BINDING_VERSION 2 #include #ifndef PUBLIC @@ -53,6 +53,7 @@ typedef enum { // HighLevel Audio Control List Master_Playback_Volume, + Master_OnOff_Switch, PCM_Playback_Volume, PCM_Playback_Switch, Capture_Volume, diff --git a/conf.d/app-templates b/conf.d/app-templates index ff516d1..0d3bfaf 160000 --- a/conf.d/app-templates +++ b/conf.d/app-templates @@ -1 +1 @@ -Subproject commit ff516d186889808ff61358c6ea8f88662401acaa +Subproject commit 0d3bfaf0888cb350f8721db4a4115ecb8dc4f005 diff --git a/htdocs/CMakeLists.txt b/htdocs/CMakeLists.txt index 751ff40..0026b8c 100644 --- a/htdocs/CMakeLists.txt +++ b/htdocs/CMakeLists.txt @@ -21,19 +21,25 @@ ################################################## # HTML Testing Files ################################################## -PROJECT_TARGET_ADD(html-simple-test) +PROJECT_TARGET_ADD(www_test) - add_custom_command(OUTPUT htdocs - DEPENDS ${TARGET_NAME} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND cp "*.html" PATTERN "*.js" PATTERN "*.jpg" ${CMAKE_CURRENT_BINARY_DIR} - ) + file(GLOB SOURCE_FILES "*.html" "*.js" "*.jpg") + + add_custom_target(${TARGET_NAME} + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} + ) - add_custom_target(${TARGET_NAME} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_command( + DEPENDS ${SOURCE_FILES} + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} + COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} + COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} + COMMAND cp -r ${SOURCE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME} + ) SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES LABELS "HTDOCS" - OUTPUT_NAME htdocs + OUTPUT_NAME ${TARGET_NAME} ) # use only under native Linux when using "make install" diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index 1ba69e3..c1f4a61 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -3,6 +3,7 @@ + Alsa-AddCtl.c Alsa-ApiHat.c Alsa-SetGet.c Alsa-Ucm.c @@ -62,7 +63,8 @@ false - + + true @@ -76,52 +78,39 @@ build - cmake -Wno-dev -DCXX=g++-5 -DCC=gcc-5 .. + cmake .. true + + + + - - ALSA-afb - ../../../opt/include/afb - build/ALSA-afb - - - ../../../opt/include/afb - ALSA-afb - /usr/include/json-c - build/ALSA-afb - - - ../../../opt/include/afb - ALSA-afb - /usr/include/json-c - build/ALSA-afb - - + - + - + Shared-Interface ../../../opt/include @@ -130,7 +119,7 @@ - + /usr/include/json-c Shared-Interface @@ -177,6 +166,23 @@ + + + + /usr/include/alsa + ../../../opt/include + /usr/include/json-c + Shared-Interface + build/ALSA-afb + + + CONTROL_CDEV_RX="/dev/inic-usb-crx" + CONTROL_CDEV_TX="/dev/inic-usb-ctx" + MAX_SND_CARD=16 + alsa_lowlevel_EXPORTS + + + @@ -217,12 +223,17 @@ - ../../../opt/include/afb - Shared-Interface - /usr/include/json-c + /usr/include/alsa ../../../opt/include + /usr/include/json-c + Shared-Interface build/Shared-Interface + + CONTROL_CDEV_RX="/dev/inic-usb-crx" + CONTROL_CDEV_TX="/dev/inic-usb-ctx" + MAX_SND_CARD=16 + -- cgit 1.2.3-korg