1*10465441SEvalZero /*
2*10465441SEvalZero * COPYRIGHT (C) 2018, Real-Thread Information Technology Ltd
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2013-11-04 Grissiom add comment
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <rthw.h>
12*10465441SEvalZero #include <rtthread.h>
13*10465441SEvalZero #include <rtdevice.h>
14*10465441SEvalZero
15*10465441SEvalZero #include "vbus.h"
16*10465441SEvalZero
_rx_indicate(void * ctx)17*10465441SEvalZero static void _rx_indicate(void *ctx)
18*10465441SEvalZero {
19*10465441SEvalZero rt_device_t dev = ctx;
20*10465441SEvalZero
21*10465441SEvalZero if (dev->rx_indicate)
22*10465441SEvalZero dev->rx_indicate(dev, 0);
23*10465441SEvalZero }
24*10465441SEvalZero
_tx_complete(void * ctx)25*10465441SEvalZero static void _tx_complete(void *ctx)
26*10465441SEvalZero {
27*10465441SEvalZero rt_device_t dev = ctx;
28*10465441SEvalZero
29*10465441SEvalZero if (dev->tx_complete)
30*10465441SEvalZero dev->tx_complete(dev, 0);
31*10465441SEvalZero }
32*10465441SEvalZero
_open(rt_device_t dev,rt_uint16_t oflag)33*10465441SEvalZero static rt_err_t _open(rt_device_t dev, rt_uint16_t oflag)
34*10465441SEvalZero {
35*10465441SEvalZero int chnr;
36*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
37*10465441SEvalZero
38*10465441SEvalZero if (vdev->chnr)
39*10465441SEvalZero return RT_EOK;
40*10465441SEvalZero
41*10465441SEvalZero /* FIXME: request the same name for twice will crash */
42*10465441SEvalZero chnr = rt_vbus_request_chn(&vdev->req, RT_WAITING_FOREVER);
43*10465441SEvalZero if (chnr < 0)
44*10465441SEvalZero return chnr;
45*10465441SEvalZero
46*10465441SEvalZero vdev->chnr = chnr;
47*10465441SEvalZero rt_vbus_register_listener(chnr, RT_VBUS_EVENT_ID_RX, _rx_indicate, dev);
48*10465441SEvalZero rt_vbus_register_listener(chnr, RT_VBUS_EVENT_ID_TX, _tx_complete, dev);
49*10465441SEvalZero
50*10465441SEvalZero return RT_EOK;
51*10465441SEvalZero }
52*10465441SEvalZero
_close(rt_device_t dev)53*10465441SEvalZero static rt_err_t _close(rt_device_t dev)
54*10465441SEvalZero {
55*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
56*10465441SEvalZero
57*10465441SEvalZero RT_ASSERT(vdev->chnr != 0);
58*10465441SEvalZero
59*10465441SEvalZero rt_vbus_close_chn(vdev->chnr);
60*10465441SEvalZero vdev->chnr = 0;
61*10465441SEvalZero
62*10465441SEvalZero return RT_EOK;
63*10465441SEvalZero }
64*10465441SEvalZero
_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)65*10465441SEvalZero static rt_size_t _read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
66*10465441SEvalZero {
67*10465441SEvalZero rt_size_t outsz = 0;
68*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
69*10465441SEvalZero
70*10465441SEvalZero RT_ASSERT(vdev->chnr != 0);
71*10465441SEvalZero
72*10465441SEvalZero if (vdev->act == RT_NULL)
73*10465441SEvalZero {
74*10465441SEvalZero vdev->act = rt_vbus_data_pop(vdev->chnr);
75*10465441SEvalZero vdev->pos = 0;
76*10465441SEvalZero }
77*10465441SEvalZero
78*10465441SEvalZero while (1)
79*10465441SEvalZero {
80*10465441SEvalZero rt_err_t err;
81*10465441SEvalZero
82*10465441SEvalZero while (vdev->act)
83*10465441SEvalZero {
84*10465441SEvalZero rt_size_t cpysz;
85*10465441SEvalZero
86*10465441SEvalZero if (size - outsz > vdev->act->size - vdev->pos)
87*10465441SEvalZero cpysz = vdev->act->size - vdev->pos;
88*10465441SEvalZero else
89*10465441SEvalZero cpysz = size - outsz;
90*10465441SEvalZero
91*10465441SEvalZero rt_memcpy((char*)buffer + outsz, ((char*)(vdev->act+1)) + vdev->pos, cpysz);
92*10465441SEvalZero vdev->pos += cpysz;
93*10465441SEvalZero
94*10465441SEvalZero outsz += cpysz;
95*10465441SEvalZero if (outsz == size)
96*10465441SEvalZero {
97*10465441SEvalZero return outsz;
98*10465441SEvalZero }
99*10465441SEvalZero else if (outsz > size)
100*10465441SEvalZero RT_ASSERT(0);
101*10465441SEvalZero
102*10465441SEvalZero /* free old and get new */
103*10465441SEvalZero rt_free(vdev->act);
104*10465441SEvalZero vdev->act = rt_vbus_data_pop(vdev->chnr);
105*10465441SEvalZero vdev->pos = 0;
106*10465441SEvalZero }
107*10465441SEvalZero
108*10465441SEvalZero /* TODO: We don't want to touch the rx_indicate here. But this lead to
109*10465441SEvalZero * some duplication. Maybe we should find a better way to handle this.
110*10465441SEvalZero */
111*10465441SEvalZero if (rt_interrupt_get_nest() == 0)
112*10465441SEvalZero {
113*10465441SEvalZero err = rt_vbus_listen_on(vdev->chnr, RT_WAITING_FOREVER);
114*10465441SEvalZero }
115*10465441SEvalZero else
116*10465441SEvalZero {
117*10465441SEvalZero err = rt_vbus_listen_on(vdev->chnr, 0);
118*10465441SEvalZero }
119*10465441SEvalZero if (err != RT_EOK)
120*10465441SEvalZero {
121*10465441SEvalZero rt_set_errno(err);
122*10465441SEvalZero return outsz;
123*10465441SEvalZero }
124*10465441SEvalZero vdev->act = rt_vbus_data_pop(vdev->chnr);
125*10465441SEvalZero vdev->pos = 0;
126*10465441SEvalZero }
127*10465441SEvalZero }
128*10465441SEvalZero
_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)129*10465441SEvalZero static rt_size_t _write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
130*10465441SEvalZero {
131*10465441SEvalZero rt_err_t err;
132*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
133*10465441SEvalZero
134*10465441SEvalZero RT_ASSERT(vdev->chnr != 0);
135*10465441SEvalZero
136*10465441SEvalZero if (rt_interrupt_get_nest() == 0)
137*10465441SEvalZero {
138*10465441SEvalZero /* Thread context. */
139*10465441SEvalZero err = rt_vbus_post(vdev->chnr, vdev->req.prio,
140*10465441SEvalZero buffer, size, RT_WAITING_FOREVER);
141*10465441SEvalZero }
142*10465441SEvalZero else
143*10465441SEvalZero {
144*10465441SEvalZero /* Interrupt context. */
145*10465441SEvalZero err = rt_vbus_post(vdev->chnr, vdev->req.prio,
146*10465441SEvalZero buffer, size, 0);
147*10465441SEvalZero }
148*10465441SEvalZero
149*10465441SEvalZero if (err)
150*10465441SEvalZero {
151*10465441SEvalZero rt_set_errno(err);
152*10465441SEvalZero return 0;
153*10465441SEvalZero }
154*10465441SEvalZero
155*10465441SEvalZero return size;
156*10465441SEvalZero }
157*10465441SEvalZero
_control(rt_device_t dev,int cmd,void * args)158*10465441SEvalZero rt_err_t _control(rt_device_t dev, int cmd, void *args)
159*10465441SEvalZero {
160*10465441SEvalZero RT_ASSERT(dev);
161*10465441SEvalZero
162*10465441SEvalZero switch (cmd) {
163*10465441SEvalZero case VBUS_IOC_LISCFG: {
164*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
165*10465441SEvalZero struct rt_vbus_dev_liscfg *liscfg = args;
166*10465441SEvalZero
167*10465441SEvalZero RT_ASSERT(vdev->chnr != 0);
168*10465441SEvalZero if (!liscfg)
169*10465441SEvalZero return -RT_ERROR;
170*10465441SEvalZero
171*10465441SEvalZero rt_vbus_register_listener(vdev->chnr, liscfg->event,
172*10465441SEvalZero liscfg->listener, liscfg->ctx);
173*10465441SEvalZero return RT_EOK;
174*10465441SEvalZero }
175*10465441SEvalZero break;
176*10465441SEvalZero #ifdef RT_VBUS_USING_FLOW_CONTROL
177*10465441SEvalZero case VBUS_IOCRECV_WM: {
178*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
179*10465441SEvalZero struct rt_vbus_wm_cfg *cfg;
180*10465441SEvalZero
181*10465441SEvalZero RT_ASSERT(vdev->chnr != 0);
182*10465441SEvalZero
183*10465441SEvalZero if (!args)
184*10465441SEvalZero return -RT_ERROR;
185*10465441SEvalZero
186*10465441SEvalZero cfg = (struct rt_vbus_wm_cfg*)args;
187*10465441SEvalZero if (cfg->low > cfg->high)
188*10465441SEvalZero return -RT_ERROR;
189*10465441SEvalZero
190*10465441SEvalZero rt_vbus_set_recv_wm(vdev->chnr, cfg->low, cfg->high);
191*10465441SEvalZero return RT_EOK;
192*10465441SEvalZero }
193*10465441SEvalZero break;
194*10465441SEvalZero case VBUS_IOCPOST_WM: {
195*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
196*10465441SEvalZero struct rt_vbus_wm_cfg *cfg;
197*10465441SEvalZero
198*10465441SEvalZero RT_ASSERT(vdev->chnr != 0);
199*10465441SEvalZero
200*10465441SEvalZero if (!args)
201*10465441SEvalZero return -RT_ERROR;
202*10465441SEvalZero
203*10465441SEvalZero cfg = (struct rt_vbus_wm_cfg*)args;
204*10465441SEvalZero if (cfg->low > cfg->high)
205*10465441SEvalZero return -RT_ERROR;
206*10465441SEvalZero
207*10465441SEvalZero rt_vbus_set_post_wm(vdev->chnr, cfg->low, cfg->high);
208*10465441SEvalZero return RT_EOK;
209*10465441SEvalZero }
210*10465441SEvalZero break;
211*10465441SEvalZero #endif
212*10465441SEvalZero default:
213*10465441SEvalZero break;
214*10465441SEvalZero };
215*10465441SEvalZero
216*10465441SEvalZero return -RT_ENOSYS;
217*10465441SEvalZero }
218*10465441SEvalZero
rt_vbus_get_chnnr(rt_device_t dev)219*10465441SEvalZero rt_uint8_t rt_vbus_get_chnnr(rt_device_t dev)
220*10465441SEvalZero {
221*10465441SEvalZero struct rt_vbus_dev *vdev;
222*10465441SEvalZero
223*10465441SEvalZero RT_ASSERT(dev);
224*10465441SEvalZero
225*10465441SEvalZero vdev = dev->user_data;
226*10465441SEvalZero
227*10465441SEvalZero return vdev->chnr;
228*10465441SEvalZero }
229*10465441SEvalZero
rt_vbus_chnx_register_disconn(rt_device_t dev,rt_vbus_event_listener indi,void * ctx)230*10465441SEvalZero void rt_vbus_chnx_register_disconn(rt_device_t dev,
231*10465441SEvalZero rt_vbus_event_listener indi,
232*10465441SEvalZero void *ctx)
233*10465441SEvalZero {
234*10465441SEvalZero struct rt_vbus_dev *vdev = dev->user_data;
235*10465441SEvalZero
236*10465441SEvalZero RT_ASSERT(vdev->chnr != 0);
237*10465441SEvalZero
238*10465441SEvalZero if (vdev)
239*10465441SEvalZero rt_vbus_register_listener(vdev->chnr, RT_VBUS_EVENT_ID_DISCONN,
240*10465441SEvalZero indi, ctx);
241*10465441SEvalZero }
242*10465441SEvalZero
243*10465441SEvalZero #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
244*10465441SEvalZero
245*10465441SEvalZero extern struct rt_vbus_dev rt_vbus_chn_devx[];
246*10465441SEvalZero static struct rt_device _devx[32];
247*10465441SEvalZero
rt_vbus_chnx_init(void)248*10465441SEvalZero rt_err_t rt_vbus_chnx_init(void)
249*10465441SEvalZero {
250*10465441SEvalZero int i;
251*10465441SEvalZero struct rt_vbus_dev *p;
252*10465441SEvalZero
253*10465441SEvalZero for (i = 0, p = rt_vbus_chn_devx;
254*10465441SEvalZero i < ARRAY_SIZE(_devx) && p->req.name;
255*10465441SEvalZero i++, p++)
256*10465441SEvalZero {
257*10465441SEvalZero _devx[i].type = RT_Device_Class_Char;
258*10465441SEvalZero _devx[i].open = _open;
259*10465441SEvalZero _devx[i].close = _close;
260*10465441SEvalZero _devx[i].read = _read;
261*10465441SEvalZero _devx[i].write = _write;
262*10465441SEvalZero _devx[i].control = _control;
263*10465441SEvalZero _devx[i].user_data = p;
264*10465441SEvalZero rt_device_register(&_devx[i], p->req.name, RT_DEVICE_FLAG_RDWR);
265*10465441SEvalZero }
266*10465441SEvalZero
267*10465441SEvalZero return RT_EOK;
268*10465441SEvalZero }
269