2 * Copyright (C) 2018, 2019 "IoT.bzh"
3 * Author José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
33 void (*callback)(void*,uint32_t,struct fdev*);
34 void *closure_callback;
37 struct fdev *fdev_create(int fd)
41 fdev = calloc(1, sizeof *fdev);
46 fdev->refcount = 3; /* set autoclose by default */
51 void fdev_set_itf(struct fdev *fdev, struct fdev_itf *itf, void *closure_itf)
54 fdev->closure_itf = closure_itf;
57 void fdev_dispatch(struct fdev *fdev, uint32_t events)
60 fdev->callback(fdev->closure_callback, events, fdev);
63 struct fdev *fdev_addref(struct fdev *fdev)
66 __atomic_add_fetch(&fdev->refcount, 2, __ATOMIC_RELAXED);
70 void fdev_unref(struct fdev *fdev)
72 if (fdev && __atomic_sub_fetch(&fdev->refcount, 2, __ATOMIC_RELAXED) <= 1) {
74 fdev->itf->disable(fdev->closure_itf, fdev);
76 fdev->itf->unref(fdev->closure_itf);
84 int fdev_fd(const struct fdev *fdev)
89 uint32_t fdev_events(const struct fdev *fdev)
94 int fdev_autoclose(const struct fdev *fdev)
96 return 1 & fdev->refcount;
99 static inline int is_active(struct fdev *fdev)
101 return !!fdev->callback;
104 static inline void update_activity(struct fdev *fdev, int old_active)
106 if (is_active(fdev)) {
108 fdev->itf->enable(fdev->closure_itf, fdev);
111 fdev->itf->disable(fdev->closure_itf, fdev);
115 void fdev_set_callback(struct fdev *fdev, void (*callback)(void*,uint32_t,struct fdev*), void *closure)
119 oa = is_active(fdev);
120 fdev->callback = callback;
121 fdev->closure_callback = closure;
122 update_activity(fdev, oa);
125 void fdev_set_events(struct fdev *fdev, uint32_t events)
127 if (events != fdev->events) {
128 fdev->events = events;
130 fdev->itf->update(fdev->closure_itf, fdev);
134 void fdev_set_autoclose(struct fdev *fdev, int autoclose)
137 fdev->refcount |= (unsigned)1;
139 fdev->refcount &= ~(unsigned)1;