1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <limits.h>
8 #include <poll.h>
9 #ifndef AOS_BOARD_HAAS700
10 #include <vfsdev/uart_dev.h>
11 #endif
12 #include "aos/hal/uart.h"
13 #include "aos/kernel.h"
14 #include "aos_hal_uart.h"
15 
16 #ifdef CONFIG_UART_NUM
17 #define PLATFORM_UART_NUM CONFIG_UART_NUM
18 #else
19 #define PLATFORM_UART_NUM 4
20 #endif
21 
22 static int uart_fd_table[PLATFORM_UART_NUM];
23 
aos_hal_uart_init(uart_dev_t * uart)24 int32_t aos_hal_uart_init(uart_dev_t *uart)
25 {
26     return hal_uart_init(uart);
27 }
28 
aos_hal_uart_send(uart_dev_t * uart,const void * data,uint32_t size,uint32_t timeout)29 int32_t aos_hal_uart_send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout)
30 {
31     return hal_uart_send(uart, data, size, timeout);
32 }
33 
aos_hal_uart_recv(uart_dev_t * uart,void * data,uint32_t expect_size,uint32_t timeout)34 int32_t aos_hal_uart_recv(uart_dev_t *uart, void *data,
35                           uint32_t expect_size, uint32_t timeout)
36 {
37     /* deprecated */
38     return -1;
39 }
40 
aos_hal_uart_recv_poll(uart_dev_t * uart,void * data,uint32_t expect_size,uint32_t * recv_size)41 int32_t aos_hal_uart_recv_poll(uart_dev_t *uart, void *data, uint32_t expect_size, uint32_t *recv_size)
42 {
43     return hal_uart_recv_II(uart, data, expect_size, recv_size, 0);
44 }
45 
aos_hal_uart_recv_II(uart_dev_t * uart,void * data,uint32_t expect_size,uint32_t * recv_size,uint32_t timeout)46 int32_t aos_hal_uart_recv_II(uart_dev_t *uart, void *data, uint32_t expect_size,
47                              uint32_t *recv_size, uint32_t timeout)
48 {
49     return hal_uart_recv_II(uart, data, expect_size, recv_size, timeout);
50 }
51 
aos_hal_uart_rx_sem_take(int uartid,int timeout)52 int aos_hal_uart_rx_sem_take(int uartid, int timeout)
53 {
54 #ifndef AOS_BOARD_HAAS700
55     return hal_uart_rx_sem_take(uartid, timeout);
56 #else
57     return -1;
58 #endif
59 }
60 
aos_hal_uart_rx_sem_give(int port)61 int aos_hal_uart_rx_sem_give(int port)
62 {
63 #ifndef AOS_BOARD_HAAS700
64     return hal_uart_rx_sem_give(port);
65 #else
66     return -1;
67 #endif
68 }
69 
70 typedef struct {
71     void (*callback)(int, void *, uint16_t, void *);
72     void *userdata;
73     uart_dev_t *uart;
74     int task_running;
75     int stop;
76     aos_mutex_t lock;
77     aos_sem_t sem;
78     aos_task_t task;
79 } uart_recv_notify_t;
80 
81 static uart_recv_notify_t *uart_recv_notifiers[PLATFORM_UART_NUM];
82 
uart_recv_handler(void * args)83 static void uart_recv_handler(void *args)
84 {
85     uart_recv_notify_t *notify = (uart_recv_notify_t *)args;
86     uart_dev_t *uart;
87     char recv_buffer[256];
88     uint32_t recv_size;
89     int ret;
90 
91     if (!notify)
92         return;
93 
94     uart = notify->uart;
95     while (1) {
96         aos_mutex_lock(&notify->lock, AOS_WAIT_FOREVER);
97         if (notify->stop) {
98             aos_mutex_unlock(&notify->lock);
99             break;
100         }
101         aos_mutex_unlock(&notify->lock);
102 
103         ret = aos_hal_uart_recv_II(uart, recv_buffer, sizeof(recv_buffer),
104                                    &recv_size, 100);
105         if (ret || recv_size <= 0)
106             continue;
107         if (notify->callback)
108             notify->callback(uart->port, recv_buffer, recv_size, notify->userdata);
109     }
110 
111     aos_sem_signal(&notify->sem);
112 }
113 
114 #if 0
115 extern int32_t hal_uart_receive_register(int port,  void(*cb)(int, void *), void *args);
116 static int uart_port_registered[7];
117 #endif
118 
aos_hal_uart_callback(uart_dev_t * uart,void (* cb)(int,void *,uint16_t,void *),void * args)119 int32_t aos_hal_uart_callback(uart_dev_t *uart, void (*cb)(int, void *, uint16_t, void *), void *args)
120 {
121 #if 0
122     if (uart_port_registered[uart->port])
123         return 0;
124     hal_uart_receive_register(uart, cb, args);
125     uart_port_registered[uart->port] = 1;
126 #else
127     uart_recv_notify_t *notify = uart_recv_notifiers[uart->port];
128 
129     if (!notify) {
130         notify = aos_malloc(sizeof(uart_recv_notify_t));
131         if (!notify)
132             return -1;
133         memset(notify, 0, sizeof(uart_recv_notify_t));
134         aos_mutex_new(&notify->lock);
135         aos_sem_new(&notify->sem, 0);
136         uart_recv_notifiers[uart->port] = notify;
137     }
138 
139     notify->callback = cb;
140     notify->userdata = args;
141     notify->uart = uart;
142 
143     if (!notify->task_running) {
144         if (aos_task_new_ext(&notify->task, "amp_uart_recv",
145             uart_recv_handler, notify, 2048, 32))
146             return -1;
147         notify->task_running = 1;
148     }
149 #endif
150     return 0;
151 }
152 
aos_hal_uart_finalize(uart_dev_t * uart)153 int32_t aos_hal_uart_finalize(uart_dev_t *uart)
154 {
155     uart_recv_notify_t *notify = uart_recv_notifiers[uart->port];
156     if (notify) {
157         if (notify->task_running) {
158             aos_mutex_lock(&notify->lock, AOS_WAIT_FOREVER);
159             notify->stop = 1;
160             aos_mutex_unlock(&notify->lock);
161             aos_sem_wait(&notify->sem, 3000);
162         }
163         aos_mutex_free(&notify->lock);
164         aos_sem_free(&notify->sem);
165         aos_free(notify);
166         uart_recv_notifiers[uart->port] = NULL;
167     }
168 
169     //close(uart_fd_table[uart->port]);
170     hal_uart_finalize(uart);
171     uart_fd_table[uart->port] = -1;
172 
173     return 0;
174 }
175