blob: 3593e997ae3b6039e44e9cd0006256c24e6dfe04 [file] [log] [blame]
/*
* Copyright (C) 2022 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "main.h"
#include "display.h"
#include "nanohub_exports.h"
#include <asm-generic/errno.h>
#define NANOHUB_DISPLAY_COMMAND_VERSION 0x01
static DEFINE_MUTEX(nanohub_display_mutex);
static DECLARE_COMPLETION(message_callback);
static int display_state;
ssize_t nanohub_pin_display_select_get(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct nanohub_data *data = dev_get_drvdata(dev);
const struct nanohub_platform_data *pdata = data->pdata;
return scnprintf(buf, PAGE_SIZE, "%d\n",
gpio_get_value(pdata->display_select_gpio));
}
ssize_t nanohub_pin_display_select_set(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct nanohub_data *data = dev_get_drvdata(dev);
const struct nanohub_platform_data *pdata = data->pdata;
if (count >= 1 && buf[0] == '0') {
gpio_set_value(pdata->display_select_gpio, 0);
} else if (count >= 1 && buf[0] == '1') {
gpio_set_value(pdata->display_select_gpio, 1);
}
return count;
}
ssize_t nanohub_get_display_state(struct device *dev, struct device_attribute *attr, char *buf)
{
int display_state = nanohub_query_display_state();
return scnprintf(buf, PAGE_SIZE, "%d", display_state);
}
#define NANOHUB_DISPLAY_COMMAND_TYPE_GET_STATE 0x06
#define NANOHUB_DISPLAY_GET_STATE_TIMEOUT_MS 100
static void on_message_received(const char *buffer, size_t length)
{
if (length == 3 && buffer[0] == NANOHUB_DISPLAY_COMMAND_VERSION &&
buffer[1] == NANOHUB_DISPLAY_COMMAND_TYPE_GET_STATE) {
display_state = buffer[2];
}
complete(&message_callback);
}
int nanohub_query_display_state_internal(struct nanohub_data *data)
{
const char message[] = { NANOHUB_DISPLAY_COMMAND_VERSION,
NANOHUB_DISPLAY_COMMAND_TYPE_GET_STATE };
long ret;
const struct nanohub_platform_data *pdata;
if (unlikely(data == NULL))
return -EINVAL;
pdata = data->pdata;
if (gpio_get_value(pdata->display_select_gpio) == 1)
return MCU_DISPLAY_NONE;
mutex_lock(&nanohub_display_mutex);
nanohub_register_listener(NANOHUB_DISPLAY_KERNEL_CHANNEL_ID, on_message_received);
reinit_completion(&message_callback);
display_state = -ENODATA;
nanohub_send_message(NANOHUB_DISPLAY_CHANNEL_ID, message, sizeof(message));
ret = wait_for_completion_interruptible_timeout(
&message_callback, msecs_to_jiffies(NANOHUB_DISPLAY_GET_STATE_TIMEOUT_MS));
nanohub_unregister_listener(NANOHUB_DISPLAY_KERNEL_CHANNEL_ID);
mutex_unlock(&nanohub_display_mutex);
if (ret < 0)
return ret;
if (ret == 0)
return -ETIMEDOUT;
return display_state;
}