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:
Родитель
d2efbbd18b
Коммит
10f146639f
|
@ -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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче