2 * Copyright (C) 2018 "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.
34 void (*callback)(void*,uint32_t,struct fdev*);
35 void *closure_callback;
38 struct fdev *fdev_create(int fd)
42 fdev = calloc(1, sizeof *fdev);
47 fdev->refcount = 3; /* set autoclose by default */
48 fdev->repeat = -1; /* always repeat by default */
53 void fdev_set_itf(struct fdev *fdev, struct fdev_itf *itf, void *closure_itf)
56 fdev->closure_itf = closure_itf;
59 void fdev_dispatch(struct fdev *fdev, uint32_t events)
61 if (fdev->repeat > 0 && !--fdev->repeat && fdev->itf)
62 fdev->itf->disable(fdev->closure_itf, fdev);
64 fdev->callback(fdev->closure_callback, events, fdev);
67 struct fdev *fdev_addref(struct fdev *fdev)
70 __atomic_add_fetch(&fdev->refcount, 2, __ATOMIC_RELAXED);
74 void fdev_unref(struct fdev *fdev)
76 if (fdev && __atomic_sub_fetch(&fdev->refcount, 2, __ATOMIC_RELAXED) <= 1) {
78 fdev->itf->disable(fdev->closure_itf, fdev);
80 fdev->itf->unref(fdev->closure_itf);
88 int fdev_fd(const struct fdev *fdev)
93 uint32_t fdev_events(const struct fdev *fdev)
98 int fdev_repeat(const struct fdev *fdev)
103 int fdev_autoclose(const struct fdev *fdev)
105 return 1 & fdev->refcount;
108 static inline int is_active(struct fdev *fdev)
110 return fdev->repeat && fdev->callback;
113 static inline void update_activity(struct fdev *fdev, int old_active)
115 if (is_active(fdev)) {
117 fdev->itf->enable(fdev->closure_itf, fdev);
120 fdev->itf->disable(fdev->closure_itf, fdev);
124 void fdev_set_callback(struct fdev *fdev, void (*callback)(void*,uint32_t,struct fdev*), void *closure)
128 oa = is_active(fdev);
129 fdev->callback = callback;
130 fdev->closure_callback = closure;
131 update_activity(fdev, oa);
134 void fdev_set_events(struct fdev *fdev, uint32_t events)
136 if (events != fdev->events) {
137 fdev->events = events;
139 fdev->itf->update(fdev->closure_itf, fdev);
143 void fdev_set_repeat(struct fdev *fdev, int count)
147 oa = is_active(fdev);
148 fdev->repeat = count;
149 update_activity(fdev, oa);
152 void fdev_set_autoclose(struct fdev *fdev, int autoclose)
155 fdev->refcount |= (unsigned)1;
157 fdev->refcount &= ~(unsigned)1;