Lines Matching +full:gnss +full:- +full:receiver
1 // SPDX-License-Identifier: GPL-2.0
3 * GNSS receiver core
13 #include <linux/gnss.h>
41 gdev = container_of(inode->i_cdev, struct gnss_device, cdev); in gnss_open()
43 get_device(&gdev->dev); in gnss_open()
46 file->private_data = gdev; in gnss_open()
48 down_write(&gdev->rwsem); in gnss_open()
49 if (gdev->disconnected) { in gnss_open()
50 ret = -ENODEV; in gnss_open()
54 if (gdev->count++ == 0) { in gnss_open()
55 ret = gdev->ops->open(gdev); in gnss_open()
57 gdev->count--; in gnss_open()
60 up_write(&gdev->rwsem); in gnss_open()
63 put_device(&gdev->dev); in gnss_open()
70 struct gnss_device *gdev = file->private_data; in gnss_release()
72 down_write(&gdev->rwsem); in gnss_release()
73 if (gdev->disconnected) in gnss_release()
76 if (--gdev->count == 0) { in gnss_release()
77 gdev->ops->close(gdev); in gnss_release()
78 kfifo_reset(&gdev->read_fifo); in gnss_release()
81 up_write(&gdev->rwsem); in gnss_release()
83 put_device(&gdev->dev); in gnss_release()
91 struct gnss_device *gdev = file->private_data; in gnss_read()
95 mutex_lock(&gdev->read_mutex); in gnss_read()
96 while (kfifo_is_empty(&gdev->read_fifo)) { in gnss_read()
97 mutex_unlock(&gdev->read_mutex); in gnss_read()
99 if (gdev->disconnected) in gnss_read()
102 if (file->f_flags & O_NONBLOCK) in gnss_read()
103 return -EAGAIN; in gnss_read()
105 ret = wait_event_interruptible(gdev->read_queue, in gnss_read()
106 gdev->disconnected || in gnss_read()
107 !kfifo_is_empty(&gdev->read_fifo)); in gnss_read()
109 return -ERESTARTSYS; in gnss_read()
111 mutex_lock(&gdev->read_mutex); in gnss_read()
114 ret = kfifo_to_user(&gdev->read_fifo, buf, count, &copied); in gnss_read()
118 mutex_unlock(&gdev->read_mutex); in gnss_read()
126 struct gnss_device *gdev = file->private_data; in gnss_write()
130 if (gdev->disconnected) in gnss_write()
131 return -EIO; in gnss_write()
136 if (!(gdev->flags & GNSS_FLAG_HAS_WRITE_RAW)) in gnss_write()
137 return -EIO; in gnss_write()
141 ret = mutex_lock_interruptible(&gdev->write_mutex); in gnss_write()
143 return -ERESTARTSYS; in gnss_write()
146 size_t n = count - written; in gnss_write()
151 if (copy_from_user(gdev->write_buf, buf, n)) { in gnss_write()
152 ret = -EFAULT; in gnss_write()
162 down_read(&gdev->rwsem); in gnss_write()
163 if (!gdev->disconnected) in gnss_write()
164 ret = gdev->ops->write_raw(gdev, gdev->write_buf, n); in gnss_write()
166 ret = -EIO; in gnss_write()
167 up_read(&gdev->rwsem); in gnss_write()
182 mutex_unlock(&gdev->write_mutex); in gnss_write()
189 struct gnss_device *gdev = file->private_data; in gnss_poll()
192 poll_wait(file, &gdev->read_queue, wait); in gnss_poll()
194 if (!kfifo_is_empty(&gdev->read_fifo)) in gnss_poll()
196 if (gdev->disconnected) in gnss_poll()
217 kfree(gdev->write_buf); in gnss_device_release()
218 kfifo_free(&gdev->read_fifo); in gnss_device_release()
219 ida_free(&gnss_minors, gdev->id); in gnss_device_release()
234 id = ida_alloc_max(&gnss_minors, GNSS_MINORS - 1, GFP_KERNEL); in gnss_allocate_device()
240 gdev->id = id; in gnss_allocate_device()
242 dev = &gdev->dev; in gnss_allocate_device()
244 dev->devt = gnss_first + id; in gnss_allocate_device()
245 dev->class = gnss_class; in gnss_allocate_device()
246 dev->parent = parent; in gnss_allocate_device()
247 dev->release = gnss_device_release; in gnss_allocate_device()
249 dev_set_name(dev, "gnss%d", id); in gnss_allocate_device()
251 init_rwsem(&gdev->rwsem); in gnss_allocate_device()
252 mutex_init(&gdev->read_mutex); in gnss_allocate_device()
253 mutex_init(&gdev->write_mutex); in gnss_allocate_device()
254 init_waitqueue_head(&gdev->read_queue); in gnss_allocate_device()
256 ret = kfifo_alloc(&gdev->read_fifo, GNSS_READ_FIFO_SIZE, GFP_KERNEL); in gnss_allocate_device()
260 gdev->write_buf = kzalloc(GNSS_WRITE_BUF_SIZE, GFP_KERNEL); in gnss_allocate_device()
261 if (!gdev->write_buf) in gnss_allocate_device()
264 cdev_init(&gdev->cdev, &gnss_fops); in gnss_allocate_device()
265 gdev->cdev.owner = THIS_MODULE; in gnss_allocate_device()
278 put_device(&gdev->dev); in gnss_put_device()
287 if (gdev->ops->write_raw != NULL) in gnss_register_device()
288 gdev->flags |= GNSS_FLAG_HAS_WRITE_RAW; in gnss_register_device()
290 ret = cdev_device_add(&gdev->cdev, &gdev->dev); in gnss_register_device()
292 dev_err(&gdev->dev, "failed to add device: %d\n", ret); in gnss_register_device()
302 down_write(&gdev->rwsem); in gnss_deregister_device()
303 gdev->disconnected = true; in gnss_deregister_device()
304 if (gdev->count) { in gnss_deregister_device()
305 wake_up_interruptible(&gdev->read_queue); in gnss_deregister_device()
306 gdev->ops->close(gdev); in gnss_deregister_device()
308 up_write(&gdev->rwsem); in gnss_deregister_device()
310 cdev_device_del(&gdev->cdev, &gdev->dev); in gnss_deregister_device()
324 ret = kfifo_in(&gdev->read_fifo, buf, count); in gnss_insert_raw()
326 wake_up_interruptible(&gdev->read_queue); in gnss_insert_raw()
343 if (gdev->type < GNSS_TYPE_COUNT) in gnss_type_name()
344 name = gnss_type_names[gdev->type]; in gnss_type_name()
347 dev_WARN(&gdev->dev, "type name not defined\n"); in gnss_type_name()
365 ATTRIBUTE_GROUPS(gnss);
383 ret = alloc_chrdev_region(&gnss_first, 0, GNSS_MINORS, "gnss"); in gnss_module_init()
389 gnss_class = class_create("gnss"); in gnss_module_init()
396 gnss_class->dev_groups = gnss_groups; in gnss_module_init()
397 gnss_class->dev_uevent = gnss_uevent; in gnss_module_init()
399 pr_info("GNSS driver registered with major %d\n", MAJOR(gnss_first)); in gnss_module_init()
419 MODULE_DESCRIPTION("GNSS receiver core");