1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "uart_dev_sample.h"
10 #include "fs/fs.h"
11 #include "securec.h"
12 #include "user_copy.h"
13 #include "hdf_log.h"
14 #include "osal_mem.h"
15 #include "uart_pl011_sample.h"
16
17 #define HDF_LOG_TAG uart_dev_sample
18 #define HDF_UART_FS_MODE 0660
19
UartSampleDevOpen(struct file * filep)20 static int32_t UartSampleDevOpen(struct file *filep)
21 {
22 struct UartHost *host = NULL;
23
24 if (filep == NULL || filep->f_vnode == NULL) {
25 return HDF_ERR_INVALID_PARAM;
26 }
27 struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
28 host = (struct UartHost *)drv->priv;
29 if (host == NULL) {
30 HDF_LOGE("%s: host is NULL", __func__);
31 return HDF_ERR_INVALID_PARAM;
32 }
33 HDF_LOGI("%s: open uart%d success", __func__, host->num);
34 return HDF_SUCCESS;
35 }
UartSampleRelease(struct file * filep)36 static int32_t UartSampleRelease(struct file *filep)
37 {
38 struct UartHost *host = NULL;
39
40 if (filep == NULL || filep->f_vnode == NULL) {
41 return HDF_ERR_INVALID_PARAM;
42 }
43 struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
44 host = (struct UartHost *)drv->priv;
45 if (host == NULL) {
46 HDF_LOGE("%s: host is NULL", __func__);
47 return HDF_ERR_INVALID_PARAM;
48 }
49 HDF_LOGI("%s: close uart%d success", __func__, host->num);
50 return HDF_SUCCESS;
51 }
52
UartSampleRead(struct file * filep,char * buf,size_t count)53 static ssize_t UartSampleRead(struct file *filep, char *buf, size_t count)
54 {
55 int32_t ret;
56 uint8_t *tmpBuf = NULL;
57 struct UartHost *host = NULL;
58
59 if (filep == NULL || filep->f_vnode == NULL) {
60 return HDF_ERR_INVALID_PARAM;
61 }
62 struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
63 host = (struct UartHost *)drv->priv;
64
65 if (LOS_IsUserAddressRange((vaddr_t)(uintptr_t)buf, count)) {
66 tmpBuf = (uint8_t *)OsalMemCalloc(count);
67 if (tmpBuf == NULL) {
68 HDF_LOGE("%s: OsalMemCalloc error", __func__);
69 return HDF_ERR_MALLOC_FAIL;
70 }
71 ret = UartHostRead(host, tmpBuf, count);
72 if (ret == HDF_SUCCESS) {
73 ret = LOS_ArchCopyToUser(buf, tmpBuf, count);
74 }
75 OsalMemFree(tmpBuf);
76 return ret;
77 } else {
78 return UartHostRead(host, (uint8_t *)buf, count);
79 }
80 }
81
UartSampleWrite(struct file * filep,const char * buf,size_t count)82 static ssize_t UartSampleWrite(struct file *filep, const char *buf, size_t count)
83 {
84 int32_t ret;
85 uint8_t *tmpBuf = NULL;
86 struct UartHost *host = NULL;
87
88 if (filep == NULL || filep->f_vnode == NULL) {
89 return HDF_ERR_INVALID_PARAM;
90 }
91 struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
92 host = (struct UartHost *)drv->priv;
93
94 if (LOS_IsUserAddressRange((vaddr_t)(uintptr_t)buf, count)) {
95 tmpBuf = (uint8_t *)OsalMemCalloc(count);
96 if (tmpBuf == NULL) {
97 HDF_LOGE("%s: OsalMemCalloc error", __func__);
98 return HDF_ERR_MALLOC_FAIL;
99 }
100 ret = LOS_ArchCopyFromUser(tmpBuf, buf, count);
101 if (ret != LOS_OK) {
102 OsalMemFree(tmpBuf);
103 return ret;
104 }
105 ret = UartHostWrite(host, tmpBuf, count);
106 OsalMemFree(tmpBuf);
107 return ret;
108 } else {
109 return UartHostWrite(host, (uint8_t *)buf, count);
110 }
111 }
112
UartSampleDevIoctl(struct file * filep,int32_t cmd,unsigned long arg)113 static int32_t UartSampleDevIoctl(struct file *filep, int32_t cmd, unsigned long arg)
114 {
115 int32_t ret;
116 struct UartHost *host = NULL;
117 if (filep == NULL || filep->f_vnode == NULL) {
118 return HDF_ERR_INVALID_PARAM;
119 }
120 struct drv_data *drv = (struct drv_data *)filep->f_vnode->data;
121 host = (struct UartHost *)drv->priv;
122 if (host->priv == NULL) {
123 return HDF_ERR_INVALID_PARAM;
124 }
125
126 ret = HDF_FAILURE;
127 switch (cmd) {
128 case UART_CFG_BAUDRATE:
129 ret = UartHostSetBaud(host, arg);
130 break;
131 default:
132 HDF_LOGE("%s cmd %d not support", __func__, cmd);
133 ret = HDF_ERR_NOT_SUPPORT;
134 break;
135 }
136 return ret;
137 }
138
139 const struct file_operations_vfs g_uartSampleDevFops = {
140 .open = UartSampleDevOpen,
141 .close = UartSampleRelease,
142 .read = UartSampleRead,
143 .write = UartSampleWrite,
144 .ioctl = UartSampleDevIoctl,
145 };
146
147 #define MAX_DEV_NAME_SIZE 32
AddRemoveUartDev(struct UartHost * host,bool add)148 static void AddRemoveUartDev(struct UartHost *host, bool add)
149 {
150 int32_t ret;
151 char *devName = NULL;
152
153 if (host == NULL || host->priv == NULL) {
154 HDF_LOGW("%s: invalid parameter", __func__);
155 return;
156 }
157 devName = (char *)OsalMemCalloc(sizeof(char) * (MAX_DEV_NAME_SIZE + 1));
158 if (devName == NULL) {
159 HDF_LOGE("%s: OsalMemCalloc error", __func__);
160 return;
161 }
162 ret = snprintf_s(devName, MAX_DEV_NAME_SIZE + 1, MAX_DEV_NAME_SIZE, "/dev/uartdev-%d", host->num);
163 if (ret < 0) {
164 HDF_LOGE("%s: snprintf_s failed", __func__);
165 OsalMemFree(devName);
166 return;
167 }
168 if (add) {
169 if (register_driver(devName, &g_uartSampleDevFops, HDF_UART_FS_MODE, host)) {
170 HDF_LOGE("%s: gen /dev/uartdev-%d fail!", __func__, host->num);
171 OsalMemFree(devName);
172 return;
173 }
174 } else {
175 if (unregister_driver(devName)) {
176 HDF_LOGE("%s: remove /dev/uartdev-%d fail!", __func__, host->num);
177 OsalMemFree(devName);
178 return;
179 }
180 }
181 OsalMemFree(devName);
182 }
183
AddUartDevice(struct UartHost * host)184 void AddUartDevice(struct UartHost *host)
185 {
186 AddRemoveUartDev(host, true);
187 }
188
RemoveUartDevice(struct UartHost * host)189 void RemoveUartDevice(struct UartHost *host)
190 {
191 AddRemoveUartDev(host, false);
192 }
193