RTKlib/постпроцессинг

Я прочитал, что один из (совсем) немногих телефонов с поддержкой Galileo это
Huawei Mate 9. По моим сведениям он использует чип Broadcom BCM4774 и гугл гонит
“инновативную” волну по этому поводу:
http://gpsworld.com/innovation-precise-positioning-using-raw-gps-measurements-from-android-smartphones
Вcе это конечно несерьезно по сравнению с u-blox + нормальная внешняя антенна,
но хоть какая-то современная альтернанива ублоксу.
Кстати Navilock недавно анонсировал китайское изделие NL-250GG очень похожее на Tallysman
http://www.navilock.de/produkte/N_60559/merkmale.html?setLanguage=en
Вот тут
https://www.mini-itx.de/DeLock-Adapterprofi-Navigation-Antennen/Navilock-60559-Diese-Antenne-von-Navilock-empfaen::568593.html
даже цена подозрительно низкая.

Broadcom BCM4774 также установлен на (более дешевом) Huawei Honor 8.
Найти исходники ядра для всего этого китайского добра представляется делом сложным,
но простой ‘strings’ по system.img дает возможность предположить, что данные идут
по I2C, то есть имея такой телефон, можно будет отследить протокол обмена.
Также там видны следы драйвера для Bosch BMI160 (такого же, который встроен в u-blox NEO-M8U,
и вероятно в NEO-M8L).

Т.е. в лучшем случае надо будет вскрыть телефон и повеситься на шину, но какой в этом практический толк?

Ещё не выложили, но обещают прислать, возможно на CD :slight_smile:
http://consumer.huawei.com/en/support/mobile-phones/honor8_en-sup.htm
Huawei Device Co., Ltd (“Huawei”)is pleased to provide you the corresponding open source code of the device. If you want the code, please contact us with an email titled “Open Source Codes Issue” to mobile@huawei.com. Please note we may charge you the cost of physically performing source distribution like sending you a CD of the Open Source Codes, if you reqest. And the code download link will be ready soon.

Просто был у меня их планшет и к нему исходники лежали на сайте, состав не исследовал.

Это слишком брутальный подход, всегда можно по(д)смотреть что идет через FIFO.
Не исключено, что такого низкоуровневого доступа как у u-blox там не будет
(по многим причинам).
Практический толк - в написании водителя для rtklib.

Я подозреваю, что там опенсорсным будет только драйвер ядра, и поэтому толку от него =0
и придется дизассеблировать какой-нибудь монстроподобный libgps.so

Если там нет такого доступа, то я полагаю включить сырые данные не выйдет, поэтому как получиться водитель для rtklib?
А на соньке я пытался, там gps.default.so весит 20Кб, но подозреваю, что настоящий драйвер где-то заныкан ещё.

Мы точно знаем, что на BCM4773/4774 можно получить доступ к сырым данным (возможно надо прошивать определенное
фирмваре). Если для u-blox 100% понятно, что и как делать, то Broadcom это темный лес.

У нее какой чипсет ? Может там в gps.default.so кроме ретрансляции NMEA ничего и нет.

Больше интересна вот эта новость. Что это за таинственный зверь, посмотрел свои последние записи, спутников PRN125/140 не обнаружил. Хотя якобы уже чуть ли не 5 лет летают.

Они всё это время были в тестовом режиме. Приёмники их не видели т.к. не были включены в прошивки.
После официального открытия системы производители начнут их использовать. скорее всего старых чипов обновления не коснутся ((

Я в сентябре PRN140 один раз поймал. Я так понимаю их периодически включают на время тестов. Но для наших широт они низковато над горизонтом для практического применения.

ради любопытства скачал “Mate 8 OpenSource ( NXT Android 6.0,kernel,overseas) .tar.gz”
там внутри Kernel_Opensource.tar.gz лежат gps_bcm4752.c и gps_bcm47531.c в подкаталогах каталога drivers
но что в них написано - мне неведомо :slight_smile:

gps_bcm4752.c

#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/consumer.h>
#include <linux/printk.h>
#include <linux/huawei/gps/huawei_gps.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/stat.h>
#include <linux/rfkill.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/list.h>
#include <linux/version.h>
#include <linux/workqueue.h>
#include <linux/unistd.h>
#include <linux/bug.h>
#include <linux/mutex.h>
#include <linux/wakelock.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>


#ifdef CONFIG_HWCONNECTIVITY
#include <linux/huawei/hw_connectivity.h>
#endif

#define DTS_COMP_GPS_POWER_NAME "huawei,gps_power"
#define GPS_REF_CLK_FREQ_49M   (49152000L)
#define GPS_REF_CLK_FREQ_19M   (19200000L)

#define GPS_STANDBY         0
#define GPS_ACTIVE          1

#define GPS_IC_TYPE_4752 4752
#define GPS_IC_TYPE_47531 47531

#define GPS_REFCLK_SEL_ENABLE 1
#define GPS_REFCLK_SEL_DISABLE 0

extern int get_gps_ic_type();
extern int get_gps_ref_sel_enable();

typedef struct gps_bcm_info
{
    struct gpio gpioid_en;
    struct clk* clk;
    struct clk* refclk_sel;
    struct clk* refclk;
    struct pinctrl* pctrl;
    struct pinctrl_state* pins_normal;
    struct pinctrl_state* pins_idle;
} GPS_BCM_INFO;

static struct clk* gps_ref_clk = NULL;
static GPS_BCM_INFO* g_gps_bcm = NULL;

static ssize_t gps_write_proc_nstandby(struct file* filp, const char __user* buffer, size_t len, loff_t* off)
{
    char gps_nstandby = '0';
    printk(KERN_INFO "[GPS] gps_write_proc_nstandby \n");

    if ((len < 1) || (NULL == g_gps_bcm))
    {
        printk(KERN_ERR "[GPS] gps_write_proc_nstandby g_gps_bcm is NULL or read length = 0.\n");
        return -EINVAL;
    }

    if (copy_from_user(&gps_nstandby, buffer, sizeof(gps_nstandby)))
    {
        printk(KERN_ERR "[GPS] gps_write_proc_nstandby copy_from_user failed!\n");
        return -EFAULT;
    }

    if (gps_nstandby == '0')
    {
        printk(KERN_INFO "[GPS] gps nstandby.\n");
        gpio_set_value(g_gps_bcm->gpioid_en.gpio, GPS_STANDBY);
    }
    else if (gps_nstandby == '1')
    {
        printk(KERN_INFO "[GPS] gps active.\n");
        gpio_set_value(g_gps_bcm->gpioid_en.gpio, GPS_ACTIVE);
    }
    else
    {
        printk(KERN_ERR "[GPS] gps nstandby write error code[%d].\n", gps_nstandby);
    }

    return len;
}

static ssize_t gps_read_proc_nstandby(struct file* filp, const char __user* buffer, size_t len, loff_t* off)
{
    int gps_nstandby = 0;
    char tmp[2];
    memset(tmp, 0, sizeof(tmp));
    printk(KERN_INFO "[GPS] gps_read_proc_nstandby \n");
    if (len < 1 || NULL == g_gps_bcm)
    {
        printk(KERN_ERR "[GPS] gps_read_proc_nstandby g_gps_bcm is NULL or read length = 0.\n");
        return -EINVAL;
    }
    len = 1;
    printk(KERN_INFO "[GPS] gps_read_proc_nstandby off = %d\n", (unsigned int)*off);
    if ((unsigned int)*off > 0)
    {
        return 0;
    }
    gps_nstandby = gpio_get_value(g_gps_bcm->gpioid_en.gpio);
    sprintf(tmp, "%d", gps_nstandby);
    printk(KERN_INFO "[GPS] gps nstandby status[%s] \n", tmp);

    if (copy_to_user(buffer, tmp, len))
    {
        printk(KERN_ERR "[GPS] gps_read_proc_nstandby copy_to_user failed!\n");
        return -EFAULT;
    }
    *off += len;
    return len;
}

static const struct file_operations gps_proc_fops_nstandby =
{
    .owner = THIS_MODULE,
    .write = gps_write_proc_nstandby,
    .read = gps_read_proc_nstandby,
};

static int create_gps_proc_file(void)
{
    int ret = 0;
    struct proc_dir_entry* gps_dir = NULL;
    struct proc_dir_entry* gps_nstandby_file = NULL;
    gps_dir = proc_mkdir("gps", NULL);
    if (!gps_dir)
    {
        printk(KERN_ERR "[GPS] proc dir create failed\n");
        ret = -ENOMEM;
        return ret;
    }

    gps_nstandby_file = proc_create("nstandby", S_IRUGO | S_IWUSR | S_IWGRP | S_IFREG, gps_dir, &gps_proc_fops_nstandby);
    if (!gps_nstandby_file)
    {
        printk(KERN_ERR "[GPS] proc nstandby file create failed\n");
        ret = -ENOMEM;
        return ret;
    }
    printk(KERN_INFO "[GPS] gps create proc file ok. \n");

    return ret;
}

static int k3_gps_bcm_probe(struct platform_device* pdev)
{
    GPS_BCM_INFO* gps_bcm = NULL;
    struct device* gps_power_dev = &pdev->dev;
    struct device_node* np = gps_power_dev->of_node;
    enum of_gpio_flags gpio_flags;
    int ret = 0;

    printk(KERN_INFO "[GPS] start find gps_power and ic type is bcm4752 \n");
    gps_bcm = kzalloc(sizeof(GPS_BCM_INFO), GFP_KERNEL);
    if (!gps_bcm)
    {
        printk(KERN_ERR "[GPS] Alloc memory failed\n");
        return -ENOMEM;
    }

    gps_bcm->gpioid_en.gpio = of_get_gpio_by_prop(np , "huawei,gps_en" , 0 , 0 , &gpio_flags);

    if (!gpio_is_valid(gps_bcm->gpioid_en.gpio))
    {
        printk(KERN_ERR "[GPS] get huawei,gps_en gpio failed. and request again\n");
        gps_bcm->gpioid_en.gpio = of_get_named_gpio(np, "huawei,gps_en", 0);
        if(!gpio_is_valid(gps_bcm->gpioid_en.gpio))
        {
            printk(KERN_ERR "[GPS] get huawei,gps_en gpio failed.\n");
            ret = -1;
            goto err_free_gps;
        }
    }

    ret = gpio_request(gps_bcm->gpioid_en.gpio, "gps_enbale");
    if (ret)
    {
        printk(KERN_ERR "[GPS] gpio_direction_output %d failed, ret:%d\n", gps_bcm->gpioid_en.gpio, ret);
        goto err_free_gps_en;
    }
    gpio_export(gps_bcm->gpioid_en.gpio, false);
    ret = gpio_direction_output( gps_bcm->gpioid_en.gpio, 0);
    if (ret)
    {
        printk(KERN_ERR "[GPS] gpio_direction_output %d failed, ret:%d\n", gps_bcm->gpioid_en.gpio, ret);
        goto err_free_gps_en;
    }
    printk(KERN_INFO "[GPS] finish gpio_direction_output gps_power\n");

    ret = create_gps_proc_file();
    if (ret)
    {
        printk(KERN_ERR "[GPS] gps create proc file failed.\n");
        goto err_free_gps_en;
    }

    /* Set 32KC clock */
    gps_bcm->clk = of_clk_get_by_name(np, "gps_32k");
    if (IS_ERR(gps_bcm->clk))
    {
        printk(KERN_ERR "[GPS] clk_32k get failed!\n");
        ret = -1;
        goto err_free_gps_en;
    }
    ret = clk_prepare_enable(gps_bcm->clk);
    if (ret)
    {
        printk(KERN_ERR "[GPS] clk_32k enable is failed\n");
        goto err_free_clk;
    }
    printk(KERN_INFO "[GPS] clk_32k is finished\n");

    gps_bcm->pctrl = devm_pinctrl_get(gps_power_dev);
    if (IS_ERR(gps_bcm->pctrl))
    {
        printk(KERN_ERR "[GPS] pinctrl get error!\n");
        ret = -1;
        goto err_free_clk;
    }
    gps_bcm->pins_normal = pinctrl_lookup_state(gps_bcm->pctrl, "default");
    if (IS_ERR(gps_bcm->pins_normal))
    {
        printk(KERN_ERR "[GPS] gps_bcm->pins_normal lookup error!\n");
        ret = -1;
        goto err_free_pinctrl;
    }

    gps_bcm->pins_idle = pinctrl_lookup_state(gps_bcm->pctrl, "idle");
    if (IS_ERR(gps_bcm->pins_idle))
    {
        printk(KERN_ERR "[GPS] gps_bcm->pins_idle lookup error!\n");
        ret = -1;
        goto err_free_pinctrl;
    }

    ret = pinctrl_select_state(gps_bcm->pctrl, gps_bcm->pins_normal);
    if (ret)
    {
        printk(KERN_ERR "[GPS] pinctrl_select_state error!\n");
        goto err_free_pinctrl;
    }
    printk(KERN_INFO "[GPS] pinctrl is finish\n");

    /*Read dtsimage to get the ref_clk_enable properity*/

    if(GPS_REFCLK_SEL_ENABLE == get_gps_ref_sel_enable())
    {
        gps_bcm->refclk = of_clk_get_by_name(np, "ref_clk");
        if (IS_ERR(gps_bcm->refclk))
        {
            printk(KERN_ERR "[GPS] ref_clk get failed!\n");
            ret = -1;
            goto err_free_pinctrl;
        }
        gps_bcm->refclk_sel = of_clk_get_by_name(np, "ref_clk_sel");
        if (IS_ERR(gps_bcm->refclk_sel))
        {
            printk(KERN_ERR "[GPS] ref_clk_sel get failed!\n");
            ret = -1;
            goto err_free_refclk;
        }
        ret = clk_set_rate(gps_bcm->refclk_sel, GPS_REF_CLK_FREQ_49M);
        if (ret < 0)
        {
            printk(KERN_ERR "[GPS] ref_clk_sel set rate failed\n");
            ret = -1;
            goto err_free_refclk_sel;
        }
    }
    else
    {
        gps_bcm->refclk = of_clk_get_by_name(np, "clk_gps");
        if (IS_ERR(gps_bcm->refclk))
        {
            printk(KERN_ERR "[GPS] ref_clk get failed!\n");
            ret = -1;
            goto err_free_pinctrl;
        }
        ret = clk_set_rate(gps_bcm->refclk, GPS_REF_CLK_FREQ_19M);
        if (ret < 0)
        {
            printk(KERN_ERR "[GPS] ref_clk_sel set rate failed\n");
            ret = -1;
            goto err_free_refclk;
        }
    }

    gps_ref_clk = gps_bcm->refclk;
    printk(KERN_INFO "[GPS] ref clk is finished!\n");
    platform_set_drvdata(pdev, gps_bcm);
    g_gps_bcm = gps_bcm;
    return 0;

err_free_refclk_sel:
    clk_put(gps_bcm->refclk_sel);
err_free_refclk:
    clk_put(gps_bcm->refclk);
err_free_pinctrl:
    pinctrl_put(gps_bcm->pctrl);
err_free_clk:
    clk_put(gps_bcm->clk);
err_free_gps_en:
    gpio_free(gps_bcm->gpioid_en.gpio);
err_free_gps:
    kfree(gps_bcm);
    gps_bcm = NULL;
    g_gps_bcm = NULL;
    return ret;
}

static void K3_gps_bcm_shutdown(struct platform_device* pdev)
{
    GPS_BCM_INFO* gps_bcm = platform_get_drvdata(pdev);
    printk(KERN_INFO "[GPS] K3_gps_bcm_shutdown!\n");

    if (!gps_bcm)
    {
        printk(KERN_ERR "[GPS] gps_bcm is NULL,just return.\n");
        return;
    }

    platform_set_drvdata(pdev, NULL);
    kfree(gps_bcm);
    gps_bcm = NULL;
    g_gps_bcm = NULL;
    return;
}

static const struct of_device_id gps_power_match_table[] =
{
    {
        .compatible = DTS_COMP_GPS_POWER_NAME,   // compatible must match with which defined in dts
        .data = NULL,
    },
    {
    },
};

MODULE_DEVICE_TABLE(of, gps_power_match_table);

static struct platform_driver k3_gps_bcm_driver =
{
    .probe          = k3_gps_bcm_probe,
    .suspend        = NULL,
    .remove         = NULL,
    .shutdown       = K3_gps_bcm_shutdown,
    .driver = {
        .name = "huawei,gps_power_4752",
        .owner = THIS_MODULE,
        .of_match_table = of_match_ptr(gps_power_match_table), // dts required code
    },
};

static int __init k3_gps_bcm_init(void)
{
#ifdef CONFIG_HWCONNECTIVITY
    //For OneTrack, we need check it's the right chip type or not.
    //If it's not the right chip type, don't init the driver
    if (!isMyConnectivityChip(CHIP_TYPE_BCM))
    {
        printk(KERN_ERR "gps chip type is not match, skip driver init");
        return -EINVAL;
    }
    else
    {
        printk(KERN_INFO "gps chip type is matched with Broadcom, continue");
    }
#endif
    if(GPS_IC_TYPE_4752 != get_gps_ic_type())
    {
        printk(KERN_ERR "gps chip type is matched with Broadcom, and it is not 4752\n");
        return -EINVAL;
    }
    printk(KERN_INFO "gps chip type is matched with Broadcom, and it is 4752\n");
    return platform_driver_register(&k3_gps_bcm_driver);
}

static void __exit k3_gps_bcm_exit(void)
{
    platform_driver_unregister(&k3_gps_bcm_driver);
}

int set_gps_ref_clk_enable_bcm4752(bool enable)
{
    int ret = 0;

    printk(KERN_INFO "[GPS] set_gps_ref_clk_enable(%d) \n", enable);
    if (IS_ERR(gps_ref_clk))
    {
        printk(KERN_ERR "[GPS] ERROR: refclk is invalid! \n");
        return -1;
    }

    if (enable)
    {
        ret = clk_prepare_enable(gps_ref_clk);
        if (ret < 0)
        {
            printk(KERN_ERR "[GPS] ERROR: refclk enable failed! \n");
            return -1;
        }
    }
    else
    {
        clk_disable_unprepare(gps_ref_clk);
    }
    printk(KERN_INFO "[GPS] set_gps_ref_clk_enable finish \n");

    return 0;
}

module_init(k3_gps_bcm_init);
module_exit(k3_gps_bcm_exit);

MODULE_AUTHOR("DRIVER_AUTHOR");
MODULE_DESCRIPTION("GPS Boardcom 47511 driver");
MODULE_LICENSE("GPL");

Посмотрите, что находится в файле linux/huawei/gps/huawei_gps.h
и вообще linux/huawei/gps/*

Я думал что сначала будет вот эта новость

Только этот файл, huawei_gps.h

#ifndef _HUAWEI_GPS_H
#define _HUAWEI_GPS_H

#ifdef CONFIG_HWCONNECTIVITY
#include <linux/huawei/hw_connectivity.h>
#endif

#ifdef CONFIG_CONNECTIVITY_HI110X
#if 0
extern int set_gps_ref_clk_enable_hi110x(bool enable);
#else
static inline int set_gps_ref_clk_enable_hi110x(bool enable)
{
	return 0;
}
#endif
#endif


#ifdef CONFIG_BCMGPS
extern int set_gps_ref_clk_enable_bcm(bool enable);
#endif

static inline int set_gps_ref_clk_enable(bool enable)
{
    int ret = 0;
#ifdef CONFIG_HWCONNECTIVITY
    if (isMyConnectivityChip(CHIP_TYPE_HI110X )) {
        #ifdef CONFIG_CONNECTIVITY_HI110X
        printk(KERN_INFO "cfg ps type is matched with hi110x, continue\n");
        ret = set_gps_ref_clk_enable_hi110x(enable);
        #endif
    } else {
        #ifdef CONFIG_BCMGPS
        ret = set_gps_ref_clk_enable_bcm(enable);
        #endif
    }
#else 

    #ifdef CONFIG_CONNECTIVITY_HI110X
        ret = set_gps_ref_clk_enable_hi110x(enable);
    #endif

    #ifdef CONFIG_BCMGPS
            ret = set_gps_ref_clk_enable_bcm(enable);
    #endif

#endif

    return ret;
}

#endif

в drivers ещё есть gps_bcm_common.c - MODULE_DESCRIPTION(“GPS Boardcom gps common driver”);

Нее, это все неинтересно. BCM4774 - целый монстр-контроллер, который включает wifi, bt
и datafusion от всяких сенсоров, от него бы на самом деле внутреннюю прошивку поиметь неплохо,
но для этого надо покупать довольно дорогой смартфон :wink:
На ублоксовском форуме задают забавные вопросы типа
https://forum.u-blox.com/index.php?qa=7625&qa_1=about-dynseed-and-fixseed
дроны они наверное спуфить собираются :roll_eyes:

Navilock собирается “в ближайшее время” выпустить приемники серии NL-82022MP
http://www.navilock.com/produkte/N_62755/merkmale.html?setLanguage=en
на базе NEO-M8U (урезанный DeadReckoning без внешних данных wheeltick, но с акселерометром+гироскопом Bosch BMI160).
Доступа к сырым GPS данным и прошивке там конечно нет :sunglasses:

Вот нашел в китайских просторах доки по ubx-m8030.https://yadi.sk/d/zK7QM0oW3EeNhq

Неплохой вебинар про метод РРР.

Обнаружились исходники для Huawei Mate 8
https://github.com/RaindropOS/android_kernel_huawei_next
а в них drivers/huawei_platform/connectivity/bcm/gps
https://github.com/RaindropOS/android_kernel_huawei_next/tree/c44a848caac35ac4ccc454b74cde24afe0806a13/drivers/huawei_platform/connectivity/bcm/gps
Это уже теплее.

ВСMGPS на этих устройствах на последовательном порту /dev/ttyAMA3