summaryrefslogtreecommitdiffstats
path: root/meta-agl-bsp/meta-raspberrypi/recipes-kernel/linux/linux-raspberrypi_%.bbappend
blob: ffbf791e8dc1557ee08784550a86032e7324640a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
FILESEXTRAPATHS_prepend := "${THISDIR}/${BPN}:"

require recipes-kernel/linux/linux-agl.inc
require recipes-kernel/linux/linux-agl-4.14.inc

# ENABLE DSI
# ported from https://github.com/k-quigley/linux
SRC_URI_append = " \
    file://dsi/0001-Add-devicetree-support-for-RaspberryPi-7-panel-over-.patch \
    file://dsi/0002-drm-vc4-Make-DSI-call-into-the-bridge-after-the-DSI-.patch \
    file://dsi/0003-drm-vc4-Set-up-the-DSI-host-at-pdev-probe-time-not-c.patch \
    file://dsi/0004-drm-panel-Backport-4.15-support-for-the-Raspberry-Pi.patch \
"

# NOTE: Kprobes need to be disabled until linux-raspberrypi gets updated
#       to newer than 4.14.104 to avoid lttng-modules failing to build.
SRC_URI_append = "\
    ${@oe.utils.conditional('USE_FAYTECH_MONITOR', '1', 'file://0002-faytech-fix-rpi.patch', '', d)} \
    file://disable_kprobes.cfg \
"

CMDLINE_DEBUG = ""
CMDLINE_append = " usbhid.mousepoll=0"

# Add options to allow CMA to operate
CMDLINE_append = ' ${@oe.utils.conditional("ENABLE_CMA", "1", "coherent_pool=6M smsc95xx.turbo_mode=N", "", d)}'

KERNEL_MODULE_AUTOLOAD += "snd-bcm2835"
KERNEL_MODULE_AUTOLOAD += "hid-multitouch"

RDEPENDS_${PN} += "kernel-module-snd-bcm2835"
PACKAGES += "kernel-module-snd-bcm2835"

# Enable support for usb video class for usb camera devices
KERNEL_CONFIG_FRAGMENTS_append = " ${WORKDIR}/uvc.cfg"

# Enable support for joystick devices
KERNEL_CONFIG_FRAGMENTS_append = " ${WORKDIR}/joystick.cfg"

# Enable support for Pi foundation touchscreen
SRC_URI_append = " file://raspberrypi-panel.cfg"
KERNEL_CONFIG_FRAGMENTS_append = " ${WORKDIR}/raspberrypi-panel.cfg"

# Enable bt hci uart
SRC_URI_append = " file://raspberrypi-hciuart.cfg"
KERNEL_CONFIG_FRAGMENTS_append = " ${WORKDIR}/raspberrypi-hciuart.cfg"

# ENABLE NETWORK (built-in)
SRC_URI_append = " file://raspberrypi_network.cfg"
KERNEL_CONFIG_FRAGMENTS_append = " ${WORKDIR}/raspberrypi_network.cfg"
ight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * Copyright (C) 2016 "IoT.bzh"
 * Author Jonathan Aillet <jonathan.aillet@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 <stdbool.h>

#include <wrap-json.h>

#include "../4a-hal-utilities/4a-hal-utilities-data.h"
#include "../4a-hal-utilities/4a-hal-utilities-verbs-loader.h"

#include "4a-hal-controllers-cb.h"

/*******************************************************************************
 *		HAL controllers sections parsing functions		       *
 ******************************************************************************/

int HalCtlsHalMixerConfig(afb_dynapi *apiHandle, CtlSectionT *section, json_object *MixerJ)
{
	unsigned int streamCount, idx;
	char *currentStreamName;

	CtlConfigT *ctrlConfig;
	struct SpecificHalData *currentHalData;

	json_object *streamsArray, *currentStream;

	struct HalUtlApiVerb *CtlHalDynApiStreamVerbs;

	if(! apiHandle || ! section)
		return -1;

	if(MixerJ) {
		ctrlConfig = (CtlConfigT *) afb_dynapi_get_userdata(apiHandle);
		if(! ctrlConfig)
			return -2;

		currentHalData = (struct SpecificHalData *) ctrlConfig->external;
		if(! currentHalData)
			return -3;

		if(json_object_is_type(MixerJ, json_type_object))
			currentHalData->ctlHalSpecificData->halMixerJ = MixerJ;
		else
			return -4;

		if(wrap_json_unpack(MixerJ, "{s:s}", "mixerapi", &currentHalData->ctlHalSpecificData->mixerApiName))
			return -5;

		if(! json_object_object_get_ex(MixerJ, "streams", &streamsArray))
			return -6;

		switch(json_object_get_type(streamsArray)) {
			case json_type_object:
				streamCount = 1;
				break;
			case json_type_array:
				streamCount = json_object_array_length(streamsArray);
				break;
			default:
				return -7;
		}

		currentHalData->ctlHalSpecificData->ctlHalStreamsData.count = streamCount;
		currentHalData->ctlHalSpecificData->ctlHalStreamsData.data =
			(struct CtlHalStreamData *) calloc(streamCount, sizeof (struct CtlHalStreamData *));

		CtlHalDynApiStreamVerbs = alloca((streamCount + 1) * sizeof(struct HalUtlApiVerb));
		memset(CtlHalDynApiStreamVerbs, '\0', (streamCount + 1) * sizeof(struct HalUtlApiVerb));
		CtlHalDynApiStreamVerbs[streamCount + 1].verb = NULL;

		for(idx = 0; idx < streamCount; idx++) {
			if(streamCount > 1)
				currentStream = json_object_array_get_idx(streamsArray, (int) idx);
			else
				currentStream = streamsArray;

			if(wrap_json_unpack(currentStream, "{s:s}", "uid", &currentStreamName))
				return -9-idx;

			currentHalData->ctlHalSpecificData->ctlHalStreamsData.data[idx].name = strdup(currentStreamName);
			currentHalData->ctlHalSpecificData->ctlHalStreamsData.data[idx].cardId = NULL;

			CtlHalDynApiStreamVerbs[idx].verb = currentStreamName;
			CtlHalDynApiStreamVerbs[idx].callback = HalCtlsActionOnStream;
			CtlHalDynApiStreamVerbs[idx].info = "Peform action on this stream";
		}

		if(HalUtlLoadVerbs(apiHandle, CtlHalDynApiStreamVerbs))
			return -8;
	}

	return 0;
}

// TODO JAI: create a new section parser to get 'halmap' and store them into hal structure

/*******************************************************************************
 *		HAL controllers verbs functions				       *
 ******************************************************************************/

// TODO JAI : to implement
void HalCtlsActionOnStream(afb_request *request)
{
	int verbToCallSize;

	char *apiToCall, *verbToCall;

	afb_dynapi *apiHandle;
	CtlConfigT *ctrlConfig;

	struct SpecificHalData *currentCtlHalData;

	json_object *requestJson, *returnJ, *toReturnJ;

	apiHandle = (afb_dynapi *) afb_request_get_dynapi(request);
	if(! apiHandle) {
		afb_request_fail(request, "api_handle", "Can't get current hal controller api handle");
		return;
	}

	ctrlConfig = (CtlConfigT *) afb_dynapi_get_userdata(apiHandle);
	if(! ctrlConfig) {
		afb_request_fail(request, "hal_controller_config", "Can't get current hal controller config");
		return;
	}

	currentCtlHalData = ctrlConfig->external;
	if(! currentCtlHalData) {
		afb_request_fail(request, "hal_controller_data", "Can't get current hal controller data");
		return;
	}

	requestJson = afb_request_json(request);
	if(! requestJson) {
		afb_request_fail(request, "request_json", "Can't get request json");
		return;
	}

	apiToCall = currentCtlHalData->ctlHalSpecificData->mixerApiName;
	if(! apiToCall) {
		afb_request_fail(request, "mixer_api", "Can't get mixer api");
		return;
	}

	// TODO JAI: check status of hal before doing anything

	// TODO JAI : remove action prefix, streams should be created as verb by mixer
	verbToCallSize = (int) strlen(API_STREAM_PREFIX) + (int) strlen(request->verb) + 2;
	verbToCall = (char *) alloca(verbToCallSize * sizeof(char));
	verbToCall[0] = '\0';
	verbToCall[verbToCallSize - 1] = '\0';

	strcat(verbToCall, API_STREAM_PREFIX);
	strcat(verbToCall, "/");
	strcat(verbToCall, request->verb);

	if(afb_dynapi_call_sync(apiHandle, apiToCall, verbToCall, json_object_get(requestJson), &returnJ)) {
		afb_request_fail_f(request, "action", "Action %s seemingly not correctly transfered to %s",
							verbToCall,
							apiToCall);

	}
	else if(json_object_object_get_ex(returnJ, "response", &toReturnJ)){
		afb_request_success_f(request, toReturnJ, "Action %s correctly transfered to %s, and successfull",
								verbToCall,
								apiToCall);
	}
	else {
		afb_request_fail_f(request, "invalid_response", "Action %s correctly transfered to %s, but response is not valid",
							verbToCall,
							apiToCall);
	}
}

// TODO JAI : to implement
void HalCtlsListVerbs(afb_request *request)
{
	AFB_REQUEST_WARNING(request, "JAI :%s not implemented yet", __func__);

	afb_request_success(request, json_object_new_boolean(false), NULL);
}

void HalCtlsInitMixer(afb_request *request)
{
	char *apiToCall;

	afb_dynapi *apiHandle;
	CtlConfigT *ctrlConfig;

	struct SpecificHalData *currentCtlHalData;

	json_object *returnJ, *toReturnJ;

	apiHandle = (afb_dynapi *) afb_request_get_dynapi(request);
	if(! apiHandle) {
		afb_request_fail(request, "api_handle", "Can't get hal manager api handle");
		return;
	}

	ctrlConfig = (CtlConfigT *) afb_dynapi_get_userdata(apiHandle);
	if(! ctrlConfig) {
		afb_request_fail(request, "hal_controller_config", "Can't get current hal controller config");
		return;
	}

	currentCtlHalData = ctrlConfig->external;
	if(! currentCtlHalData) {
		afb_request_fail(request, "hal_controller_data", "Can't get current hal controller data");
		return;
	}

	apiToCall = currentCtlHalData->ctlHalSpecificData->mixerApiName;
	if(! apiToCall) {
		afb_request_fail(request, "mixer_api", "Can't get mixer api");
		return;
	}

	// TODO JAI: test hal status (card is detected)

	if(afb_dynapi_call_sync(apiHandle, apiToCall, "mixer_new", json_object_get(currentCtlHalData->ctlHalSpecificData->halMixerJ), &returnJ)) {
		afb_request_fail_f(request,
				   "mixer_new_call",
				   "Seems that mix_new call to api %s didn't end well",
				   apiToCall);
	}
	else if(json_object_object_get_ex(returnJ, "response", &toReturnJ)) {
		// TODO JAI : get streams cardId from mixer response

		afb_request_success_f(request,
				      toReturnJ,
				      "Seems that mix_new call to api %s succeed",
				      apiToCall);
	}
	else {
		afb_request_fail_f(request,
				   "invalid_response",
				   "Seems that mix_new call to api %s succeed, but response is not valid",
				   apiToCall);
	}
}