diff options
-rw-r--r-- | ALSA-afb/Alsa-AddCtl.c | 78 | ||||
-rw-r--r-- | ALSA-afb/Alsa-ApiHat.c | 61 | ||||
-rw-r--r-- | ALSA-afb/Alsa-ApiHat.h | 1 | ||||
-rw-r--r-- | ALSA-afb/Alsa-SetGet.c | 47 | ||||
-rw-r--r-- | Common/AudioCommonLib.c | 102 | ||||
-rw-r--r-- | Common/AudioCommonLib.h | 68 | ||||
-rw-r--r-- | Common/CMakeLists.txt | 31 | ||||
-rw-r--r-- | HAL-afb/HAL-interface/hal-interface.c | 104 | ||||
-rw-r--r-- | HAL-afb/HAL-interface/hal-interface.h | 14 | ||||
-rw-r--r-- | HAL-afb/HDA-intel/IntelHdaHAL.c | 24 | ||||
-rw-r--r-- | HighLevel-afb/CMakeLists.txt | 43 | ||||
-rw-r--r-- | HighLevel-afb/HighLevelApiConf.c | 98 | ||||
-rw-r--r-- | HighLevel-afb/HighLevelBinding.c | 316 | ||||
-rw-r--r-- | HighLevel-afb/HighLevelBinding.h | 54 | ||||
-rw-r--r-- | HighLevel-afb/README.md | 35 | ||||
-rw-r--r-- | Shared-Interface/audio-interface.h | 12 | ||||
-rw-r--r-- | nbproject/configurations.xml | 82 |
17 files changed, 170 insertions, 1000 deletions
diff --git a/ALSA-afb/Alsa-AddCtl.c b/ALSA-afb/Alsa-AddCtl.c index e30ebea..7593f2d 100644 --- a/ALSA-afb/Alsa-AddCtl.c +++ b/ALSA-afb/Alsa-AddCtl.c @@ -21,16 +21,14 @@ #include <systemd/sd-event.h> #include "Alsa-ApiHat.h" -STATIC int addOneSndCtl(struct afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ) { - snd_ctl_elem_info_t *cinfo; +STATIC int addOneSndCtl(afb_req request, snd_ctl_t *ctlDev, json_object *ctlJ) { 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); @@ -42,7 +40,7 @@ STATIC int addOneSndCtl(struct afb_req request, snd_ctl_t *ctlDev, json_object 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); @@ -80,7 +78,7 @@ STATIC int addOneSndCtl(struct afb_req request, snd_ctl_t *ctlDev, json_object switch (ctlType) { case SND_CTL_ELEM_TYPE_BOOLEAN: - err = snd_ctl_add_boolean_elem_set(ctlDev, cinfo, 1, ctlCount); + err = snd_ctl_add_boolean_elem_set(ctlDev, elemInfo, 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; @@ -104,77 +102,9 @@ STATIC int addOneSndCtl(struct afb_req request, snd_ctl_t *ctlDev, json_object 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 9520ce7..ced5d50 100644 --- a/ALSA-afb/Alsa-ApiHat.c +++ b/ALSA-afb/Alsa-ApiHat.c @@ -28,54 +28,31 @@ #include "Alsa-ApiHat.h" -PUBLIC const struct afb_binding_interface *afbIface; - /* * 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= pingtest, .info= "Ping Binding" }, - { .name= "getinfo", .session= AFB_SESSION_NONE, .callback= alsaGetInfo, .info= "List All/One Sound Cards Info" }, - { .name= "getctls", .session= AFB_SESSION_NONE, .callback= alsaGetCtls, .info= "Get Controls from selected sndcard" }, - { .name= "setctls", .session= AFB_SESSION_NONE, .callback= alsaSetCtls, .info= "Set 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= "ucmquery", .session= AFB_SESSION_NONE, .callback= alsaUseCaseQuery,.info= "Use Case Query" }, - { .name= "ucmset", .session= AFB_SESSION_NONE, .callback= alsaUseCaseSet, .info= "Use Case Set" }, - { .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 */ +static const struct afb_verb_v2 binding_verbs[] = { + /* VERB'S NAME FUNCTION TO CALL */ + { .verb= "ping" , .callback= pingtest }, + { .verb= "getinfo", .callback= alsaGetInfo}, + { .verb= "getctls", .callback= alsaGetCtls}, + { .verb= "setctls", .callback= alsaSetCtls}, + { .verb= "subscribe", .callback= alsaSubcribe}, + { .verb= "getcardid", .callback= alsaGetCardId}, + { .verb= "registerHal", .callback= alsaRegisterHal}, + { .verb= "ucmquery", .callback= alsaUseCaseQuery}, + { .verb= "ucmset", .callback= alsaUseCaseSet}, + { .verb= "ucmget", .callback= alsaUseCaseGet}, + { .verb= "ucmreset", .callback= alsaUseCaseReset}, + { .verb= "ucmclose", .callback= alsaUseCaseClose}, + { .verb= "addctl", .callback= alsaAddCustomCtl}, + { .verb= 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= "alsacore", - .info= "Low Level Interface to Alsa Sound Lib", - .verbs = binding_verbs - } -}; - -extern int afbBindingV1ServiceInit(struct afb_service service) { - // this is call when after all bindings are loaded - // alsaLibInit (service); // AlsaBinding check for sound card at installation time - return (0); +const struct afb_binding_v2 afbBindingV2 = { + .api = "alsacore", + .verbs = binding_verbs, }; - -/* - * activation function for registering the binding called by afb-daemon - */ -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/ALSA-afb/Alsa-ApiHat.h b/ALSA-afb/Alsa-ApiHat.h index 44ef26f..c33f92e 100644 --- a/ALSA-afb/Alsa-ApiHat.h +++ b/ALSA-afb/Alsa-ApiHat.h @@ -21,7 +21,6 @@ #include "audio-interface.h" - typedef enum { ACTION_SET, ACTION_GET diff --git a/ALSA-afb/Alsa-SetGet.c b/ALSA-afb/Alsa-SetGet.c index 025846f..d6cf50d 100644 --- a/ALSA-afb/Alsa-SetGet.c +++ b/ALSA-afb/Alsa-SetGet.c @@ -103,7 +103,7 @@ PUBLIC void NumidsListParse (queryValuesT *queryValues, ctlRequestT *ctlRequest) case json_type_object: // numid+values formated as {id:xxx, val:[aa,bb...,nn]} if (!json_object_object_get_ex (ctlRequest[idx].jToken,"id", &jId) || !json_object_object_get_ex (ctlRequest[idx].jToken,"val",&jVal)) { - NOTICE (afbIface,"Invalid Json=%s missing 'id'|'val'", json_object_get_string(ctlRequest[idx].jToken)); + NOTICE("Invalid Json=%s missing 'id'|'val'", json_object_get_string(ctlRequest[idx].jToken)); ctlRequest[idx].used=-1; } else { ctlRequest[idx].numId =json_object_get_int(jId); @@ -117,8 +117,7 @@ PUBLIC void NumidsListParse (queryValuesT *queryValues, ctlRequestT *ctlRequest) } } -PUBLIC int alsaCheckQuery (struct afb_req request, queryValuesT *queryValues) { - +PUBLIC int alsaCheckQuery (afb_req request, queryValuesT *queryValues) { queryValues->devid = afb_req_value(request, "devid"); if (queryValues->devid == NULL) goto OnErrorExit; const char *numids; @@ -384,14 +383,14 @@ STATIC json_object* alsaCardProbe (const char *rqtSndId) { int err; if ((err = snd_ctl_open(&handle, rqtSndId, 0)) < 0) { - INFO (afbIface, "SndCard [%s] Not Found", rqtSndId); + INFO ("SndCard [%s] Not Found", rqtSndId); return NULL; } snd_ctl_card_info_alloca(&cardinfo); if ((err = snd_ctl_card_info(handle, cardinfo)) < 0) { snd_ctl_close(handle); - WARNING (afbIface, "SndCard [%s] info error: %s", rqtSndId, snd_strerror(err)); + WARNING ("SndCard [%s] info error: %s", rqtSndId, snd_strerror(err)); return NULL; } @@ -403,13 +402,13 @@ STATIC json_object* alsaCardProbe (const char *rqtSndId) { name = snd_ctl_card_info_get_name(cardinfo); json_object_object_add (ctlDev, "name", json_object_new_string (name)); - if (afbIface->verbosity > 1) { + if (AFB_GET_VERBOSITY > 1) { json_object_object_add (ctlDev, "devid", json_object_new_string(rqtSndId)); driver= snd_ctl_card_info_get_driver(cardinfo); json_object_object_add (ctlDev, "driver" , json_object_new_string(driver)); info = strdup(snd_ctl_card_info_get_longname (cardinfo)); json_object_object_add (ctlDev, "info" , json_object_new_string (info)); - INFO (afbIface, "AJG: Soundcard Devid=%-5s devid=%-7s Name=%s\n", rqtSndId, devid, info); + INFO ("AJG: Soundcard Devid=%-5s devid=%-7s Name=%s\n", rqtSndId, devid, info); } // free card handle and return info @@ -418,7 +417,7 @@ STATIC json_object* alsaCardProbe (const char *rqtSndId) { } // Loop on every potential Sound card and register active one -PUBLIC void alsaGetInfo (struct afb_req request) { +PUBLIC void alsaGetInfo (afb_req request) { int card; json_object *ctlDev, *ctlDevs; char devid[32]; @@ -491,13 +490,13 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe snd_ctl_elem_info_alloca(&elemInfo); snd_ctl_elem_info_set_id(elemInfo, elemId); // map ctlInfo to ctlId elemInfo is updated !!! if (snd_ctl_elem_info(ctlDev, elemInfo) < 0) { - NOTICE (afbIface, "Fail to load ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); + NOTICE( "Fail to load ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); goto OnErrorExit; } snd_ctl_elem_info_get_id(elemInfo, elemId); // map ctlInfo to ctlId elemInfo is updated !!! if (!snd_ctl_elem_info_is_writable(elemInfo)) { - NOTICE (afbIface, "Not Writable ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); + NOTICE( "Not Writable ALSA NUMID=%d Values=[%s]", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues)); goto OnErrorExit; } @@ -521,7 +520,7 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe if (count == 0 || count < length) { - NOTICE (afbIface, "Invalid values NUMID='%d' Values='%s' count='%d' wanted='%d'", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), length, count); + NOTICE( "Invalid values NUMID='%d' Values='%s' count='%d' wanted='%d'", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), length, count); goto OnErrorExit; } @@ -543,7 +542,7 @@ STATIC int alsaSetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe err = snd_ctl_elem_write(ctlDev, elemData); if (err < 0) { - NOTICE (afbIface, "Fail to write ALSA NUMID=%d Values=[%s] Error=%s", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), snd_strerror(err)); + NOTICE( "Fail to write ALSA NUMID=%d Values=[%s] Error=%s", ctlRequest->numId, json_object_to_json_string(ctlRequest->jValues), snd_strerror(err)); goto OnErrorExit; } @@ -682,7 +681,7 @@ STATIC int alsaGetSingleCtl (snd_ctl_t *ctlDev, snd_ctl_elem_id_t *elemId, ctlRe } // assign multiple control to the same value -PUBLIC void alsaSetGetCtls (struct afb_req request, ActionSetGetT action) { +PUBLIC void alsaSetGetCtls (afb_req request, ActionSetGetT action) { ctlRequestT *ctlRequest; const char *warmsg=NULL; int err=0, status=0; @@ -737,7 +736,7 @@ PUBLIC void alsaSetGetCtls (struct afb_req request, ActionSetGetT action) { } else { int numid = snd_ctl_elem_list_get_numid(ctlList, ctlIndex); if (numid < 0) { - NOTICE (afbIface,"snd_ctl_elem_list_get_numid index=%d fail", ctlIndex); + NOTICE("snd_ctl_elem_list_get_numid index=%d fail", ctlIndex); continue; } // check if current control was requested in query numids list @@ -806,11 +805,11 @@ PUBLIC void alsaSetGetCtls (struct afb_req request, ActionSetGetT action) { return; } -PUBLIC void alsaGetCtls (struct afb_req request) { +PUBLIC void alsaGetCtls (afb_req request) { alsaSetGetCtls (request, ACTION_GET); } -PUBLIC void alsaSetCtls (struct afb_req request) { +PUBLIC void alsaSetCtls (afb_req request) { alsaSetGetCtls (request, ACTION_SET); } @@ -830,7 +829,7 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* snd_ctl_elem_id_t *elemId; if ((revents & EPOLLHUP) != 0) { - NOTICE (afbIface, "SndCtl hanghup [car disconnected]"); + NOTICE( "SndCtl hanghup [car disconnected]"); goto ExitOnSucess; } @@ -869,7 +868,7 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* json_object_object_add(ctlEventJ, "devname",json_object_new_string (devname)); } if (ctlRequest.jValues) (json_object_object_add(ctlEventJ, "values" ,ctlRequest.jValues)); - DEBUG(afbIface, "sndCtlEventCB=%s", json_object_get_string(ctlEventJ)); + DEBUG( "sndCtlEventCB=%s", json_object_get_string(ctlEventJ)); afb_event_push(evtHandle->afbevt, ctlEventJ); } @@ -878,12 +877,12 @@ STATIC int sndCtlEventCB (sd_event_source* src, int fd, uint32_t revents, void* return 0; OnErrorExit: - WARNING (afbIface, "sndCtlEventCB: ignored unsupported event type"); + WARNING ("sndCtlEventCB: ignored unsupported event type"); return (0); } // Subscribe to every Alsa CtlEvent send by a given board -PUBLIC void alsaSubcribe (struct afb_req request) { +PUBLIC void alsaSubcribe (afb_req request) { static sndHandleT sndHandles[MAX_SND_CARD]; evtHandleT *evtHandle; snd_ctl_t *ctlDev; @@ -947,14 +946,14 @@ PUBLIC void alsaSubcribe (struct afb_req request) { snd_ctl_poll_descriptors(evtHandle->ctlDev, &evtHandle->pfds, 1); // register sound event to binder main loop - err = sd_event_add_io(afb_daemon_get_event_loop(afbIface->daemon), &evtHandle->src, evtHandle->pfds.fd, EPOLLIN, sndCtlEventCB, evtHandle); + err = sd_event_add_io(afb_daemon_get_event_loop(), &evtHandle->src, evtHandle->pfds.fd, EPOLLIN, sndCtlEventCB, evtHandle); if (err < 0) { afb_req_fail_f (request, "register-mainloop", "Cannot hook events to mainloop devid=%s err=%d", queryValues.devid, err); goto OnErrorExit; } // create binder event attached to devid name - evtHandle->afbevt = afb_daemon_make_event (afbIface->daemon, queryValues.devid); + evtHandle->afbevt = afb_daemon_make_event (queryValues.devid); if (!afb_event_is_valid (evtHandle->afbevt)) { afb_req_fail_f (request, "register-event", "Cannot register new binder event name=%s", queryValues.devid); goto OnErrorExit; @@ -982,7 +981,7 @@ PUBLIC void alsaSubcribe (struct afb_req request) { } // Subscribe to every Alsa CtlEvent send by a given board -PUBLIC void alsaGetCardId (struct afb_req request) { +PUBLIC void alsaGetCardId (afb_req request) { char devid [10]; const char *devname, *shortname, *longname; int card, err, index, idx; @@ -1047,7 +1046,7 @@ PUBLIC void alsaGetCardId (struct afb_req request) { } // Register loaded HAL with board Name and API prefix -PUBLIC void alsaRegisterHal (struct afb_req request) { +PUBLIC void alsaRegisterHal (afb_req request) { static int index=0; const char *shortname, *apiPrefix; diff --git a/Common/AudioCommonLib.c b/Common/AudioCommonLib.c deleted file mode 100644 index 0055896..0000000 --- a/Common/AudioCommonLib.c +++ /dev/null @@ -1,102 +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 // needed for vasprintf - -#include <json-c/json.h> -#include <afb/afb-binding.h> -#include <afb/afb-service-itf.h> -#include <semaphore.h> -#include <string.h> - -#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 deleted file mode 100644 index ffefbfc..0000000 --- a/Common/AudioCommonLib.h +++ /dev/null @@ -1,68 +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 - */ - -#ifndef AUDIOCOMMON_H -#define AUDIOCOMMON_H - -#include <json-c/json.h> -#include <afb/afb-binding.h> -#include <afb/afb-service-itf.h> - -#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 deleted file mode 100644 index 79ee8ac..0000000 --- a/Common/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -########################################################################### -# 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. -########################################################################### - -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 510ed2a..2c6595f 100644 --- a/HAL-afb/HAL-interface/hal-interface.c +++ b/HAL-afb/HAL-interface/hal-interface.c @@ -36,9 +36,6 @@ typedef struct { int numid; } shareHallMap_T; - -static struct afb_service srvitf; -static const struct afb_binding_interface *afbIface; static shareHallMap_T *shareHallMap; // Force specific HAL to depend on ShareHalLib @@ -46,12 +43,12 @@ PUBLIC char* SharedHalLibVersion="1.0"; // 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); + 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)); + 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; @@ -65,23 +62,8 @@ STATIC void alsaSubcribeCB(void *handle, int iserror, struct json_object *result 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) { +STATIC void halSubscribe(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"); @@ -89,8 +71,7 @@ STATIC void halSubscribe(struct afb_req request) { } // Call when all bindings are loaded and ready to accept request - -STATIC void halGetVol(struct afb_req request) { +STATIC void halGetVol(afb_req request) { // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card afb_req_success(request, NULL, NULL); @@ -98,7 +79,7 @@ STATIC void halGetVol(struct afb_req request) { } -STATIC void halSetVol(struct afb_req request) { +STATIC void halSetVol(afb_req request) { const char *arg; const char *pcm; @@ -148,7 +129,7 @@ STATIC void halGetControlCB(void *handle, int iserror, struct json_object *resul struct json_object *response; // retrieve request and check for errors - struct afb_req request = afb_req_unstore(handle); + afb_req request = afb_req_unstore(handle); if (!cbCheckResponse(request, iserror, result)) goto OnExit; // Get response from object @@ -208,7 +189,7 @@ STATIC void halGetControlCB(void *handle, int iserror, struct json_object *resul // Translate high level control to low level and call lower layer -STATIC void halGetCtls(struct afb_req request) { +STATIC void halGetCtls(afb_req request) { struct json_object *queryin, *queryout, *ctlsin, *devid; struct json_object *ctlsout = json_object_new_array(); @@ -251,47 +232,42 @@ STATIC void halGetCtls(struct afb_req request) { json_object_object_add(queryout, "devid", devid); json_object_object_add(queryout, "ctls", ctlsout); - // save request context dans call lowlevel API - struct afb_req *handle = afb_req_store(request); - afb_service_call(srvitf, "alsacore", "getctl", queryout, halGetControlCB, handle); + // Fulup afb_service_call("alsacore", "getctl", queryout, halGetControlCB, handle); OnExit: // Under normal situation success/failure is set from callback return; }; -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 afbServiceEvent(const char *evtname, struct json_object *object) { - NOTICE(daemon, "afbBindingV1ServiceEvent evtname=%s [msg=%s]", evtname, json_object_to_json_string(object)); + 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(struct afb_service service) { +STATIC int afbServiceInit() { int rc=0, err; - srvitf = service; - struct json_object *queryurl, jResponse; + struct json_object *queryurl, *jResponse; alsaHalMapT *halCtls = alsaHalSndCard.ctls; // Get sndcard specific HAL control mapping if (alsaHalSndCard.initCB) { - rc= (alsaHalSndCard.initCB) (afbIface, service); + rc= (alsaHalSndCard.initCB)(); if (rc != 0) goto OnErrorExit; } + err= afb_daemon_require_api("alsacore", 1); + // 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, "prefix", json_object_new_string(sndCardApiPrefix)); json_object_object_add(queryurl, "name", json_object_new_string(alsaHalSndCard.name)); - err= afb_req_subcall_sync (request, "alsacore", "registerHal", queryurl, &jResponse); + + afb_service_call_sync("alsacore", "registerHal", queryurl, &jResponse); + err= afb_service_call_sync ("alsacore", "registerHal", queryurl, &jResponse); if (err) { - ERROR (daemon, "Fail to register HAL to ALSA lowlevel binding"); + ERROR ("Fail to register HAL to ALSA lowlevel binding"); goto OnErrorExit; } json_object_put(queryurl); @@ -300,29 +276,28 @@ STATIC int afbServiceInit(struct afb_service service) { 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)); + 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)); - err= afb_req_subcall_sync (request, "alsacore", "addUserCtl", queryurl, &jResponse); + err= afb_service_call_sync ("alsacore", "addUserCtl", queryurl, &jResponse); if (err) { - ERROR (daemon, "Fail to register Callback for ctrl=[%s]", halCtls[idx].alsa.name); + ERROR ("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); + err= afb_service_call_sync ("alsacore", "subscribe", queryurl, &jResponse); if (err) { - ERROR (daemon, "Fail subscribing to ALSA lowlevel events"); + ERROR ("Fail subscribing to ALSA lowlevel events"); goto OnErrorExit; } - return (0); OnErrorExit: @@ -330,20 +305,21 @@ STATIC int afbServiceInit(struct afb_service service) { }; // Every HAL export the same API & Interface Mapping from SndCard to AudioLogic is done through alsaHalSndCardT -static const struct afb_verb_v2 halSharedApi[] = { +STATIC 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 = "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 */ }; -const struct afb_binding_v2 afbBindingV2 = { - .api = "audio-hal", - .specification = "", + +PUBLIC const struct afb_binding_v2 afbBindingV2 = { + .api = sndCardApiPrefix, + .specification = NULL, .verbs = halSharedApi, .preinit = NULL, .init = afbServiceInit, diff --git a/HAL-afb/HAL-interface/hal-interface.h b/HAL-afb/HAL-interface/hal-interface.h index 6aebb6e..e08ec18 100644 --- a/HAL-afb/HAL-interface/hal-interface.h +++ b/HAL-afb/HAL-interface/hal-interface.h @@ -19,6 +19,8 @@ #define SHAREHALLIB_H #include <stdio.h> +#include <alsa/asoundlib.h> + #include "audio-interface.h" typedef struct { @@ -37,8 +39,11 @@ 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)(alsaHalServiceT service, int control, int value, alsaHalCtlMapT *map, void* handle); + struct json_object* (*callback)(alsaHalCtlMapT *control, void* handle); void* handle; } alsaHalCbMapT; @@ -48,17 +53,16 @@ typedef struct { char* info; } alsaHalMapT; -typedef struct { - const char *prefix; + +typedef const struct { const char *name; const char *info; alsaHalMapT *ctls; - int (*initCB) (const struct afb_binding_interface *itf, struct afb_service service); + int (*initCB) (void); } alsaHalSndCardT; PUBLIC alsaHalSndCardT alsaHalSndCard; -PUBLIC char* SharedHalLibVersion; #endif /* SHAREHALLIB_H */ diff --git a/HAL-afb/HDA-intel/IntelHdaHAL.c b/HAL-afb/HDA-intel/IntelHdaHAL.c index 6967c1f..98ac442 100644 --- a/HAL-afb/HDA-intel/IntelHdaHAL.c +++ b/HAL-afb/HDA-intel/IntelHdaHAL.c @@ -18,25 +18,22 @@ #include "hal-interface.h" #include "audio-interface.h" -// Force a hard dependency to ShareHallLib -PUBLIC char* SharedHalLibVersion; - // Init is call after all binding are loaded -STATIC int IntelHalInit (const struct afb_binding_interface *itf, struct afb_service service) { - DEBUG (itf, "IntelHalBinding Initialised"); +STATIC int IntelHalInit (void) { + DEBUG ("IntelHalBinding Initialised"); return 0; // 0=OK } -STATIC void MasterOnOff (void * handle) { - static powerStatus=0; +STATIC void MasterOnOff (alsaHalCtlMapT *control, void* handle) { + static int powerStatus=0; if (! powerStatus) { powerStatus = 1; - DEBUG (itf, "Power Set to On"); + DEBUG ("Power Set to On"); } else { powerStatus = 0; - DEBUG (itf, "Power Set to Off"); + DEBUG ("Power Set to Off"); } } @@ -57,7 +54,7 @@ STATIC alsaHalMapT alsaHalMap[]= { { .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={.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 */ } ; @@ -72,10 +69,15 @@ STATIC alsaHalMapT alsaHalMap[]= { * 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", .info = "Hardware Abstraction Layer for IntelHDA sound card", .ctls = alsaHalMap, - .prefix="intel-hda", .initCB=IntelHalInit, // if NULL no initcallback }; + diff --git a/HighLevel-afb/CMakeLists.txt b/HighLevel-afb/CMakeLists.txt deleted file mode 100644 index 9d7af4c..0000000 --- a/HighLevel-afb/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -########################################################################### -# 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(audio) - - # Define project Targets - ADD_LIBRARY(audio MODULE HighLevelApiConf.c HighLevelBinding.c) - - # Binder exposes a unique public entry point - 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 - audio-inter - ${link_libraries} - ) - - # installation directory - INSTALL(TARGETS audio - LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR}) diff --git a/HighLevel-afb/HighLevelApiConf.c b/HighLevel-afb/HighLevelApiConf.c deleted file mode 100644 index 75e4a2f..0000000 --- a/HighLevel-afb/HighLevelApiConf.c +++ /dev/null @@ -1,98 +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 "HighLevelBinding.h" - -PUBLIC const struct afb_binding_interface *afbIface; - -// Map HAL Enum to Labels -typedef const struct { - halCtlsEnumT control; - char *label; -} LogicControlT; - -// High Level Control Mapping to String for JSON & HTML5 -STATIC LogicControlT LogicControl[] = { - {.control= Master_Playback_Volume,.label= "Master_Volume"}, - {.control= PCM_Playback_Volume, .label= "Playback_Volume"}, - {.control= PCM_Playback_Switch, .label= "Playback_Switch"}, - {.control= Capture_Volume, .label= "Capture_Volume"}, - - {.control= 0,.label= NULL} // closing convention -}; - - -/* - * 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= pingtest, .info= "Ping Binding" }, - { .name= "setvolume", .session= AFB_SESSION_CHECK, .callback= audioLogicSetVol, .info= "Set Volume" }, - { .name= "getvolume", .session= AFB_SESSION_CHECK, .callback= audioLogicGetVol, .info= "Get Volume" }, - { .name= "subscribe", .session= AFB_SESSION_CHECK, .callback= audioLogicSubscribe, .info= "Subscribe AudioBinding Events" }, - { .name= "monitor", .session= AFB_SESSION_CHECK, .callback= audioLogicMonitor, .info= "Activate AlsaCtl Monitoring" }, - { .name= "open", .session= AFB_SESSION_CREATE,.callback= audioLogicOpen, .info= "Open a Dedicated SoundCard" }, - { .name= "close", .session= AFB_SESSION_CLOSE, .callback= audioLogicClose, .info= "Close previously open SoundCard" }, - { .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= "audio", - .info= "High Level Interface to Audio bindings", - .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 (audioLogicInit(service)); -}; - -/* - * 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/HighLevel-afb/HighLevelBinding.c b/HighLevel-afb/HighLevelBinding.c deleted file mode 100644 index 07ed2fc..0000000 --- a/HighLevel-afb/HighLevelBinding.c +++ /dev/null @@ -1,316 +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 "HighLevelBinding.h" - -static struct afb_service srvitf; - - -// This callback is fired when afb_service_call for api/alsacore/subctl returns -STATIC void audioLogicSetVolCB(void *handle, int iserror, struct json_object *result) { - struct afb_req request = afb_req_unstore(handle); - - if (!cbCheckResponse(request, iserror, result)) goto OnExit; - -OnExit: - return; -} - -PUBLIC void audioLogicSetVol(struct afb_req request) { - struct json_object *queryurl; - int volume=0; // FULUP TBD !!!!!!!!!!!! - - // keep request for callback to respond - struct afb_req *handle = afb_req_store(request); - - // get client context - AudioLogicCtxT *ctx = afb_req_context_get(request); - - const char *vol = afb_req_value(request, "vol"); - if (vol == NULL) { - afb_req_fail_f(request, "argument-missing", "vol=+-%%[0,100] missing"); - goto OnExit; - } - - switch (vol[0]) { - case '+': - break; - case '-': - break; - case '%': - break; - - default: - afb_req_fail_f(request, "value-invalid", "volume should be (+-%%[0-100]xxx) vol=%s", vol); - goto OnExit; - } - - if (!ctx->halapi) { - afb_req_fail_f(request, "context-invalid", "No valid halapi in client context"); - goto OnExit; - } - - // ********** Caluler le volume en % de manière intelligente - queryurl = json_object_new_object(); - json_object_object_add(ctx->queryurl, "pcm", json_object_new_int(Master_Playback_Volume)); - json_object_object_add(ctx->queryurl, "value", json_object_new_int(volume)); - - // subcontract HAL API to process volume - afb_service_call(srvitf, ctx->halapi, "volume", queryurl, audioLogicSetVolCB, handle); - - // final success/failure messages handle from callback -OnExit: - return; -} - -// 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); - - if (!cbCheckResponse(request, iserror, result)) goto OnExit; - -OnExit: - return; -} - -// Create and subscribe to alsacore ctl events -PUBLIC void audioLogicMonitor(struct afb_req request) { - - - // get client context - AudioLogicCtxT *ctx = afb_req_context_get(request); - if (!ctx) { - afb_req_fail_f(request, "ctx-notfound", "No Client Context HAL/getcontrol devid=[%s] name=[%s]", ctx->devid, ctx->shortname); - goto OnExit; - } - - // push request to low level binding - NOTICE(afbIface, "audioLogicMonitor ctx->devid=%s [ctx->queryurl=%s]", ctx->devid, json_object_to_json_string(ctx->queryurl)); - - if (ctx->queryurl) { - json_object_get(ctx->queryurl); // Make sure usage count does not fall to zero - struct afb_req *handle = afb_req_store(request); - afb_service_call(srvitf, "alsacore", "subscribe", ctx->queryurl, alsaSubcribeCB, handle); - } - else afb_req_fail_f(request, "context-invalid", "No valid queryurl in client context"); - - // success/failure messages return from callback -OnExit: - return; -} - -// Subscribe to AudioBinding events - -PUBLIC void audioLogicSubscribe(struct afb_req request) { - - return; -} - - -// Call when all bindings are loaded and ready to accept request -PUBLIC void audioLogicGetVol(struct afb_req request) { - - // Should call here Hardware Alsa Abstraction Layer for corresponding Sound Card - afb_req_success(request, NULL, NULL); - return; - -} - -// This callback is fired when afb_service_call for api/alsacore/subctl returns - -STATIC void audioLogicOpenCB2(void *handle, int iserror, struct json_object *result) { - struct json_object *response; - - // Make sure we got a response from API - struct afb_req request = afb_req_unstore(handle); - if (!cbCheckResponse(request, iserror, result)) goto OnExit; - - // get client context - AudioLogicCtxT *ctx = afb_req_context_get(request); - if (!ctx) { - afb_req_fail_f(request, "ctx-notfound", "No Client Context HAL/getcontrol devid=[%s] name=[%s]", ctx->devid, ctx->shortname); - goto OnExit; - } - - // 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 HAL/getcontrol devid=[%s] name=[%s]", ctx->devid, ctx->shortname); - goto OnExit; - } - - // extract sounds controls information from received Object - struct json_object *ctls; - json_object_object_get_ex(response, "ctls", &ctls); - if (!ctls) { - afb_req_fail_f(request, "ctls-notfound", "No Controls return from HAL/getcontrol devid=[%s] name=[%s]", ctx->devid, ctx->shortname); - goto OnExit; - } - - // make sure return controls have a valid type - if (json_object_get_type(ctls) != json_type_array) { - afb_req_fail_f(request, "ctls-notarray", "Invalid Controls return from HAL/getcontrol devid=[%s] name=[%s]", ctx->devid, ctx->shortname); - goto OnExit; - } - - // loop on array and store values into client context - for (int idx = 0; idx < json_object_array_length(ctls); idx++) { - struct json_object *ctl; - halCtlsEnumT control; - int 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 return from HAL/getcontrol devid=[%s] name=[%s] ctl=%s" - , ctx->devid, ctx->shortname, json_object_get_string(ctl)); - goto OnExit; - } - - // As HAL and Business logic use the same AlsaMixerHal.h direct conversion is not an issue - control = (halCtlsEnumT) json_object_get_int(json_object_array_get_idx(ctl, 0)); - value = json_object_get_int(json_object_array_get_idx(ctl, 1)); - - switch (control) { - case Master_Playback_Volume: - ctx->volumes.masterPlaybackVolume = value; - break; - - case PCM_Playback_Volume: - ctx->volumes.pcmPlaybackVolume = value; - break; - - case PCM_Playback_Switch: - ctx->volumes.pcmPlaybackSwitch = value; - break; - - case Capture_Volume: - ctx->volumes.captureVolume = value; - break; - - default: - NOTICE(afbIface, "audioLogicOpenCB2 unknown HAL control=[%s]", json_object_get_string(ctl)); - } - } - -OnExit: - afb_req_context_set(request, ctx, free); - return; -} - -// This callback is fired when afb_service_call for api/alsacore/subctl returns -STATIC void audioLogicOpenCB1(void *handle, int iserror, struct json_object *result) { - struct json_object *response, *subobj; - - // Make sure we got a valid API response - struct afb_req request = afb_req_unstore(handle); - if (!cbCheckResponse(request, iserror, result)) goto OnExit; - - // 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 HAL/getcontrol"); - goto OnExit; - } - - // attach client context to session - AudioLogicCtxT *ctx = malloc(sizeof (AudioLogicCtxT)); - - // extract information from Json Alsa Object - json_object_object_get_ex(response, "cardid", &subobj); - if (subobj) ctx->cardid = json_object_get_int(subobj); - - // store devid as an object for further alsa request - json_object_object_get_ex(response, "devid", &subobj); - if (subobj) ctx->devid = strdup(json_object_get_string(subobj)); - - json_object_object_get_ex(response, "halapi", &subobj); - if (subobj) ctx->halapi = strdup(json_object_get_string(subobj)); - - json_object_object_get_ex(response, "shortname", &subobj); - if (subobj)ctx->shortname = strdup(json_object_get_string(subobj)); - - json_object_object_get_ex(response, "longname", &subobj); - if (subobj)ctx->longname = strdup(json_object_get_string(subobj)); - - // save queryurl with devid only for further ALSA request - ctx->queryurl = json_object_new_object(); - json_object_object_add(ctx->queryurl, "devid", json_object_new_string(ctx->devid)); - - afb_req_context_set(request, ctx, free); - - // sound card was find let's store keycontrols into client session - if (!ctx->halapi) { - afb_req_fail_f(request, "hal-notfound", "No HAL found devid=[%s] name=[%s]", ctx->devid, ctx->shortname); - goto OnExit; - } - - struct json_object *queryurl = json_object_new_object(); - struct json_object *ctls = json_object_new_array(); - - // add sound controls we want to keep track of into client session context - json_object_array_add(ctls, json_object_new_int((int) Master_Playback_Volume)); - json_object_array_add(ctls, json_object_new_int((int) PCM_Playback_Volume)); - json_object_array_add(ctls, json_object_new_int((int) PCM_Playback_Switch)); - json_object_array_add(ctls, json_object_new_int((int) Capture_Volume)); - - // send request to soundcard HAL binding - json_object_object_add(queryurl, "ctls", ctls); - handle = afb_req_store(request); // FULUP ???? Needed for 2nd Callback ???? - afb_service_call(srvitf, ctx->halapi, "getControl", queryurl, audioLogicOpenCB2, handle); - - afb_req_success(request, response, NULL); - -OnExit: - // release original calling request - afb_req_unref(request); - return; -} - -// Delegate to lowerlevel the mapping of soundcard name with soundcard ID -PUBLIC void audioLogicOpen(struct afb_req request) { - - // Delegate query to lower level - struct afb_req *handle = afb_req_store(request); - afb_service_call(srvitf, "alsacore", "getCardId", json_object_get(afb_req_json(request)), audioLogicOpenCB1, handle); -} - -// Free client context create from audioLogicOpenCB -PUBLIC void audioLogicClose(struct afb_req request) { - - // retrieve current client context to print debug info - AudioLogicCtxT *ctx = (AudioLogicCtxT*) afb_req_context_get(request); - DEBUG(afbIface, "audioLogicClose cardid=%d devid=%s shortname=%s longname=%s", ctx->cardid, ctx->devid, ctx->shortname, ctx->longname); -} - - -// this function is call after all binder are loaded and initialised -PUBLIC int audioLogicInit(struct afb_service service) { - srvitf = service; - return 0; -} diff --git a/HighLevel-afb/HighLevelBinding.h b/HighLevel-afb/HighLevelBinding.h deleted file mode 100644 index c1a0aef..0000000 --- a/HighLevel-afb/HighLevelBinding.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 AUDIOLOGIC_H -#define AUDIOLOGIC_H - -#include "audio-interface.h" - -// import from AlsaAfbBinding -extern const struct afb_binding_interface *afbIface; - - -// This structure hold private data for a given client of binding -typedef struct { - - int cardid; - const char *devid; - const char *shortname; - const char *longname; - const char *halapi; - struct { // volume in % [0-100] - int masterPlaybackVolume; - int pcmPlaybackVolume; - int pcmPlaybackSwitch; - int captureVolume; - } volumes; - json_object *queryurl; -} AudioLogicCtxT; - -// import from AlsaAfbMapping -PUBLIC void audioLogicSetVol (struct afb_req request); -PUBLIC void audioLogicGetVol(struct afb_req request); -PUBLIC void audioLogicMonitor(struct afb_req request); -PUBLIC void audioLogicOpen(struct afb_req request); -PUBLIC void audioLogicClose(struct afb_req request); -PUBLIC void audioLogicSubscribe(struct afb_req request); -PUBLIC int audioLogicInit (struct afb_service service); - -#endif /* AUDIOLOGIC_H */ - diff --git a/HighLevel-afb/README.md b/HighLevel-afb/README.md deleted file mode 100644 index fa50173..0000000 --- a/HighLevel-afb/README.md +++ /dev/null @@ -1,35 +0,0 @@ ------------------------------------------------------------------------- - AudioLogic High Level APIs ------------------------------------------------------------------------- - -Testing: (from project directory bindings) - * start binder: ~/opt/bin/afb-daemon --ldpaths=./build --token=mysecret --roothttp=htdocs - * connect browser on http://localhost:1234?devid=hw:0 - - # Open Sound Card from its name - http://localhost:1234/api/audio/open?token=mysecret&sndname=H650e - - # Subscribe event for a given board - http://localhost:1234/api/audio/subscribe?token=mysecret&devid=hw:0 - - # Increase Volume - http://localhost:1234/api/audio/setvol?token=mysecret&devid=hw:0&pcm=master&vol=50% - - # Get Volume - http://localhost:1234/api/audio/getvol?token=mysecret&devid=hw:0&pcm=master - - # Close Session - http://localhost:1234/api/audio/close?token=mysecret - - -Testing with afb-client-demo - -``` -~/opt/bin/afb-client-demo localhost:1234/api?token=mysecret -alsacore subctl {"devid":"hw:0"} -``` - -Start AlsaMixer and change volume -``` -alsamixer -D hw:0 -```
\ No newline at end of file diff --git a/Shared-Interface/audio-interface.h b/Shared-Interface/audio-interface.h index ee681aa..4fbda4b 100644 --- a/Shared-Interface/audio-interface.h +++ b/Shared-Interface/audio-interface.h @@ -19,13 +19,17 @@ * http://www.tldp.org/HOWTO/Alsa-sound-6.html */ -#ifndef AUDIOCOMMON_H -#define AUDIOCOMMON_H +#ifndef AUDIO_INTERF_H +#define AUDIO_INTERF_H -#include <json-c/json.h> #define AFB_BINDING_VERSION 2 + +#include <json-c/json.h> #include <afb/afb-binding.h> +// Waiting for official macro from José +#define AFB_GET_VERBOSITY afb_get_verbosity_v2() + #ifndef PUBLIC #define PUBLIC #endif @@ -64,5 +68,5 @@ typedef enum { PUBLIC int cbCheckResponse(struct afb_req request, int iserror, struct json_object *result) ; PUBLIC void pingtest(struct afb_req request); -#endif /* AUDIOCOMMON_H */ +#endif /* AUDIO_INTERF_H */ diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index c1f4a61..02884db 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -8,6 +8,9 @@ <in>Alsa-SetGet.c</in> <in>Alsa-Ucm.c</in> </df> + <df name="Common"> + <in>AudioCommonLib.c</in> + </df> <df name="HAL-afb"> <df name="HAL-interface"> <in>hal-interface.c</in> @@ -74,7 +77,7 @@ <buildCommandWorkingDir>build</buildCommandWorkingDir> <buildCommand>${MAKE} -f Makefile</buildCommand> <cleanCommand>${MAKE} -f Makefile clean</cleanCommand> - <executablePath></executablePath> + <executablePath>build/CMakeFiles/feature_tests.bin</executablePath> </makeTool> <preBuild> <preBuildCommandWorkingDir>build</preBuildCommandWorkingDir> @@ -82,19 +85,38 @@ <preBuildFirst>true</preBuildFirst> </preBuild> </makefileType> - <item path="ALSA-afb/Alsa-AddCtl.c" ex="false" tool="0" flavor2="0"> - <cTool flags="0"> + <item path="ALSA-afb/Alsa-AddCtl.c" ex="false" tool="0" flavor2="3"> + <cTool flags="1"> + <incDir> + <pElem>/usr/include/json-c</pElem> + <pElem>build/ALSA-afb</pElem> + </incDir> </cTool> </item> <item path="ALSA-afb/Alsa-ApiHat.c" ex="false" tool="0" flavor2="3"> - <cTool flags="0"> + <cTool flags="1"> + <incDir> + <pElem>build/ALSA-afb</pElem> + </incDir> </cTool> </item> <item path="ALSA-afb/Alsa-SetGet.c" ex="false" tool="0" flavor2="3"> - <cTool flags="0"> + <cTool flags="1"> + <incDir> + <pElem>/usr/include/json-c</pElem> + <pElem>build/ALSA-afb</pElem> + </incDir> </cTool> </item> <item path="ALSA-afb/Alsa-Ucm.c" ex="false" tool="0" flavor2="3"> + <cTool flags="1"> + <incDir> + <pElem>/usr/include/json-c</pElem> + <pElem>build/ALSA-afb</pElem> + </incDir> + </cTool> + </item> + <item path="Common/AudioCommonLib.c" ex="false" tool="0" flavor2="2"> <cTool flags="0"> </cTool> </item> @@ -102,11 +124,11 @@ ex="false" tool="0" flavor2="3"> - <cTool flags="1"> + <cTool flags="0"> </cTool> </item> <item path="HAL-afb/HDA-intel/IntelHdaHAL.c" ex="false" tool="0" flavor2="3"> - <cTool flags="1"> + <cTool flags="0"> </cTool> </item> <item path="HighLevel-afb/HighLevelApiConf.c" ex="false" tool="0" flavor2="3"> @@ -163,40 +185,51 @@ <item path="MostVolume/libmostvolume.cpp" ex="false" tool="1" flavor2="4"> </item> <item path="Shared-Interface/audio-interface.c" ex="false" tool="0" flavor2="3"> - <cTool flags="0"> + <cTool flags="1"> </cTool> </item> <folder path="0/ALSA-afb"> <cTool> <incDir> + <pElem>../../../opt/include/afb</pElem> + <pElem>ALSA-afb</pElem> + </incDir> + </cTool> + </folder> + <folder path="0/Common"> + <cTool> + <incDir> <pElem>/usr/include/alsa</pElem> <pElem>../../../opt/include</pElem> <pElem>/usr/include/json-c</pElem> - <pElem>Shared-Interface</pElem> - <pElem>build/ALSA-afb</pElem> + <pElem>build/Common</pElem> </incDir> <preprocessorList> <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem> <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem> <Elem>MAX_SND_CARD=16</Elem> - <Elem>alsa_lowlevel_EXPORTS</Elem> </preprocessorList> </cTool> </folder> <folder path="0/HAL-afb"> <cTool> <incDir> - <pElem>../../../opt/include/afb</pElem> + <pElem>/usr/include/alsa</pElem> + <pElem>../../../opt/include</pElem> + <pElem>/usr/include/json-c</pElem> + <pElem>HAL-afb/HAL-interface</pElem> + <pElem>Shared-Interface</pElem> </incDir> + <preprocessorList> + <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem> + <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem> + <Elem>MAX_SND_CARD=16</Elem> + </preprocessorList> </cTool> </folder> <folder path="0/HAL-afb/HAL-interface"> <cTool> <incDir> - <pElem>HAL-afb/HAL-interface</pElem> - <pElem>/usr/include/json-c</pElem> - <pElem>Shared-Interface</pElem> - <pElem>../../../opt/include</pElem> <pElem>build/HAL-afb/HAL-interface</pElem> </incDir> </cTool> @@ -204,12 +237,11 @@ <folder path="0/HAL-afb/HDA-intel"> <cTool> <incDir> - <pElem>HAL-afb/HDA-intel</pElem> - <pElem>Shared-Interface</pElem> - <pElem>HAL-afb/HAL-interface</pElem> - <pElem>../../../opt/include</pElem> <pElem>build/HAL-afb/HDA-intel</pElem> </incDir> + <preprocessorList> + <Elem>hal_intel_hda_EXPORTS</Elem> + </preprocessorList> </cTool> </folder> <folder path="0/HighLevel-afb"> @@ -223,17 +255,11 @@ <folder path="0/Shared-Interface"> <cTool> <incDir> - <pElem>/usr/include/alsa</pElem> - <pElem>../../../opt/include</pElem> - <pElem>/usr/include/json-c</pElem> + <pElem>../../../opt/include/afb</pElem> <pElem>Shared-Interface</pElem> + <pElem>/usr/include/json-c</pElem> <pElem>build/Shared-Interface</pElem> </incDir> - <preprocessorList> - <Elem>CONTROL_CDEV_RX="/dev/inic-usb-crx"</Elem> - <Elem>CONTROL_CDEV_TX="/dev/inic-usb-ctx"</Elem> - <Elem>MAX_SND_CARD=16</Elem> - </preprocessorList> </cTool> </folder> </conf> |