frameworks_bluetooth/framework/common/euv_pty.c

199 lines
4.9 KiB
C

/****************************************************************************
* Copyright (C) 2023 Xiaomi Corporation
*
* 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.
***************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "uv.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "euv_pty.h"
typedef struct _euv_pty {
uv_tty_t uv_tty;
} euv_pty_t;
typedef struct {
uv_write_t req;
uint8_t* buffer;
euv_write_cb write_cb;
} euv_wreq_t;
typedef struct {
euv_read_cb read_cb;
euv_alloc_cb alloc_cb;
uint16_t read_size;
} euv_read_t;
static void uv_close_callback(uv_handle_t* handle)
{
if (handle->data)
free(handle->data);
free(handle);
}
static void uv_alloc_callback(uv_handle_t* handle, size_t size, uv_buf_t* buf)
{
if (!handle->data)
return;
euv_read_t* reader = (euv_read_t*)handle->data;
if (reader->alloc_cb)
reader->alloc_cb((euv_pty_t*)handle, (uint8_t**)&buf->base, &buf->len);
else {
buf->base = malloc(reader->read_size);
buf->len = reader->read_size;
}
}
static void uv_read_callback(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
if (!stream->data)
return;
euv_read_t* reader = (euv_read_t*)stream->data;
/*if read stopped in read callback, will free reader struct*/
bool release = !reader->alloc_cb;
if (reader->read_cb)
reader->read_cb((euv_pty_t*)stream, (const uint8_t*)buf->base, nread);
if (release)
free(buf->base);
}
static void uv_write_callback(uv_write_t* req, int status)
{
euv_wreq_t* wreq = (euv_wreq_t*)req;
if (wreq->write_cb)
wreq->write_cb((euv_pty_t*)wreq->req.data, wreq->buffer, status);
free(wreq);
}
static int euv_pty_read_start_(euv_pty_t* handle, uint16_t read_size, euv_read_cb read_cb, euv_alloc_cb alloc_cb)
{
euv_read_t* reader;
int ret;
if (uv_is_active((uv_handle_t*)&handle->uv_tty))
return 0;
reader = malloc(sizeof(euv_read_t));
if (reader == NULL)
return -ENOMEM;
reader->read_cb = read_cb;
reader->alloc_cb = alloc_cb;
reader->read_size = read_size;
handle->uv_tty.data = reader;
ret = uv_read_start((uv_stream_t*)&handle->uv_tty, uv_alloc_callback, uv_read_callback);
if (ret != 0) {
handle->uv_tty.data = NULL;
free(reader);
}
return ret;
}
int euv_pty_read_start(euv_pty_t* handle, uint16_t read_size, euv_read_cb cb)
{
return euv_pty_read_start_(handle, read_size, cb, NULL);
}
int euv_pty_read_start2(euv_pty_t* handle, uint16_t read_size, euv_read_cb read_cb, euv_alloc_cb alloc_cb)
{
return euv_pty_read_start_(handle, read_size, read_cb, alloc_cb);
}
int euv_pty_read_stop(euv_pty_t* handle)
{
if (handle == NULL)
return -EINVAL;
free(handle->uv_tty.data);
handle->uv_tty.data = NULL;
if (uv_is_active((uv_handle_t*)&handle->uv_tty))
return uv_read_stop((uv_stream_t*)&handle->uv_tty);
return 0;
}
int euv_pty_write(euv_pty_t* handle, uint8_t* buffer, int length, euv_write_cb cb)
{
uv_buf_t buf;
euv_wreq_t* wreq;
int ret;
if (handle == NULL)
return -EINVAL;
wreq = (euv_wreq_t*)malloc(sizeof(euv_wreq_t));
if (!wreq)
return -ENOMEM;
wreq->req.data = (void*)handle;
wreq->buffer = buffer;
wreq->write_cb = cb;
buf = uv_buf_init((char*)buffer, length);
ret = uv_write(&wreq->req, (uv_stream_t*)&handle->uv_tty, &buf, 1, uv_write_callback);
if (ret != 0)
free(wreq);
return ret;
}
euv_pty_t* euv_pty_init(uv_loop_t* loop, int fd, uv_tty_mode_t mode)
{
euv_pty_t* handle;
int ret;
if (loop == NULL || fd < 0)
return NULL;
handle = (euv_pty_t*)malloc(sizeof(euv_pty_t));
if (!handle)
return NULL;
memset(handle, 0, sizeof(euv_pty_t));
ret = uv_tty_init(loop, &handle->uv_tty, fd, 1);
if (ret != 0) {
free(handle);
return NULL;
}
// set mode
ret = uv_tty_set_mode(&handle->uv_tty, mode);
return handle;
}
void euv_pty_close(euv_pty_t* hdl)
{
if (hdl == NULL)
return;
uv_close((uv_handle_t*)&hdl->uv_tty, uv_close_callback);
}