Milana
Milana

Reputation: 23

Deciphering a specific response from a Broadcom mobile GPS module

So far I have managed to work with the GPS module "Broadcom 4775x CSP Hub Lib ver 408635". However, the responses from the module are not standardized and it was impossible for me to decipher the responses. Perhaps I don't know much about decrypting the responses and how GPS modules work. The drivers for the module were found in the kernel kernel of the Google Pixel 6 smartphone. The module chip sends this response:

00000e40: ec 89 eb 93 cb 99 29 00 c0 c4 ff b0 01 b0 00 a5  ......).........
00000e50: 6b 00 1f 80 68 66 00 c0 c1 02 80 60 00 47 31 58  k...hf.....`.G1X
00000e60: 00 6b 91 ab 84 0b 82 4b ff 0c f7 ec 86 0b 86 6b  .k.....K.......k
00000e70: 89 ab 84 cb 05 02 19 29 9b cd 99 0e ae ae cd 2e  .......)........
00000e80: 99 8e ed 6e aa 0e df 4f b2 ce 87 cd 99 2d 81 8d  ...n...O.....-..
00000e90: 81 ed ba 0e ee 2f ba 4f 93 6d 81 8d f2 ae d3 0e  ...../.O.m......
00000ea0: 8d ce bb 6e aa 8d 91 ad b3 ce d5 2f cc 4e 8b 6d  ...n......./.N.m
00000eb0: 8e ce c5 af 9b 2e a0 ae f6 2b 00 c0 c4 37 b0 01  .........+...7..
00000ec0: b0 00 a6 b9 00 1f 80 b6 b4 00 c0 c1 02 80 ae 00  ................
00000ed0: 66 3b a5 00 cf 97 2e c8 2e e0 02 ee c1 ee ae 4e  f;.............N
00000ee0: 87 4d 9a 8d 31 32 c1 00 1f 41 4b 6d ac f0 8d 9a  .M..12...AKm....
00000ef0: cc 00 20 04 00 02 b9 26 00 01 b5 31 00 05 c5 03  .. ....&...1....
00000f00: 00 00 91 ba 00 09 2b 77 00 01 07 e3 00 10 3f 48  ......+w......?H

You can get this response from the module. The response depends on the output method.

b000be224208011e811f1d01c0c1028014017c420b01e000de000044070f030405060708090a0b140d10e003121609da000000ea000600001a007f005e0005e200000a0f000600001a00ff0061010569fffd0306080f00001a007f00f300033bfffe1f2d080500001a00ff004a01f439fffc0279060f00001a007f00f900fc29fffc00c20c0600001a007f005800fdb5fffd087f0c0200001a00ff002001efc1ffff03e5010900001a007f008b00f64c000027df010200001a00ff001e01fc0d00000190020400001a0065004300043a00000000000000001a0005000000fe08000000bd050500c0c01a00ff004800e12fffed0053060f00c0c01a00ff00e900d6ec00030085080800bf1a00ff007900183bfff30064080200c0c01a00ff001900f6e001004400c0c46db001

I noticed that every module response starts with "b0 00". And often end up "b0 XX". XX are different characters, e.g. 01, 03.:

b0 00 3a 4b 00 1f 80 48 46 00 c0 c1 02 80 40 00  ..:K...HF.....@.
2f 1a 38 00 03 ad a1 93 ff e6 f3 c1 03 47 68 b7  /.8..........Gh.
00 4a a6 a9 03 c8 72 c5 00 00 00 00 03 5e bf c1  .J....r......^..
ff b8 06 a8 02 55 84 25 ff 93 19 ba 02 37 77 d4  .....U.%.....7w.
00 62 a3 22 00 0a e0 02 aa ff fd cc eb 00 c0 c4  .b."............
06 b0 01 b0 00 3b 34 00 1f 80 31 2f 00 c0 c1 02  .....;4...1/....
80 28 00 b7 06 20 00 c0 c0 41 e0 03 05 06 0a 43  .(... ...A.....C
01 07 07 07 07 07 5a 39 03 8f 56 51 01 0f 00 00  ......Z9..VQ....
00 2a ae b5 1c 00 00 08 ed 00 c0 c4 eb b0 01     .*.............
b0 00 3a 4b 00 1f 80 48 46 00 c0 c1 02 80 40 00  ..:K...HF.....@.
2f 1a 38 00 03 ad a1 93 ff e6 f3 c1 03 47 68 b7  /.8..........Gh.
00 4a a6 a9 03 c8 72 c5 00 00 00 00 03 5e bf c1  .J....r......^..
ff b8 06 a8 
b0 00 3c f3 00 1f 80 f0 ee 00 c0 c1 02 80 e8 00
97 6f e0 00 20 00 00 00 28 1e d0 f3 00 7f d5 00
b9 f2 e8 03 0d e9 03 0e e0 04 03 0e 53 03 0e 6f
03 0e 7c 00 00 04 e0 03 00 00 51 67 5b e0 01 e0
00 e5 00 db e0 03 02 06 60 02 8a a8 5d 2f cc 53
00 fa fe ad c9 2e 8b 08 fc 93 d0 cd 00 10 99 8b
bd ea c3 69 8a c8 d7 29 b1 6a 87 cb c6 ec 92 6b
bc cb 86 aa ad 2a 95 8a bf ab 81 8b 80 6b 05 02
19 29 de 2e d4 4d d7 8d c7 ac 8a aa a4 6b 82 0d
e0 02 6d a2 6d a2 8d da 0e ba ac a9 cb bc 4c cb
4e fd 4e 92 8d bf cd 81 0d 8f 6b 99 aa 8c 4b 85
2e df ed b5 0e af 6d d7 ad 9f ec f4 ec 9a 8c 85
6e e2 ee be ee cb 0d bb 2e c8 cc e3 6b da ec ad
8e 80 6d 0b 08 b9 f2 69 75 a8 47 49 fb 09 d7 ec
00 00 00 00 0f 43 34 ff fc 8d b8 00 21 9e 18 ff
fd

Please help me decipher the answers. What algorithm should I use to decode the answers to get human-readable answers?

I've tried different ways of outputting the answers, but always get a coded result.

static ssize_t bcm_spi_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
    struct bcm_spi_priv *priv = filp->private_data;
    struct circ_buf *circ = &priv->read_buf;
    size_t rd_size = 0;

    mutex_lock(&priv->rlock);

    print_hex_dump(KERN_ERR, "bcm_gps_spi.c Circ Buffer: ", DUMP_PREFIX_NONE, 32, 1, circ->buf, BCM_SPI_READ_BUF_SIZE, true);

    /*
     * Copy from circ buffer to user
     * We may require 2 copies from [tail..end] and [end..head]
     */
    do {
        size_t cnt_to_end = CIRC_CNT_TO_END(
                circ->head, circ->tail, BCM_SPI_READ_BUF_SIZE);
        size_t copied = min(cnt_to_end, size);

        //pr_err("bcm_gps_spi.c GPSCHK copied = %zu\n", copied);

        if (copy_to_user(buf + rd_size,
                circ->buf + circ->tail, copied)){
            dev_err(&priv->spi->dev, "failed to copy to user.\n");
            mutex_unlock(&priv->rlock);
            return -EFAULT;
        }
        
print_hex_dump(KERN_ERR, "bcm_gps_spi.c Data: ", DUMP_PREFIX_NONE, 32, 1, circ->buf + circ->tail, copied, true);

        size -= copied;
        rd_size += copied;
        circ->tail = (circ->tail + copied) & (BCM_SPI_READ_BUF_SIZE-1);

    } while (size > 0 && CIRC_CNT(circ->head,
                circ->tail, BCM_SPI_READ_BUF_SIZE));
    mutex_unlock(&priv->rlock);

#ifdef DEBUG_1HZ_STAT
    bbd_update_stat(priv->bbd, STAT_RX_LHD, rd_size);
#endif

    return rd_size;
}
static ssize_t bbd_common_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
    struct bbd_device *bbd = filp->private_data;
    unsigned int minor = iminor(filp->f_path.dentry->d_inode);
    struct circ_buf *circ = &bbd->priv[minor].read_buf;
    size_t rd_size = 0;
    char temp_buf[512];
    char temp_buf2[512];
    unsigned char *data_ptr;
    size_t i; size_t log_size; char c;

    if (minor >= BBD_DEVICE_INDEX) {
        WARN_ON(minor >= BBD_DEVICE_INDEX);
        goto out;
    }

    mutex_lock(&bbd->priv[minor].lock);

    /*
     * Copy from circ buffer to lhd
     * Because lhd's buffer is linear,
     * we may require 2 copies from [tail..end] and [end..head]
     */
    do {
        size_t cnt_to_end = CIRC_CNT_TO_END(circ->head,
                circ->tail, BBD_BUFF_SIZE);
        size_t copied = min(cnt_to_end, size);
        //pr_info("bbd.c: bbd_common_read check buf: %02x \n", buf + rd_size);
        if (copy_to_user(buf + rd_size,
                (void *) circ->buf + circ->tail, copied)) {
            mutex_unlock(&bbd->priv[minor].lock);
            rd_size = -EFAULT;
            goto out;
        }

        // Logging the data in hex format
        print_hex_dump(KERN_ERR, "bbd.c GPS Data Hex: ", DUMP_PREFIX_NONE, 16, 1, circ->buf + circ->tail, copied, false);
        
        // Copy data to temp_buf for ASCII logging
        log_size = min(copied, sizeof(temp_buf) - 1);
        memcpy(temp_buf, circ->buf + circ->tail, log_size);
        temp_buf[log_size] = '\0'; // Ensure null-termination

        // Logging as ASCII - this may not be meaningful if data is in a binary format
        pr_err("bbd.c bbd_common_read GPS Data ASCII: %s\n", temp_buf);

    // Attempt to interpret the data as ASCII (for NMEA-like formats)
    for (i = 0; i < copied && i < sizeof(temp_buf) - 1; ++i) {
         c = circ->buf[circ->tail + i];
        temp_buf2[i] = (c >= 32 && c <= 126) ? c : '.'; // Replace non-printable characters with '.'
    }
    temp_buf2[i] = '\0'; // Null-terminate the string
    pr_err("bbd.c GPSCHK bbd_common_read Interpreted Data: %s\n", temp_buf2);

    data_ptr = circ->buf + circ->tail;

        size -= copied;
        rd_size += copied;
        circ->tail = (circ->tail + copied) & (BBD_BUFF_SIZE - 1);

    } while (size > 0 && CIRC_CNT(circ->head, circ->tail, BBD_BUFF_SIZE));

    mutex_unlock(&bbd->priv[minor].lock);

    bbd_log_hex(bbd->db, bbd_dev_name[minor], buf, rd_size);

#ifdef DEBUG_1HZ_STAT
    bbd_update_stat(bbd, STAT_RX_LHD, rd_size);
#endif
out:
    return rd_size;
}

There is a logging function within the drivers. But this function again does not help to decrypt the responses. It outputs the answers in the same form that I got.

static void pk_log(struct bcm_spi_priv *priv, char *dir,
        unsigned char *data, int len)
{
    const char ic = 'D';

    if (likely(!priv->bbd->ssi_dbg))
        return;

    /*
     * TODO: There is print issue. Printing 7 digits instead of 6
     * when clock is over 1000000. "% 1000000" added
     * E.g.
     * #999829D w 0x68,  1: A2
     * #999829D r 0x68, 34: 8D 00 01 52 5F B0 01 B0 00 8E 00 01 53 8B
     * B0 01 B0 00 8F 00 01 54 61 B0 01 B0 00 90 00 01 55 B5
     *          r B0 01
     * #1000001D w 0x68, 1: A1
     * #1000001D r 0x68, 1: 00
     */
    dev_info(&priv->spi->dev, "#%06ld%c %2s,\t  %5d: ",
            bcm_clock_get_ms() % 1000000, ic, dir, len);

    print_hex_dump(KERN_INFO, dir[0] == 'r' ? "r " : "w ",
            DUMP_PREFIX_NONE, 32, 1, data, len, false);
}

I thought the module was supposed to send responses in NMEA video, but most likely the module is sending responses in its own binary format.

Upvotes: 0

Views: 84

Answers (0)

Related Questions