xref: /nrf52832-nimble/rt-thread/components/vbus/vbus_chnx.c (revision 104654410c56c573564690304ae786df310c91fc)
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