提交 ddcd4306 编写于 作者: W wenjun

add OpenHarmony 1.0 baseline

上级 0d3a2381
*.swp
test
huawei_proprietary
# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
source "../../vendor/hisi/hi35xx/platform/Kconfig"
source "../../vendor/huawei/hdf/wifi/driver/Kconfig"
source "../../vendor/huawei/hdf/input/driver/Kconfig"
source "../../vendor/huawei/hdf/display/driver/Kconfig"
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
\ No newline at end of file
config DRIVERS_HDF_LCD
bool "Enable HDF Lcd driver"
default n
depends on DRIVERS_HDF
help
Answer Y to enable HDF Lcd driver.
config DRIVERS_HDF_LCD_ICN9700
bool "Enable HDF Lcd Icn9700 driver"
default n
depends on DRIVERS_HDF_LCD
help
Answer Y to enable HDF Lcd Icn9700 driver.
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
import("//build/lite/config/component/lite_component.gni")
copy("display_layer") {
sources = [
"../../libs/${board_name}/libdisplay_layer.so",
]
outputs = [ "$root_out_dir/libdisplay_layer.so" ]
}
copy("display_gfx") {
sources = [
"../../libs/${board_name}/libdisplay_gfx.so",
]
outputs = [ "$root_out_dir/libdisplay_gfx.so" ]
}
copy("display_gralloc") {
sources = [
"../../libs/${board_name}/libdisplay_gralloc.so",
]
outputs = [ "$root_out_dir/libdisplay_gralloc.so" ]
}
group("hdi_display") {
deps = [
":display_layer",
":display_gfx",
":display_gralloc",
]
}
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
LITEOS_BASELIB += -lhdf_config
LIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/vendor/hisi/hi35xx/$(LITEOS_PLATFORM)/config
VENDOR_HDF_DRIVERS_PLATFORM_ROOT := $(LITEOSTOPDIR)/../../vendor/hisi/hi35xx/platform
VENDOR_HDF_DRIVERS_ROOT := $(LITEOSTOPDIR)/../../vendor/huawei/hdf
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_I2C), y)
LITEOS_BASELIB += -lhdf_i2c
endif
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_SPI), y)
LITEOS_BASELIB += -lhdf_spi
endif
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO), y)
LITEOS_BASELIB += -lhdf_gpio
endif
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_WATCHDOG), y)
LITEOS_BASELIB += -lhdf_watchdog
endif
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_SDIO), y)
LITEOS_BASELIB += -lhdf_sdio
endif
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_RTC), y)
LITEOS_BASELIB += -lhdf_rtc
endif
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_UART), y)
LITEOS_BASELIB += -lhdf_uart
endif
ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_HISI_SDK), y)
LITEOS_BASELIB += -lhdf_hisi_sdk
endif
ifeq ($(LOSCFG_DRIVERS_HDF_WIFI), y)
LITEOS_BASELIB += -lhdf_vendor_wifi
ifeq ($(LOSCFG_DRIVERS_HI3881), y)
LITEOS_BASELIB += -lhi3881
endif
endif
ifeq ($(LOSCFG_DRIVERS_HDF_INPUT), y)
LITEOS_BASELIB += -lhdf_input_driver
endif
ifeq ($(LOSCFG_DRIVERS_HDF_LCD), y)
LITEOS_BASELIB += -lhdf_lcd_driver
endif
# lib path
LITEOS_LD_PATH += -L$(VENDOR_HDF_DRIVERS_PLATFORM_ROOT)/libs/$(LITEOS_PLATFORM)
LITEOS_LD_PATH += -L$(VENDOR_HDF_DRIVERS_ROOT)/libs/$(LITEOS_PLATFORM)
config DRIVERS_HDF_INPUT
bool "Enable HDF input driver"
default n
depends on DRIVERS_HDF
help
Answer Y to enable HDF input driver.
config DRIVERS_HDF_TP_5P5_GT911
bool "Enable HDF tp 5P5 GT911 driver"
default n
depends on DRIVERS_HDF_INPUT
help
Answer Y to enable HDF TP 5P5 GT911 driver.
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
import("//build/lite/config/component/lite_component.gni")
copy("hdi_input") {
sources = [
"../../libs/${board_name}/libhdi_input.so",
]
outputs = [ "$root_out_dir/libhdi_input.so" ]
}
// Copyright 2020 Huawei Device Co., Ltd.
//
// 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.
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_uart :: device {
device5 :: deviceNode {
policy = 2;
priority = 10;
permission = 0644;
moduleName = "UART_SAMPLE";
serviceName = "HDF_PLATFORM_UART_5";
deviceMatchAttr = "sample_uart_5";
}
}
}
}
}
// Copyright 2020 Huawei Device Co., Ltd.
//
// 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.
root {
platform {
uart_sample {
num = 5;
base = 0x120a0000; // UART base register address
irqNum = 38;
baudrate = 115200;
uartClk = 24000000; // 24 M
wlen = 0x60; // 8 bit width
parity = 0;
stopBit = 0;
match_attr = "sample_uart_5";
}
}
}
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
import("//build/lite/config/component/lite_component.gni")
lite_component("hello_uart_sample") {
features = [
"dev:hello_uart",
"dispatch:hello_uart_dispatch",
]
}
\ No newline at end of file
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
config DRIVERS_HDF_PLATFORM_UART_SAMPLE
bool "Enable HDF platform uart sample driver"
default n
depends on DRIVERS_HDF_PLATFORM
help
Answer Y to enable HDF platform uart sample driver.
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
include $(LITEOSTOPDIR)/config.mk
include $(LITEOSTOPDIR)/../../drivers/hdf/lite/lite.mk
MODULE_NAME := hdf_uart_sample
LOCAL_CFLAGS += $(HDF_INCLUDE)
LOCAL_SRCS += src/uart_sample.c \
src/uart_pl011_sample.c \
src/buf_fifo.c \
src/uart_dev_sample.c \
src/uart_dispatch_sample.c \
LOCAL_INCLUDE := ./include
LOCAL_CFLAGS += -fstack-protector-strong
include $(HDF_DRIVER)
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
HDF_FRAMEWORKS = "//drivers/hdf/frameworks"
executable("hello_uart") {
sources = [
"hello_uart_dev.c"
]
include_dirs = [
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/master/include",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"//third_party/bounds_checking_function/include",
]
deps = [
"//drivers/hdf/lite/manager:hdf_core",
"//drivers/hdf/lite/adapter/osal/posix:hdf_posix_osal",
]
public_deps = [
"//third_party/bounds_checking_function:libsec_shared",
]
defines = [
"__USER__",
]
cflags = [
"-Wall",
"-Wextra",
]
}
\ No newline at end of file
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "hdf_log.h"
#define HDF_LOG_TAG "hello_uart"
#define INFO_SIZE 16
int main(void)
{
int ret;
int fd;
const char info[INFO_SIZE] = {" HELLO UART! "};
fd = open("/dev/uartdev-5", O_RDWR);
if (fd < 0) {
HDF_LOGE("hello_uart uartdev-5 open failed %d", fd);
return -1;
}
ret = write(fd, info, INFO_SIZE);
if (ret != 0) {
HDF_LOGE("hello_uart write uartdev-5 ret is %d", ret);
}
ret = close(fd);
if (ret != 0) {
HDF_LOGE("hello_uart uartdev-5 close failed %d", fd);
return -1;
}
return ret;
}
\ No newline at end of file
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
HDF_FRAMEWORKS = "//drivers/hdf/frameworks"
executable("hello_uart_dispatch") {
sources = [
"hello_uart_dispatch.c",
"uart_if.c",
]
include_dirs = [
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/master/include",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"//drivers/hdf/lite/include/host",
"//third_party/bounds_checking_function/include",
]
deps = [
"//drivers/hdf/lite/manager:hdf_core",
"//drivers/hdf/lite/adapter/osal/posix:hdf_posix_osal",
]
public_deps = [
"//third_party/bounds_checking_function:libsec_shared",
]
defines = [
"__USER__",
]
cflags = [
"-Wall",
"-Wextra",
]
}
\ No newline at end of file
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include <string.h>
#include "hdf_log.h"
#include "osal_mem.h"
#include "uart_if.h"
#define HDF_LOG_TAG "hello_uart_dispatch"
#define UART_PORT 5
int main()
{
const char *info = " HELLO UART! ";
struct DevHandle *handle = UartOpen(UART_PORT);
if (handle == NULL) {
HDF_LOGE("Failed to open uart %d", UART_PORT);
return HDF_FAILURE;
}
int ret = UartWrite(handle, (uint8_t *)info, strlen(info));
if (ret != HDF_SUCCESS) {
HDF_LOGE("Failed to send data to uart");
}
UartClose(handle);
return ret;
}
\ No newline at end of file
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include "uart_if.h"
#include "securec.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "hdf_io_service_if.h"
struct DevHandle *UartOpen(uint32_t port)
{
int32_t ret;
struct DevHandle *handle = NULL;
char *serviceName = NULL;
handle = (struct DevHandle *)OsalMemCalloc(sizeof(struct DevHandle));
if (handle == NULL) {
HDF_LOGE("Failed to OsalMemCalloc handle");
return NULL;
}
serviceName = (char *)OsalMemCalloc(sizeof(char) * (MAX_DEV_NAME_SIZE + 1));
if (serviceName == NULL) {
HDF_LOGE("Failed to OsalMemCalloc serviceName");
OsalMemFree(handle);
return NULL;
}
ret = snprintf_s(serviceName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, UART_DEV_SERVICE_NAME_PREFIX, port);
if (ret < 0) {
HDF_LOGE("Failed to snprintf_s");
OsalMemFree(handle);
OsalMemFree(serviceName);
return NULL;
}
struct HdfIoService *service = HdfIoServiceBind(serviceName, 0);
if (service == NULL) {
HDF_LOGE("Failed to get service %s", serviceName);
OsalMemFree(handle);
OsalMemFree(serviceName);
return NULL;
}
OsalMemFree(serviceName);
handle->object = service;
return handle;
}
int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size)
{
int ret;
struct HdfIoService *service = NULL;
if (handle == NULL || handle->object == NULL) {
HDF_LOGE("handle or handle->object is NULL");
return HDF_FAILURE;
}
struct HdfSBuf *sBuf = HdfSBufObtainDefaultSize();
if (sBuf == NULL) {
HDF_LOGE("Failed to obtain sBuf");
return HDF_FAILURE;
}
if (!HdfSbufWriteBuffer(sBuf, data, size)) {
HDF_LOGE("Failed to write sbuf");
HdfSBufRecycle(sBuf);
return HDF_FAILURE;
}
service = (struct HdfIoService *)handle->object;
ret = service->dispatcher->Dispatch(&service->object, UART_WRITE, sBuf, NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("Failed to send service call");
}
HdfSBufRecycle(sBuf);
return ret;
}
void UartClose(struct DevHandle *handle)
{
struct HdfIoService *service = NULL;
if (handle == NULL || handle->object == NULL) {
HDF_LOGE("handle or handle->object is NULL");
return;
}
service = (struct HdfIoService *)handle->object;
HdfIoServiceRecycle(service);
OsalMemFree(handle);
}
\ No newline at end of file
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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 UART_IF_H
#define UART_IF_H
#include <stdint.h>
#define UART_DEV_SERVICE_NAME_PREFIX "HDF_PLATFORM_UART_%d"
#define MAX_DEV_NAME_SIZE 32
enum {
UART_WRITE = 1
};
struct DevHandle {
void *object;
};
struct DevHandle *UartOpen(uint32_t port);
int32_t UartWrite(struct DevHandle *handle, uint8_t *data, uint32_t size);
void UartClose(struct DevHandle *handle);
#endif // UART_IF_H
\ No newline at end of file
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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 BUF_FIFO_H
#define BUF_FIFO_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
struct BufferFifo {
volatile uint32_t readPosition;
volatile uint32_t writePosition;
uint16_t bufSizeMask;
uint8_t *buffer;
};
static inline uint16_t BufferFifoGetDataSize(struct BufferFifo *fifo)
{
return (fifo->writePosition - fifo->readPosition);
}
static inline bool IsPowerOfTwo(int num)
{
return (num > 0) && (num & (num - 1)) == 0;
}
bool BufferFifoInit(struct BufferFifo *fifo, uint8_t *buf, uint16_t bufSize);
#endif // BUF_FIFO_H
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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 UART_DEV_SAMPLE_H
#define UART_DEV_SAMPLE_H
#include "sys/ioctl.h"
#include "uart_core.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
#define UART_IOC_MAGIC 'u'
/* baudrate config */
#define UART_CFG_BAUDRATE _IO(UART_IOC_MAGIC, 1)
void UartSampleAddDev(struct UartHost *host);
void UartSampleRemoveDev(struct UartHost *host);
#ifdef __cplusplus
#if __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif /* UART_DEV_SAMPLE_H */
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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 UART_DISPATCH_SAMPLE_H
#define UART_DISPATCH_SAMPLE_H
#include "uart_pl011_sample.h"
enum {
UART_WRITE = 1
};
void SampleDispatchConstruct(struct UartDevice *device);
#endif // UART_DISPATCH_SAMPLE_H
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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 UART_PL011_SAMPLE_H
#define UART_PL011_SAMPLE_H
#include <stdint.h>
#include <stdbool.h>
#include "hdf_device_desc.h"
#include "buf_fifo.h"
#ifdef __cplusplus
extern "C" {
#endif
struct UartRegisterMap {
volatile uint32_t dr; /* Offset: 0x000 TYPE: (RW) Data register */
union {
volatile uint32_t rsr; /* Offset: 0x004 TYPE: (RO) Receive status register */
volatile uint32_t ecr; /* Offset: 0x004 TYPE: (WO) Error clear register */
};
volatile uint32_t reserved0[4]; /* Offset: 0x008-0x014 Reserved */
volatile uint32_t fr; /* Offset: 0x018 TYPE: (RO) Flag register */
volatile uint32_t reserved1; /* Offset: 0x01C Reserved */
volatile uint32_t ilpr; /* Offset: 0x020 TYPE: (RW) IrDA low-power counter register */
volatile uint32_t ibrd; /* Offset: 0x024 TYPE: (RW) Integer baud rate register */
volatile uint32_t fbrd; /* Offset: 0x028 TYPE: (RW) Fractional baud rate register */
volatile uint32_t lcr; /* Offset: 0x02C TYPE: (RW) Line control register */
volatile uint32_t cr; /* Offset: 0x030 TYPE: (RW) Control register */
volatile uint32_t ifls; /* Offset: 0x034 TYPE: (RW) Interrupt FIFO level select register */
volatile uint32_t imsc; /* Offset: 0x038 TYPE: (RW) Interrupt mask set/clear register */
volatile uint32_t ris; /* Offset: 0x03C TYPE: (RO) Raw interrupt status register */
volatile uint32_t mis; /* Offset: 0x040 TYPE: (RO) Masked interrupt status register */
volatile uint32_t icr; /* Offset: 0x044 TYPE: (WO) Interrupt clear register */
volatile uint32_t dmacr; /* Offset: 0x048 TYPE: (RW) DMA control register */
};
struct UartResource {
uint32_t num; /* UART port num */
uint32_t base; /* UART PL011 base address */
uint32_t irqNum; /* UART PL011 IRQ num */
uint32_t baudrate; /* Default baudrate */
uint32_t wlen; /* Default word length */
uint32_t parity; /* Default parity */
uint32_t stopBit; /* Default stop bits */
uint32_t uartClk; /* UART clock */
unsigned long physBase;
};
enum UartDeviceState {
UART_DEVICE_UNINITIALIZED = 0x0u,
UART_DEVICE_INITIALIZED = 0x1u,
};
struct UartDevice {
struct IDeviceIoService ioService;
struct UartResource resource;
enum UartDeviceState state; /* UART State */
uint32_t uartClk; /* UART clock */
uint32_t baudrate; /* Baudrate */
struct BufferFifo rxFifo;
};
/* Receive Status Register/Error Clear Register data */
#define UART_PL011_RSR_FRAMING_ERROR_MASK (1 << 0x0u) /* Framing error bit mask */
#define UART_PL011_RSR_PARITY_ERROR_MASK (1 << 0x1u) /* Parity error bit mask */
#define UART_PL011_RSR_BREAK_ERROR_MASK (1 << 0x2u) /* Break error bit mask */
#define UART_PL011_RSR_OVERRUN_ERROR_MASK (1 << 0x3u) /* Overrun error bit mask */
/* Receive Status Register Error Mask */
#define UART_PL011_RSR_RX_ERROR_MASK ( \
UART_PL011_RSR_FRAMING_ERROR_MASK \
| UART_PL011_RSR_PARITY_ERROR_MASK \
| UART_PL011_RSR_BREAK_ERROR_MASK \
| UART_PL011_RSR_OVERRUN_ERROR_MASK)
#define UART_PL011_FR_CTS_MASK (1 << 0x0u) /* Clear to send bit mask */
#define UART_PL011_FR_DSR_MASK (1 << 0x1u) /* Data set ready bit mask */
#define UART_PL011_FR_DCD_MASK (1 << 0x2u) /* Data carrier detect bit mask */
#define UART_PL011_FR_BUSY_MASK (1 << 0x3u) /* UART busy bit mask */
#define UART_PL011_FR_RX_FIFO_EMPTY_MASK (1 << 0x4u) /* Receive FIFO empty bit mask */
#define UART_PL011_FR_TX_FIFO_FULL_MASK (1 << 0x5u) /* Transmit FIFO full bit mask */
#define UART_PL011_FR_RX_FIFO_FULL_MASK (1 << 0x6u) /* Receive FIFO full bit mask */
#define UART_PL011_FR_TX_FIFO_EMPTY_MASK (1 << 0x7u) /* Transmit FIFO empty. bit mask */
#define UART_PL011_FR_RI_MASK (1 << 0x8u) /* Ring indicator bit mask */
/* PL011 Line Control Register Data bits */
#define UART_PL011_LCR_H_BRK_MASK (1 << 0x0u) /* Send Break bit mask */
#define UART_PL011_LCR_H_PEN_MASK (1 << 0x1u) /* Parity enable bit mask */
#define UART_PL011_LCR_H_EPS_MASK (1 << 0x2u) /* Even parity select bit mask . */
#define UART_PL011_LCR_H_FEN_MASK (1 << 0x4u) /* Enable FIFOs bit mask */
#define UART_PL011_LCR_H_SPS_MASK (1 << 0x7u) /* Stick parity select bit mask */
#define UART_PL011_LCR_H_WLEN_BIT_OFFSET 0x5u /* Word length bit offset */
#define UART_PL011_LCR_H_WLEN_MASK ( \
0x3u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_5BITS (0x0u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_6BITS (0x1u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_7BITS (0x2u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_WLEN_8BITS (0x3u << UART_PL011_LCR_H_WLEN_BIT_OFFSET)
#define UART_PL011_NONE_PARITY_CHECKED 0
#define UART_PL011_LCR_H_STP2_BIT_OFFSET 0x3u /* Two stop bits select */
#define UART_PL011_STOPBIT_1 (0x0u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
#define UART_PL011_STOPBIT_2 (0x1u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
#define UART_PL011_LCR_H_PARITY_MASK ( \
UART_PL011_LCR_H_PEN_MASK \
| UART_PL011_LCR_H_EPS_MASK \
| UART_PL011_LCR_H_SPS_MASK)
#define UART_PL011_LCR_H_STOPBIT_MASK \
(0x1u << UART_PL011_LCR_H_STP2_BIT_OFFSET)
#define UART_PL011_DATA_FORMAT_MASK ( \
UART_PL011_LCR_H_PARITY_MASK \
| UART_PL011_LCR_H_STOPBIT_MASK \
| UART_PL011_LCR_H_WLEN_MASK)
/* Control Register */
#define UART_PL011_CR_UARTEN_MASK (0x1u << 0x0u) /* Uart enable bit mask */
#define UART_PL011_CR_SIREN_MASK (0x1u << 0x1u) /* Sir enable bit mask */
#define UART_PL011_CR_SIRLP_MASK (0x1u << 0x2u) /* SIR low-power IrDA mode bit mask */
#define UART_PL011_CR_LBE_MASK (0x1u << 0x7u) /* Loopback enable bit mask */
#define UART_PL011_CR_TXE_MASK (0x1u << 0x8u) /* Transmit enable bit mask */
#define UART_PL011_CR_RXE_MASK (0x1u << 0x9u) /* Receive enable bit mask */
#define UART_PL011_CR_DTR_MASK (0x1u << 0xAu) /* Data transmit ready.bit mask */
#define UART_PL011_CR_RTS_MASK (0x1u << 0xBu) /* Request to send bit mask */
#define UART_PL011_CR_OUT1_MASK (0x1u << 0xCu) /* Out1 bit field mask */
#define UART_PL011_CR_OUT2_MASK (0x1u << 0xDu) /* Out2 bit field mask */
#define UART_PL011_CR_RTSE_MASK (0x1u << 0xEu) /* RTS hardware flow control enable bit mask */
#define UART_PL011_CR_CTSE_MASK (0x1u << 0xFu) /* CTS hardware flow control enable bit mask */
/* Interrupt FIFO Level Select Register Transmit bit offset */
#define UART_PL011_IFLS_TX_BIT_OFFSET 0x0u
/* Interrupt FIFO Level Select Register Receive bit offset */
#define UART_PL011_IFLS_RX_BIT_OFFSET 0x3u
#define UART_PL011_RX_FIFO_LVL_1_8 (0x0u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_1_4 (0x1u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_1_2 (0x2u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_3_4 (0x3u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_RX_FIFO_LVL_7_8 (0x4u << UART_PL011_IFLS_RX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_1_8 (0x0u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_1_4 (0x1u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_1_2 (0x2u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_3_4 (0x3u << UART_PL011_IFLS_TX_BIT_OFFSET)
#define UART_PL011_TX_FIFO_LVL_7_8 (0x4u << UART_PL011_IFLS_TX_BIT_OFFSET)
/* Default register values of UART PL011 */
#define UART_PL011_DEFAULT_DATA_REG_VALUE (0x0u)
#define UART_PL011_DEFAULT_ECR_VALUE (0xFFu)
#define UART_PL011_DEFAULT_ILPR_VALUE (0x0u)
#define UART_PL011_DEFAULT_IBRD_REG_VALUE (0x0u)
#define UART_PL011_DEFAULT_FBRD_REG_VALUE (0x0u)
/* Clear UARTLCR */
#define UART_PL011_DEFAULT_LCR_H_VALUE (0x0u)
#define UART_PL011_DEFAULT_CTRL_REG_VALUE (0x0300u)
#define UART_PL011_DEFAULT_IFLS_REG_VALUE ( \
UART_PL011_RX_FIFO_LVL_1_2 \
| UART_PL011_TX_FIFO_LVL_7_8)
/* Clear interrupt mask */
#define UART_PL011_DEFAULT_IMSC_REG_VALUE (0x0u)
/* Clear interrupt */
#define UART_PL011_DEFAULT_ICR_VALUE (0x7FFu)
#define UART_PL011_DEFAULT_DMACR_VALUE (0x0u)
#define FREQ_IRLPBAUD16_MIN (1420000u) /* 1.42 MHz */
#define FREQ_IRLPBAUD16_MAX (2120000u) /* 2.12 MHz */
#define SAMPLING_FACTOR (16u)
#define UART_PL011_FBRD_WIDTH (6u)
/**
* \brief ARM UART PL011 error enumeration types
*/
typedef enum UartPl011Error {
UART_PL011_ERR_NONE = (0x0u),
UART_PL011_ERR_RX_FRAME = UART_PL011_RSR_FRAMING_ERROR_MASK,
UART_PL011_ERR_RX_PARITY = UART_PL011_RSR_PARITY_ERROR_MASK,
UART_PL011_ERR_RX_BREAK = UART_PL011_RSR_BREAK_ERROR_MASK,
UART_PL011_ERR_RX_OVERFLOW = UART_PL011_RSR_OVERRUN_ERROR_MASK,
UART_PL011_ERR_INVALID_ARG = (UART_PL011_RSR_RX_ERROR_MASK + 1),
UART_PL011_ERR_NOT_READY,
UART_PL011_ERR_INVALID_BAUD,
UART_PL011_ERR_NOT_INIT,
} UartPl011Error;
static inline void UartPl011Enable(struct UartRegisterMap *regMap)
{
regMap->cr |= UART_PL011_CR_UARTEN_MASK;
}
static inline void UartPl011Disable(struct UartRegisterMap *regMap)
{
regMap->cr &= ~UART_PL011_CR_UARTEN_MASK;
}
static inline bool UartPl011IsEnabled(struct UartRegisterMap *regMap)
{
return (bool)(regMap->cr & UART_PL011_CR_UARTEN_MASK);
}
static inline bool UartPl011IsBusy(struct UartRegisterMap *regMap)
{
return (bool)(regMap->fr & UART_PL011_FR_BUSY_MASK);
}
void UartPl011SetLcrBits(struct UartRegisterMap *regMap, uint32_t bits);
static inline void UartPl011Write(struct UartRegisterMap *regMap, uint8_t byte)
{
while (UartPl011IsBusy(regMap));
regMap->dr = byte;
}
UartPl011Error UartPl011SetBaudrate(struct UartRegisterMap *regMap, uint32_t clk, uint32_t baudrate);
void UartPl011SetDataFormat(struct UartRegisterMap *regMap, uint32_t wordLen, uint32_t parity, uint32_t stopBits);
void UartPl011ResetRegisters(struct UartRegisterMap *regMap);
static inline void UartPl011EnableFifo(struct UartRegisterMap *regMap)
{
UartPl011SetLcrBits(regMap, UART_PL011_LCR_H_FEN_MASK);
}
#ifdef __cplusplus
}
#endif
#endif /* UART_PL011_SAMPLE_H */
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include "buf_fifo.h"
bool BufferFifoInit(struct BufferFifo *fifo, uint8_t *fifoBuffer, uint16_t fifoSize)
{
if (fifoBuffer == NULL) {
return false;
}
if (!IsPowerOfTwo(fifoSize)) {
return false;
}
fifo->buffer = fifoBuffer;
fifo->bufSizeMask = fifoSize - 1;
fifo->readPosition = 0;
fifo->writePosition = 0;
return true;
}
\ No newline at end of file
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include "uart_dev_sample.h"
#include "fs/fs.h"
#include "securec.h"
#include "user_copy.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "uart_pl011_sample.h"
#define HDF_LOG_TAG hdf_uart_dev
#define HDF_UART_FS_MODE 0660
static int32_t UartSampleDevOpen(FAR struct file *filep)
{
struct inode *inode = NULL;
struct UartHost *host = NULL;
if (filep == NULL || filep->f_inode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
inode = (struct inode *)filep->f_inode;
host = (struct UartHost *)inode->i_private;
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
HDF_LOGI("%s: open uart%d success", __func__, host->num);
return HDF_SUCCESS;
}
static int32_t UartSampleRelease(FAR struct file *filep)
{
struct inode *inode = NULL;
struct UartHost *host = NULL;
if (filep == NULL || filep->f_inode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
inode = (struct inode *)filep->f_inode;
host = (struct UartHost *)inode->i_private;
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
HDF_LOGI("%s: close uart%d success", __func__, host->num);
return HDF_SUCCESS;
}
static ssize_t UartSampleRead(FAR struct file *filep, FAR char *buf, size_t count)
{
int32_t ret;
uint8_t *tmpBuf = NULL;
struct inode *inode = NULL;
struct UartHost *host = NULL;
if (filep == NULL || filep->f_inode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
inode = (struct inode *)filep->f_inode;
host = (struct UartHost *)inode->i_private;
if (LOS_IsUserAddressRange((vaddr_t)buf, count)) {
tmpBuf = (uint8_t *)OsalMemCalloc(count);
if (tmpBuf == NULL) {
HDF_LOGE("%s: OsalMemCalloc error", __func__);
return HDF_ERR_MALLOC_FAIL;
}
ret = UartHostRead(host, tmpBuf, count);
if (ret == HDF_SUCCESS) {
ret = LOS_ArchCopyToUser(buf, tmpBuf, count);
}
OsalMemFree(tmpBuf);
return ret;
} else {
return UartHostRead(host, (uint8_t *)buf, count);
}
}
static ssize_t UartSampleWrite(struct file *filep, const char *buf, size_t count)
{
int32_t ret;
uint8_t *tmpBuf = NULL;
struct inode *inode = NULL;
struct UartHost *host = NULL;
if (filep == NULL || filep->f_inode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
inode = (struct inode *)filep->f_inode;
host = (struct UartHost *)inode->i_private;
if (LOS_IsUserAddressRange((vaddr_t)buf, count)) {
tmpBuf = (uint8_t *)OsalMemCalloc(count);
if (tmpBuf == NULL) {
HDF_LOGE("%s: OsalMemCalloc error", __func__);
return HDF_ERR_MALLOC_FAIL;
}
ret = LOS_ArchCopyFromUser(tmpBuf, buf, count);
if (ret != LOS_OK) {
OsalMemFree(tmpBuf);
return ret;
}
ret = UartHostWrite(host, tmpBuf, count);
OsalMemFree(tmpBuf);
return ret;
} else {
return UartHostWrite(host, (uint8_t *)buf, count);
}
}
static int32_t UartSampleDevIoctl(FAR struct file *filep, int32_t cmd, unsigned long arg)
{
int32_t ret = HDF_FAILURE;
struct UartHost *host = NULL;
struct inode *inode = NULL;
if (filep == NULL || filep->f_inode == NULL) {
return HDF_ERR_INVALID_PARAM;
}
inode = (struct inode *)filep->f_inode;
if (inode->i_private == NULL) {
return HDF_ERR_INVALID_PARAM;
}
host = (struct UartHost *)inode->i_private;
if (host->priv == NULL) {
return HDF_ERR_INVALID_PARAM;
}
HDF_LOGE("%s: num %d", __func__, host->num);
switch (cmd) {
case UART_CFG_BAUDRATE:
ret = UartHostSetBaud(host, arg);
break;
default:
HDF_LOGE("%s cmd %d not support", __func__, cmd);
ret = HDF_ERR_NOT_SUPPORT;
break;
}
return ret;
}
const struct file_operations_vfs g_uartSampleDevFops = {
.open = UartSampleDevOpen,
.close = UartSampleRelease,
.read = UartSampleRead,
.write = UartSampleWrite,
.ioctl = UartSampleDevIoctl,
};
#define MAX_DEV_NAME_SIZE 32
static void UartSampleAddRemoveDev(struct UartHost *host, bool add)
{
int32_t ret;
char *devName = NULL;
if (host == NULL || host->priv == NULL) {
HDF_LOGE("%s invalid parameter", __func__);
return;
}
devName = (char *)OsalMemCalloc(sizeof(char) * (MAX_DEV_NAME_SIZE + 1));
if (devName == NULL) {
HDF_LOGE("%s: OsalMemCalloc error", __func__);
return;
}
ret = snprintf_s(devName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, "/dev/uartdev-%d", host->num);
if (ret < 0) {
HDF_LOGE("%s snprintf_s failed", __func__);
OsalMemFree(devName);
return;
}
if (add) {
if (register_driver(devName, &g_uartSampleDevFops, HDF_UART_FS_MODE, host)) {
HDF_LOGE("%s: gen /dev/uartdev-%d fail!", __func__, host->num);
OsalMemFree(devName);
return;
}
} else {
if (unregister_driver(devName)) {
HDF_LOGE("%s: remove /dev/uartdev-%d fail!", __func__, host->num);
OsalMemFree(devName);
return;
}
}
OsalMemFree(devName);
}
void UartSampleAddDev(struct UartHost *host)
{
UartSampleAddRemoveDev(host, true);
}
void UartSampleRemoveDev(struct UartHost *host)
{
UartSampleAddRemoveDev(host, false);
}
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include "uart_core.h"
#include "uart_dispatch_sample.h"
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "osal_mem.h"
#include "uart_pl011_sample.h"
#define HDF_LOG_TAG "uart_dispatch_sample"
static int32_t SampleDispatchWrite(struct UartDevice *device, struct HdfSBuf *txBuf)
{
uint32_t idx;
uint32_t dataSize = 0;
const uint8_t *data = NULL;
struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;
if (regMap == NULL) {
HDF_LOGE("%s: regMap is NULL", __func__);
return HDF_FAILURE;
}
if (!HdfSbufReadBuffer(txBuf, (const void **)&data, &dataSize)) {
HDF_LOGE("%s: Failed to read sbuf", __func__);
return HDF_FAILURE;
}
regMap = (struct UartRegisterMap *)device->resource.physBase;
for (idx = 0; idx < dataSize; idx++) {
UartPl011Write(regMap, data[idx]);
}
return HDF_SUCCESS;
}
static int32_t SampleDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t result = HDF_FAILURE;
if (client == NULL || client->device == NULL) {
HDF_LOGE("%s: client or client->device is NULL", __func__);
return result;
}
struct UartDevice *uartDevice = (struct UartDevice *)client->device->service;
if (uartDevice == NULL) {
HDF_LOGE("%s: uartDevice is NULL", __func__);
return result;
}
switch (cmdId) {
case UART_WRITE: {
result = SampleDispatchWrite(uartDevice, data);
break;
}
default:
break;
}
return result;
}
void SampleDispatchConstruct(struct UartDevice *device)
{
struct IDeviceIoService *ioService = &device->ioService;
if (ioService != NULL) {
ioService->Dispatch = &SampleDispatch;
}
}
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include "uart_pl011_sample.h"
void UartPl011SetLcrBits(struct UartRegisterMap *regMap, uint32_t bits)
{
bool uartEnabled = UartPl011IsEnabled(regMap);
/* UART must be disabled before UARTLCR_H are reprogrammed */
UartPl011Disable(regMap);
regMap->lcr |= (bits);
/* Restore uart enable state */
if (uartEnabled) {
UartPl011Enable(regMap);
}
}
void UartPl011UpdateLcr(struct UartRegisterMap *regMap)
{
bool uartEnabled = UartPl011IsEnabled(regMap);
/* UART must be disabled before UARTLCR_H are reprogrammed */
UartPl011Disable(regMap);
regMap->lcr = regMap->lcr;
/* restore uart enable state */
if (uartEnabled) {
UartPl011Enable(regMap);
}
}
UartPl011Error UartPl011SetBaudrate(struct UartRegisterMap *regMap, uint32_t clk, uint32_t baudrate)
{
if (baudrate == 0) {
return UART_PL011_ERR_INVALID_ARG;
}
uint32_t value = SAMPLING_FACTOR * baudrate;
uint32_t divider = clk / value;
uint32_t remainder = clk % value;
uint32_t fraction;
value = (SAMPLING_FACTOR * remainder) / baudrate;
fraction = (value >> 1) + (value & 1);
regMap->ibrd = divider;
regMap->fbrd = fraction;
/* to internally update the contents of UARTIBRD or
* UARTFBRD, a UARTLCR_H write must always be performed at the end.
*/
UartPl011UpdateLcr(regMap);
return UART_PL011_ERR_NONE;
}
void UartPl011SetDataFormat(
struct UartRegisterMap *regMap, uint32_t wordLen, uint32_t parity, uint32_t stopBits)
{
bool uartEnabled = UartPl011IsEnabled(regMap);
uint32_t lcr = regMap->lcr & (~UART_PL011_DATA_FORMAT_MASK);
lcr |= wordLen & UART_PL011_LCR_H_WLEN_MASK;
lcr |= parity & UART_PL011_LCR_H_PARITY_MASK;
lcr |= stopBits & UART_PL011_LCR_H_STOPBIT_MASK;
/* UART must be disabled before UARTLCR_H are reprogrammed */
UartPl011Disable(regMap);
regMap->lcr = lcr;
if (uartEnabled) {
UartPl011Enable(regMap);
}
}
void UartPl011ResetRegisters(struct UartRegisterMap *regMap)
{
regMap->cr = UART_PL011_DEFAULT_CTRL_REG_VALUE;
regMap->dr = UART_PL011_DEFAULT_DATA_REG_VALUE;
/* Clear all the errors */
regMap->ecr = UART_PL011_DEFAULT_ECR_VALUE;
regMap->ilpr = UART_PL011_DEFAULT_ILPR_VALUE;
regMap->ibrd = UART_PL011_DEFAULT_IBRD_REG_VALUE;
regMap->fbrd = UART_PL011_DEFAULT_FBRD_REG_VALUE;
regMap->lcr = UART_PL011_DEFAULT_LCR_H_VALUE;
regMap->ifls = UART_PL011_DEFAULT_IFLS_REG_VALUE;
/* Clear all interrupt mask */
regMap->imsc = UART_PL011_DEFAULT_IMSC_REG_VALUE;
/* Clear all interrupts */
regMap->icr = UART_PL011_DEFAULT_ICR_VALUE;
regMap->dmacr = UART_PL011_DEFAULT_DMACR_VALUE;
}
/* Copyright 2020 Huawei Device Co., Ltd.
*
* 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.
*/
#include "device_resource_if.h"
#include "buf_fifo.h"
#include "hdf_device_desc.h"
#include "hdf_log.h"
#include "hisoc/uart.h"
#include "osal_io.h"
#include "osal_mem.h"
#include "uart_core.h"
#include "uart_dev_sample.h"
#include "uart_dispatch_sample.h"
#include "uart_pl011_sample.h"
#define HDF_LOG_TAG uart_sample
#define UART_RX_FIFO_SIZE 128
static uint8_t g_fifoBuffer[UART_RX_FIFO_SIZE] = {0};
/* HdfDriverEntry method definitions */
static int32_t HdfUartSampleBind(struct HdfDeviceObject *device);
static int32_t HdfUartSampleInit(struct HdfDeviceObject *device);
static void HdfUartSampleRelease(struct HdfDeviceObject *device);
/* HdfDriverEntry definitions */
struct HdfDriverEntry g_hdfUartSample = {
.moduleVersion = 1,
.moduleName = "UART_SAMPLE",
.Bind = HdfUartSampleBind,
.Init = HdfUartSampleInit,
.Release = HdfUartSampleRelease,
};
// Initialize HdfDriverEntry
HDF_INIT(g_hdfUartSample);
/* UartHostMethod method definitions */
static int32_t SampleInit(struct UartHost *host);
static int32_t SampleDeinit(struct UartHost *host);
static int32_t SampleWrite(struct UartHost *host, uint8_t *data, uint32_t size);
static int32_t SampleSetBaud(struct UartHost *host, uint32_t baudRate);
static int32_t SampleGetBaud(struct UartHost *host, uint32_t *baudRate);
/* UartHostMethod definitions */
struct UartHostMethod g_uartSampleHostMethod = {
.Init = SampleInit,
.Deinit = SampleDeinit,
.Read = NULL,
.Write = SampleWrite,
.SetBaud = SampleSetBaud,
.GetBaud = SampleGetBaud,
.SetAttribute = NULL,
.GetAttribute = NULL,
.SetTransMode = NULL,
};
/* UartHostMethod implementations */
static int32_t SampleInit(struct UartHost *host)
{
HDF_LOGI("%s: Enter", __func__);
if (host == NULL) {
HDF_LOGE("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
static int32_t SampleDeinit(struct UartHost *host)
{
HDF_LOGI("%s: Enter", __func__);
if (host == NULL) {
HDF_LOGE("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
return HDF_SUCCESS;
}
static int32_t SampleWrite(struct UartHost *host, uint8_t *data, uint32_t size)
{
HDF_LOGI("%s: Enter", __func__);
uint32_t idx;
struct UartRegisterMap *regMap = NULL;
struct UartDevice *device = NULL;
if (host == NULL || data == NULL || size == 0) {
HDF_LOGE("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
device = (struct UartDevice *)host->priv;
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
regMap = (struct UartRegisterMap *)device->resource.physBase;
for (idx = 0; idx < size; idx++) {
UartPl011Write(regMap, data[idx]);
}
return HDF_SUCCESS;
}
static int32_t SampleSetBaud(struct UartHost *host, uint32_t baudRate)
{
HDF_LOGI("%s: Enter", __func__);
struct UartDevice *device = NULL;
struct UartRegisterMap *regMap = NULL;
UartPl011Error err;
if (host == NULL) {
HDF_LOGE("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
device = (struct UartDevice *)host->priv;
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
regMap = (struct UartRegisterMap *)device->resource.physBase;
if (device->state != UART_DEVICE_INITIALIZED) {
return UART_PL011_ERR_NOT_INIT;
}
if (baudRate == 0) {
return UART_PL011_ERR_INVALID_BAUD;
}
err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate);
if (err == UART_PL011_ERR_NONE) {
device->baudrate = baudRate;
}
return err;
}
static int32_t SampleGetBaud(struct UartHost *host, uint32_t *baudRate)
{
HDF_LOGI("%s: Enter", __func__);
struct UartDevice *device = NULL;
if (host == NULL) {
HDF_LOGE("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
device = (struct UartDevice *)host->priv;
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
*baudRate = device->baudrate;
return HDF_SUCCESS;
}
static int UartDeviceInit(struct UartDevice *device)
{
UartPl011Error err;
struct UartResource *resource = &device->resource;
struct UartRegisterMap *regMap = (struct UartRegisterMap *)resource->physBase;
if ((resource->uartClk == 0) || (resource->baudrate == 0)) {
return HDF_ERR_INVALID_PARAM;
}
/* Updating the system clock */
device->uartClk = resource->uartClk;
uart_clk_cfg(0, true);
/* clear and reset registers. */
UartPl011ResetRegisters(regMap);
/* set baud rate as device config */
err = UartPl011SetBaudrate(regMap, resource->uartClk, resource->baudrate);
if (err != UART_PL011_ERR_NONE) {
return HDF_FAILURE;
}
/* set the data format as device config */
UartPl011SetDataFormat(regMap, resource->wlen, resource->parity, resource->stopBit);
/* Enabling the FIFOs */
UartPl011EnableFifo(regMap);
UartPl011Enable(regMap);
BufferFifoInit(&device->rxFifo, g_fifoBuffer, UART_RX_FIFO_SIZE);
device->state = UART_DEVICE_INITIALIZED;
return HDF_SUCCESS;
}
static uint32_t UartDeviceGetResource(
struct UartDevice *device, const struct DeviceResourceNode *resourceNode)
{
struct UartResource *resource = &device->resource;
struct DeviceResourceIface *dri = NULL;
dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (dri == NULL || dri->GetUint32 == NULL) {
HDF_LOGE("DeviceResourceIface is invalid");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read num fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read base fail");
return HDF_FAILURE;
}
resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48);
if (resource->physBase == 0) {
HDF_LOGE("uart config fail to remap physBase");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read irqNum fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read baudrate fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read wlen fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read parity fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read stopBit fail");
return HDF_FAILURE;
}
if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) {
HDF_LOGE("uart config read uartClk fail");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t SampleAttach(struct UartHost *host, struct HdfDeviceObject *device)
{
int32_t ret;
struct UartDevice *uartDevice = NULL;
if (device->property == NULL) {
HDF_LOGE("%s: property is NULL", __func__);
return HDF_FAILURE;
}
uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice));
if (uartDevice == NULL) {
HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__);
return HDF_ERR_MALLOC_FAIL;
}
SampleDispatchConstruct(uartDevice);
device->service = &uartDevice->ioService;
ret = UartDeviceGetResource(uartDevice, device->property);
if (ret != HDF_SUCCESS) {
(void)OsalMemFree(uartDevice);
return HDF_FAILURE;
}
host->num = uartDevice->resource.num;
host->priv = uartDevice;
UartSampleAddDev(host);
return UartDeviceInit(uartDevice);
}
static void UartDeviceDeinit(struct UartDevice *device)
{
struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase;
/* wait for uart enter idle. */
while (UartPl011IsBusy(regMap));
UartPl011ResetRegisters(regMap);
uart_clk_cfg(0, false);
OsalIoUnmap((void *)device->resource.physBase);
device->state = UART_DEVICE_UNINITIALIZED;
}
static void SampleDetach(struct UartHost *host)
{
struct UartDevice *uartDevice = NULL;
if (host->priv == NULL) {
HDF_LOGE("%s: invalid parameter", __func__);
return;
}
uartDevice = host->priv;
UartDeviceDeinit(uartDevice);
(void)OsalMemFree(uartDevice);
host->priv = NULL;
}
/* HdfDriverEntry implementations */
static int32_t HdfUartSampleBind(struct HdfDeviceObject *device)
{
if (device == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
HDF_LOGI("Enter %s:", __func__);
return (UartHostCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;
}
static int32_t HdfUartSampleInit(struct HdfDeviceObject *device)
{
int32_t ret;
struct UartHost *host = NULL;
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return HDF_ERR_INVALID_OBJECT;
}
HDF_LOGI("Enter %s:", __func__);
host = UartHostFromDevice(device);
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return HDF_FAILURE;
}
ret = SampleAttach(host, device);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: attach error", __func__);
return HDF_FAILURE;
}
host->method = &g_uartSampleHostMethod;
return ret;
}
static void HdfUartSampleRelease(struct HdfDeviceObject *device)
{
struct UartHost *host = NULL;
HDF_LOGI("Enter %s:", __func__);
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return;
}
host = UartHostFromDevice(device);
if (host == NULL) {
HDF_LOGE("%s: host is NULL", __func__);
return;
}
if (host->priv != NULL) {
SampleDetach(host);
}
UartHostDestroy(host);
}
# Copyright (c) 2020 Huawei Device Co., Ltd.
# 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.
import("//build/lite/config/component/lite_component.gni")
copy("wifi_firmware") {
sources = [
"driver/firmware"
]
outputs = [
"$root_out_dir/vendor/{{source_file_part}}"
]
}
config DRIVERS_HDF_WIFI
bool "Enable HDF WiFi Host driver"
default n
depends on DRIVERS_HDF
help
Answer Y to enable HDF WiFi Host driver.
config DRIVERS_HI3881
bool "Enable Hi3881 Host driver"
default n
depends on DRIVERS_HDF_WIFI
help
Answer Y to enable Hi3881 Host driver.
@WiFi patch info
CFG_COUNTRY_CODE=CN;
CFG_RSSI_OFFSET=0;
CFG_MAC=00:00:00:00:00:00;
CFG_DBB_PARAMS=0x6B6B6D6E,0x67676767,0x50545F60,0x565E5E5E,0x4F4F5656,0x00000000,0x01000000;
CFG_FREQ_COMP=105,100,-30;
CFG_CH_TXPWR_OFFSET=0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff;
PARA_VERSION=Hi3881V100;
ADDR_FILE_FILES=1,0xe4800,/vendor/firmware/hisilicon/hi3881_fw.bin;
PARA_CONFIG=0xe4800,4;
QUIT;
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册