gnss: add receiver type support

Add a "type" device attribute and a "GNSS_TYPE" uevent variable which
can be used to determine the type of a GNSS receiver. The currently
identified types reflect the protocol(s) supported by a receiver:

	"NMEA"	NMEA 0183
	"SiRF"	SiRF Binary
	"UBX"	UBX

Note that both SiRF and UBX type receivers typically support a subset of
NMEA 0183 with vendor extensions (e.g. to allow switching to the vendor
protocol).

Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Johan Hovold 2018-06-01 10:22:59 +02:00 коммит произвёл Greg Kroah-Hartman
Родитель d2efbbd18b
Коммит 10f146639f
6 изменённых файлов: 77 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,15 @@
What: /sys/class/gnss/gnssN/type
Date: May 2018
KernelVersion: 4.18
Contact: Johan Hovold <johan@kernel.org>
Description:
The GNSS receiver type. The currently identified types reflect
the protocol(s) supported by the receiver:
"NMEA" NMEA 0183
"SiRF" SiRF Binary
"UBX" UBX
Note that also non-"NMEA" type receivers typically support a
subset of NMEA 0183 with vendor extensions (e.g. to allow
switching to a vendor protocol).

Просмотреть файл

@ -6041,6 +6041,7 @@ F: include/uapi/linux/gigaset_dev.h
GNSS SUBSYSTEM GNSS SUBSYSTEM
M: Johan Hovold <johan@kernel.org> M: Johan Hovold <johan@kernel.org>
S: Maintained S: Maintained
F: Documentation/ABI/testing/sysfs-class-gnss
F: Documentation/devicetree/bindings/gnss/ F: Documentation/devicetree/bindings/gnss/
F: drivers/gnss/ F: drivers/gnss/
F: include/linux/gnss.h F: include/linux/gnss.h

Просмотреть файл

@ -330,6 +330,52 @@ int gnss_insert_raw(struct gnss_device *gdev, const unsigned char *buf,
} }
EXPORT_SYMBOL_GPL(gnss_insert_raw); EXPORT_SYMBOL_GPL(gnss_insert_raw);
static const char * const gnss_type_names[GNSS_TYPE_COUNT] = {
[GNSS_TYPE_NMEA] = "NMEA",
[GNSS_TYPE_SIRF] = "SiRF",
[GNSS_TYPE_UBX] = "UBX",
};
static const char *gnss_type_name(struct gnss_device *gdev)
{
const char *name = NULL;
if (gdev->type < GNSS_TYPE_COUNT)
name = gnss_type_names[gdev->type];
if (!name)
dev_WARN(&gdev->dev, "type name not defined\n");
return name;
}
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct gnss_device *gdev = to_gnss_device(dev);
return sprintf(buf, "%s\n", gnss_type_name(gdev));
}
static DEVICE_ATTR_RO(type);
static struct attribute *gnss_attrs[] = {
&dev_attr_type.attr,
NULL,
};
ATTRIBUTE_GROUPS(gnss);
static int gnss_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct gnss_device *gdev = to_gnss_device(dev);
int ret;
ret = add_uevent_var(env, "GNSS_TYPE=%s", gnss_type_name(gdev));
if (ret)
return ret;
return 0;
}
static int __init gnss_module_init(void) static int __init gnss_module_init(void)
{ {
int ret; int ret;
@ -347,6 +393,9 @@ static int __init gnss_module_init(void)
goto err_unregister_chrdev; goto err_unregister_chrdev;
} }
gnss_class->dev_groups = gnss_groups;
gnss_class->dev_uevent = gnss_uevent;
pr_info("GNSS driver registered with major %d\n", MAJOR(gnss_first)); pr_info("GNSS driver registered with major %d\n", MAJOR(gnss_first));
return 0; return 0;

Просмотреть файл

@ -267,6 +267,7 @@ static int sirf_probe(struct serdev_device *serdev)
if (!gdev) if (!gdev)
return -ENOMEM; return -ENOMEM;
gdev->type = GNSS_TYPE_SIRF;
gdev->ops = &sirf_gnss_ops; gdev->ops = &sirf_gnss_ops;
gnss_set_drvdata(gdev, data); gnss_set_drvdata(gdev, data);

Просмотреть файл

@ -77,6 +77,8 @@ static int ubx_probe(struct serdev_device *serdev)
gserial->ops = &ubx_gserial_ops; gserial->ops = &ubx_gserial_ops;
gserial->gdev->type = GNSS_TYPE_UBX;
data = gnss_serial_get_drvdata(gserial); data = gnss_serial_get_drvdata(gserial);
data->vcc = devm_regulator_get(&serdev->dev, "vcc"); data->vcc = devm_regulator_get(&serdev->dev, "vcc");

Просмотреть файл

@ -18,6 +18,14 @@
struct gnss_device; struct gnss_device;
enum gnss_type {
GNSS_TYPE_NMEA = 0,
GNSS_TYPE_SIRF,
GNSS_TYPE_UBX,
GNSS_TYPE_COUNT
};
struct gnss_operations { struct gnss_operations {
int (*open)(struct gnss_device *gdev); int (*open)(struct gnss_device *gdev);
void (*close)(struct gnss_device *gdev); void (*close)(struct gnss_device *gdev);
@ -30,6 +38,7 @@ struct gnss_device {
struct cdev cdev; struct cdev cdev;
int id; int id;
enum gnss_type type;
unsigned long flags; unsigned long flags;
struct rw_semaphore rwsem; struct rw_semaphore rwsem;