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);
79 fdev->itf->unref(fdev->closure_itf);
87 int fdev_fd(const struct fdev *fdev)
92 uint32_t fdev_events(const struct fdev *fdev)
97 int fdev_repeat(const struct fdev *fdev)
102 int fdev_autoclose(const struct fdev *fdev)
104 return 1 & fdev->refcount;
107 static inline int is_active(struct fdev *fdev)
109 return fdev->repeat && fdev->callback;
112 static inline void update_activity(struct fdev *fdev, int old_active)
114 if (is_active(fdev)) {
116 fdev->itf->enable(fdev->closure_itf, fdev);
119 fdev->itf->disable(fdev->closure_itf, fdev);
123 void fdev_set_callback(struct fdev *fdev, void (*callback)(void*,uint32_t,struct fdev*), void *closure)
127 oa = is_active(fdev);
128 fdev->callback = callback;
129 fdev->closure_callback = closure;
130 update_activity(fdev, oa);
133 void fdev_set_events(struct fdev *fdev, uint32_t events)
135 if (events != fdev->events) {
136 fdev->events = events;
138 fdev->itf->enable(fdev->closure_itf, fdev);
142 void fdev_set_repeat(struct fdev *fdev, int count)
146 oa = is_active(fdev);
147 fdev->repeat = count;
148 update_activity(fdev, oa);
151 void fdev_set_autoclose(struct fdev *fdev, int autoclose)
154 fdev->refcount |= (unsigned)1;
156 fdev->refcount &= ~(unsigned)1;