Full Code of fpv-wtf/msp-osd for AI

main ef9d906cf43a cached
80 files
859.0 KB
242.7k tokens
1612 symbols
1 requests
Download .txt
Showing preview only (893K chars total). Download the full file or copy to clipboard to get everything.
Repository: fpv-wtf/msp-osd
Branch: main
Commit: ef9d906cf43a
Files: 80
Total size: 859.0 KB

Directory structure:
gitextract_wyjnxqch/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── FAKEHD.md
├── LICENSE
├── Makefile.dji
├── Makefile.unix
├── README.md
├── config/
│   ├── airunit/
│   │   ├── config.json
│   │   ├── schema.json
│   │   ├── schemaV2.json
│   │   └── uiSchemaV2.json
│   └── goggles/
│       ├── config.json
│       ├── schema.json
│       ├── schemaV2.json
│       └── uiSchemaV2.json
├── docs/
│   └── fonts/
│       └── gen.sh
├── ipk/
│   ├── airunit/
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   └── data/
│   │       └── opt/
│   │           ├── bin/
│   │           │   └── airunit-osd-start.sh
│   │           └── etc/
│   │               └── dinit.d/
│   │                   └── msp-osd-airside
│   └── goggle/
│       ├── control/
│       │   ├── conffiles
│       │   ├── control
│       │   ├── postinst
│       │   ├── preinst
│       │   └── prerm
│       └── data/
│           └── opt/
│               └── etc/
│                   └── dinit.d/
│                       └── msp-osd-goggles
├── jni/
│   ├── Android.mk
│   ├── Application.mk
│   ├── displayport_osd_shim.c
│   ├── fakehd/
│   │   ├── fakehd.c
│   │   └── fakehd.h
│   ├── font/
│   │   ├── font.c
│   │   └── font.h
│   ├── hw/
│   │   ├── dji_display.c
│   │   ├── dji_display.h
│   │   ├── dji_radio_shm.c
│   │   ├── dji_radio_shm.h
│   │   ├── dji_services.c
│   │   ├── dji_services.h
│   │   └── duml_hal.h
│   ├── json/
│   │   ├── osd_config.c
│   │   ├── osd_config.h
│   │   ├── parson.c
│   │   └── parson.h
│   ├── libspng/
│   │   ├── spng.c
│   │   └── spng.h
│   ├── lz4/
│   │   ├── lz4.c
│   │   └── lz4.h
│   ├── msp/
│   │   ├── msp.c
│   │   ├── msp.h
│   │   ├── msp_displayport.c
│   │   └── msp_displayport.h
│   ├── msp_displayport_mux.c
│   ├── net/
│   │   ├── data_protocol.h
│   │   ├── network.c
│   │   ├── network.h
│   │   ├── serial.c
│   │   └── serial.h
│   ├── osd.h
│   ├── osd_dji_overlay_udp.c
│   ├── osd_dji_udp.c
│   ├── osd_sfml_udp.c
│   ├── rec/
│   │   ├── rec.c
│   │   ├── rec.h
│   │   ├── rec_pb.c
│   │   ├── rec_pb.h
│   │   ├── rec_shim.c
│   │   ├── rec_shim.h
│   │   ├── rec_util.c
│   │   └── rec_util.h
│   ├── toast/
│   │   ├── toast.c
│   │   └── toast.h
│   └── util/
│       ├── debug.h
│       ├── display_info.h
│       ├── fs_util.c
│       ├── fs_util.h
│       └── time_util.h
└── libshims/
    └── duml_hal.c

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/build.yml
================================================
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main ]
    tags:
      - '*'

#  pull_request:
#    branches: [ main ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  release:
    name: Create new releas and attach IPKs
    runs-on: ubuntu-latest
    permissions:
      contents: write
    needs: build
    steps:
      - name: Branch name
        id: branch_name
        run: |
          echo ::set-output name=IS_TAG::${{ startsWith(github.ref, 'refs/tags/') }}
          echo ::set-output name=SOURCE_TAG::${GITHUB_REF#refs/tags/}
          echo ::set-output name=RELEASE_VERSION::${GITHUB_REF#refs/*/}

      - name: Download artifact
        env:
            IS_TAG: ${{ steps.branch_name.outputs.IS_TAG }}
            SOURCE_TAG: ${{ steps.branch_name.outputs.SOURCE_TAG }}
        if: "${{ env.IS_TAG == 'true' }}"
        uses: actions/download-artifact@v4
        with:
          name: ${{ env.ARTIFACT_NAME }}

      - name: View content
        env:
            IS_TAG: ${{ steps.branch_name.outputs.IS_TAG }}
            SOURCE_TAG: ${{ steps.branch_name.outputs.SOURCE_TAG }}
        if: "${{ env.IS_TAG == 'true' }}"
        run: ls -R

      - name: Create tagged release
        id: create_release
        env:
            IS_TAG: ${{ steps.branch_name.outputs.IS_TAG }}
            SOURCE_TAG: ${{ steps.branch_name.outputs.SOURCE_TAG }}
        if: "${{ env.IS_TAG == 'true' }}"
        uses: ncipollo/release-action@v1
        with:
          tag: ${{ env.SOURCE_TAG }}
          name: ${{ env.SOURCE_TAG }}
          token: ${{ secrets.GITHUB_TOKEN }}
          prerelease: false
          artifacts: "./*/*.ipk"

  build:
    name: Build .ipk packages
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v2

      - name: Get GitHub Build Number (ENV)
        id: get_buildno
        run: echo "GITHUBBUILDNUMBER=${{ github.run_number }}" >> $GITHUB_ENV
        continue-on-error: true

      - name: Get repository name
        run: echo "REPOSITORY_NAME=$(echo '${{ github.repository }}' | cut -d '/' -f2)" >> $GITHUB_ENV
        shell: bash

      - name: Make artifact name
        id: make_artifactname
        run: |
          ARTIFACT_NAME="${{ env.REPOSITORY_NAME }}-${{ github.run_number }}"
          echo "${ARTIFACT_NAME}"
          echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV

      - uses: nttld/setup-ndk@v1
        id: setup-ndk
        with:
          ndk-version: r23b

      - name: Build .ipk
        env:
          ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
        run: |
          export PATH=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/:$PATH
          make ipk

      - name: Upload release artifacts
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.ARTIFACT_NAME }}
          path: |
            ./ipk/*.ipk


================================================
FILE: .gitignore
================================================
*.o
osd_dji
msp_displayport_mux
ipk/goggle/build
ipk/airunit/build
*.ipk
repo
obj
libs

================================================
FILE: FAKEHD.md
================================================
# FakeHD

Betaflight's (before 4.4) OSD supports a 30 * 16 Grid, which looks large/blocky when displayed in the DJI Goggles.

For versions of Betaflight before 4.4 (or other FC firmwares without HD support), as a workaround, we have a mode called "FakeHD". It chops up the OSD into sections and positions them evenly around an HD grid (with gaps between) - the way this is done is configurable, explained below. This then allows the use of smaller fonts - so it looks nicer/more in keeping with the built in Goggles OSD (but you still only have 30 columns / 16 rows to configure.... and you have the gaps to contend with).

A diagram to help...

| Before (in Configurator)                               | After (in Goggles)                                  |
| ------------------------------------------------------ | --------------------------------------------------- |
| ![FakeHD Before](/docs/img/fakehd_before.png "Before") | ![FakeHD After](/docs/img/fakehd_after.png "After") |

##### To configure/enable:

Visit https://fpv.wtf/package/fpv-wtf/msp-osd with your goggles connected, and check "Fake HD"

Optionally, place custom fonts in the root of your sd card, using the names `font_bf_hd.png`

Configuration of the grid is also possible; see below.

No air unit/vista config is required.

##### Menu Switching - Getting rid of gaps when displaying Menu / Post Flight Stats + displaying centered:

In order to have menus (accessible in Betaflight using stick commands) and post-flight stats appear in the center of the screen while using FakeHD, rather than having gaps + looking broken, you should set up menu switching.

FakeHD can use the presence/absence of a character in the OSD as a switch to indicate when you are in regular OSD mode or in the menu/stats and switch to centering temporarily when needed.

By default, the `Throttle Position` icon is used (character 4) - but you can set any character you want. It needs to be something that doesn't flash or change in the regular OSD, and ideally (but not essential) something that is never in the menu/post flight stats. The icons next to various elements are obvious choices here. You can set this using the `fakehd_menu_switch` configuration parameter.

Betaflight has a list here: https://github.com/betaflight/betaflight/blob/master/docs/osd.md


If you want to use FakeHD with some other Flight Controller, you will need to find an appropriate icon. (Let us know - we can include the information here).

Finally, if you don't have anything in your OSD that works for menu switching, you can hide the menu switching character and the subsequent 5 characters, allowing you to add the `Throttle Position` element but not have to see it on screen. This is enabled by setting `fakehd_hide_menu_switch` to true.

Notes:

 - Because of this switching feature, if you change to a different quad or OSD config (specifically the switch element is in a different place), FakeHD will center - you will need to reboot your Goggles to get it to recognise the switch element in a different location.

 - Also because of this switching, if you are editing OSD in the configurator with the goggles on to preview and you move the switching element around, it will cause the gaps to be disabled and everything to center. The new location of the switching element will be found next time you reboot the goggles and it'll work as normal.

##### I don't want gaps at all...

Set config `fakehd_lock_center` to true and the center locking used for the menu / post flight stats will be enabled permanently (ie: you fly with it as well) - basically it places your 30 x 16 SD grid into the middle of an HD grid, there's never any gaps - see diagram below + compare to diagrams above.

| After/Centered (in Goggles) `fakehd_lock_center`                               |
| ------------------------------------------------------------------------------ |
| <img src="/docs/img/fakehd_centered.png" alt="After / Centered"  height=200 /> |

##### Customising the default FakeHD grid.

By default, FakeHD positions your SD grid into the HD grid as per the before/after diagram above.

If this doesn't work for you for whatever reason, some customisation is available. It's necessarily a little complicated.

Each row can be set to one of:

| Code | Description                                                                                                                    |
| ---- | ------------------------------------------------------------------------------------------------------------------------------ |
| L    | Left aligned, the SD row occupies cell 1-30, no gaps                                                                           |
| C    | Center aligned, the SD row occupies cell 16-45, no gaps                                                                        |
| R    | Right aligned, , the SD row occupies cell 31-60, no gaps                                                                       |
| W    | Split A - Row is split in 3, the FakeHD default, filling cells 1-10, 26-35, 51-60                                              |
| T    | Split B - Row is split in 2, touching the sides - filling cells 1-15 + 46-60                                                   |
| F    | Split C - Row is split in 2 and away from the sides - filling cells 11-25 + 36-50                                              |
| D    | DJI Special - Row is centered but pushed a little left; used to posiution the bottom row between the existing DJI OSD elements |

<img src="/docs/img/fakehd_rows.png" alt="Columns"  height=200 />

And then the columns as a whole can be set to one of:

| Code | Description                                                                 |
| ---- | --------------------------------------------------------------------------- |
| T    | Top aligned, OSD occupies rows 1-16                                         |
| M    | Center aligned, OSD occupies cells 4-19, no gaps                            |
| B    | Bottom aligned, , the OSD occupies rows 7-22                                |
| S    | Split - FakeHD default - split in 3, OSD occupies rows 1 - 5, 9 - 13, 17-22 |

Using the default row config; here's what they all look like:

| T                                                    | M                                                    | B                                                    | S                                                |
| ---------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------- | ------------------------------------------------ |
| <img src="/docs/img/fakehd_columns_t.png" alt="T" /> | <img src="/docs/img/fakehd_columns_m.png" alt="M" /> | <img src="/docs/img/fakehd_columns_b.png" alt="B" /> | <img src="/docs/img/fakehd_after.png" alt="S" /> |

###### To configure rows

Rows config accepts a 16 character long string; each character configuring it's corresponding row. The default FakeHD config would be set like this:

`fakehd_rows = WWWWWWCCWWWWWWWD`

The characters are case sensitive, but the configurator will reject invalid characters.

###### To configure columns

Columns accepts a single character configuring how the whole grid is aligned. The default would be set like this:

`fakehd_columns = S`

The characters are case sensitive, but the configurator will reject invalid characters.



================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: Makefile.dji
================================================
CC=armv7a-linux-androideabi19-clang
CFLAGS=-I. -O2
LIB_SHIMS = libshims/libduml_hal.so

.PHONY: repo

%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

#this doesn't work by default
#an extra duss_result_t(frame_pop_handler)
#is generated that the compiler doesn't like
libshims/%.c: %.h
	stubgen -g -e .c -l -N -t libshims -p "../" -n $<

libshims/lib%.so: libshims/%.c
	$(CC) -Wno-c2x-extensions -O2 -shared -Wl,-soname,libduml_hal.so -o $@ $< $(CFLAGS)

libshims: $(LIB_SHIMS)

all: jni/*
	ndk-build

install: all
	install -d ipk/goggle/build/data/opt/fonts/
	install fonts/*.png ipk/goggle/build/data/opt/fonts/
	install -d ipk/goggle/build/data/opt/mspdictionaries/
	install dictionaries/*.bin ipk/goggle/build/data/opt/mspdictionaries/
	install -d ipk/goggle/build/data/opt/etc/preload.d/
	install libs/armeabi-v7a/libdisplayport_osd_shim.so ipk/goggle/build/data/opt/etc/preload.d/
	install -d ipk/airunit/build/data/opt/bin/
	install libs/armeabi-v7a/msp_displayport_mux ipk/airunit/build/data/opt/bin/
	install -d ipk/airunit/build/data/opt/mspdictionaries/
	install dictionaries/*.bin ipk/airunit/build/data/opt/mspdictionaries/
	install -d ipk/airunit/build/data/opt/etc/package-config/msp-osd/
	install config/airunit/* ipk/airunit/build/data/opt/etc/package-config/msp-osd/
	install -d ipk/goggle/build/data/opt/etc/package-config/msp-osd/
	install config/goggles/* ipk/goggle/build/data/opt/etc/package-config/msp-osd/

goggle_ipk: install
	$(eval PKG_NAME := $(shell cat ./ipk/goggle/control/control | grep Package | cut -d" " -f2))
	$(eval ARCH := $(shell cat ./ipk/goggle/control/control | grep Architecture | cut -d" " -f2))
	$(eval VERSION :=$(shell cat ./ipk/goggle/control/control | grep Version | cut -d" " -f2))
	$(eval IPK_NAME := "${PKG_NAME}_${VERSION}_${ARCH}.ipk")
	cp -r ipk/goggle/data ipk/goggle/build/
	echo "2.0" > ipk/goggle/build/debian-binary
	cp -r ipk/goggle/control ipk/goggle/build/
	cd ipk/goggle/build/control && tar czvf ../control.tar.gz .
	cd ipk/goggle/build/data && tar czvf ../data.tar.gz .
	cd ipk/goggle/build && tar czvf "../../${IPK_NAME}" ./control.tar.gz ./data.tar.gz ./debian-binary

airunit_ipk: install
	$(eval PKG_NAME := $(shell cat ./ipk/airunit/control/control | grep Package | cut -d" " -f2))
	$(eval ARCH := $(shell cat ./ipk/airunit/control/control | grep Architecture | cut -d" " -f2))
	$(eval VERSION :=$(shell cat ./ipk/airunit/control/control | grep Version | cut -d" " -f2))
	$(eval IPK_NAME := "${PKG_NAME}_${VERSION}_${ARCH}.ipk")
	mkdir -p ipk/airunit/build
	echo "2.0" > ipk/airunit/build/debian-binary
	cp -r ipk/airunit/data ipk/airunit/build/
	cp -r ipk/airunit/control ipk/airunit/build/
	cd ipk/airunit/build/control && tar czvf ../control.tar.gz .
	cd ipk/airunit/build/data && tar czvf ../data.tar.gz .
	cd ipk/airunit/build && tar czvf "../../${IPK_NAME}" ./control.tar.gz ./data.tar.gz ./debian-binary

ipk: install goggle_ipk airunit_ipk

repo: ipk
	mkdir -p repo
	cp ipk/*.ipk repo/
	../opkg-utils-0.5.0/opkg-make-index ./repo/ > repo/Packages
	http-server -p 8042 ./repo/

clean:
	rm -rf **/*.o
	rm -rf *.o
	rm -rf repo
	rm -rf libshims/*.so
	rm -rf msp_displayport_mux
	rm -rf osd_dji
	rm -rf ipk/goggle/build
	rm -rf ipk/airunit/build
	rm -rf ipk/*.ipk
	rm -rf obj
	rm -rf libs


================================================
FILE: Makefile.unix
================================================
CC=gcc
CFLAGS=-I. -O2
SRCDIR = jni/
DEPS = $(addprefix $(SRCDIR), msp/msp.h msp/msp_displayport.h net/network.h net/serial.h)
OSD_OBJ = $(addprefix $(SRCDIR), osd_sfml_udp.o net/network.o msp/msp.o msp/msp_displayport.o)
DISPLAYPORT_MUX_OBJ = $(addprefix $(SRCDIR), msp_displayport_mux.o net/serial.o net/network.o msp/msp.o)
OSD_LIBS=-lcsfml-graphics

%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

osd_sfml: $(OSD_OBJ)
	$(CC) -o $@ $^ $(CFLAGS) $(OSD_LIBS)

msp_displayport_mux: $(DISPLAYPORT_MUX_OBJ)
	$(CC) -o $@ $^ $(CFLAGS)

clean: 
	rm -rf *.o
	rm -rf **/*.o
	rm -f msp_displayport_mux
	rm -f osd_sfml


================================================
FILE: README.md
================================================
# IMPORTANT
As of msp-osd v0.12+, the required font format has now changed for the goggles and the OSD Overlay tool.  Support for .bin font file format has been removed in favour of .png font file format.
See the 'Fonts' section and the 'Overlaying OSD on DVR' sections further below for clarification.

# MSP-OSD - Full OSD / Displayport OSD

This package gives you support for full flight controller driven OSD in line with those on analog + other HD systems.

Technically - it takes MSP DisplayPort (so-called "canvas" although this is a misnomer as there is another Betaflight "canvas" mode for Pixel OSDs) messages through UDP and renders them to a framebuffer overlaid under the DJI 'dji_glasses' menu system.

SFML (PC/Mac development) and DJI Goggles viewports are available, as well as a *mux* for the Air Unit / Vista, which creates a *pty* and provides filtered MSP access, and reroutes DisplayPort messages to UDP.

# Setup and Installation

## Easy Installation

* Install WTFOS from https://fpv.wtf. WTFOS must be installed on both the goggles and each AU/Vista.
* Install the msp-osd package on each device using WTFOS.
* Reboot.

## Flight Controller Setup

* Ensure that the correct UART is set to use MSP
* Enable MSP DisplayPort

### Betaflight - Since 4.5

Betaflight 4.5 has added support for coloured warning messages/OSD elements.
This added feature requires a Betaflight font that includes the extra colour elements.  The extra colour elements are for green, amber and red indicators and respectively reside in additional font pages.
This means that to support the extra 3 colours, a 4 page font file is required.

MSP-OSD 0.12+ now supports this feature and includes the required 4 page coloured font for Betaflight bundled by default.
A Betaflight CLI command may needed to take advantage of the this feature:

`set displayport_msp_fonts = 0,1,2,3`

This tells Betaflight to use a specific [colour] page when displaying the warning.

##### *Important*
If you are **not** using a Betaflight 4 page font, and this value is set to `0,1,2,3`, some OSD elements may not display.  In this case, set the value to `0,0,0,0`.  Meaning every warning will use the first page of the font.

### Betaflight - Since 4.4

Betaflight 4.4 has added native support for OSD in HD aspect ratio.

#### Configure With Preset

There is a preset available: "OSD for Fpv.wtf, DJI O3, Avatar HD", once applied you can then skip ahead to configuring in the OSD tab.

#### Configure Manually

Or to configure manually, first enter the following commands in the CLI tab:

```
set osd_displayport_device = MSP
set vcd_video_system = HD
save
```

And then in the Ports tab, select the peripheral "VTX (MSP + DisplayPort)" for the UART your Vista/Air unit is connected to.

![Ports Tab Setting](/docs/img/ports-vtx.png)

Afterwards, you can configure the OSD elements as normal in the OSD tab.

#### Troubleshooting wrong grid size in BF 4.4 Configurator

It is recommended to enable [compressed transmission](#compressed-transmission) with BF 4.4; (now default). It removes/avoids ordering issues between FC/AU/Goggles bootup - the AU has to tell the FC the grid size it supports.

If you don't want to / can't do this - try rebooting your goggles, then reboot your AU.

### Betaflight - 4.3 or Before

We have a configurator preset available - "FPV.WTF MSP-OSD", just be sure to pick the UART your Vista/Air unit is connected to.

#### Or to configure manually

On *Betaflight*, this is done using the following commands in the CLI tab:

```
set osd_displayport_device = MSP
set displayport_msp_serial = <ConfiguratorUART - 1>
set vcd_video_system = PAL
save
```

Eg.: If the Betaflight Configurator says your DJI VTx is attached to UART2, the value for **<ConfiguratorUART - 1>** is **1** - so you would use ```set displayport_msp_serial = 1```.
Test if the value is correct by typing `save` and after the reboot `get displayport_msp_serial` This command should return the value you set it to. If it returns -1 (and that was not the value you set) then the value was not correct.

For Betaflight - ensure you set the Video Format to PAL or Auto in the OSD tab - otherwise you don't get access to the whole OSD area. Note that currently BF Configurator hides these options once you switch to MSP for OSD; the last command above should have done this for you.

#### Softserial

We don't recommend connecting via soft serial; results have been poor - it gives slow/laggy/inconsistent behaviour. But some users have reported it being usable, so if for whatever reason this is your only option, read on.

If you have connected the Vista/Airunit to a softserial port run the `serial` command to list serial ports
Use the value after _serial_ with set `displayport_msp_serial` but do **not** subtract 1 from the value. E.g.:
```
# serial
serial 20 1 115200 57600 0 115200
serial 0 64 115200 57600 0 115200
serial 1 0 115200 57600 0 115200
serial 30 1 115200 57600 0 115200
# set displayport_msp_serial = 30
```

#### FakeHD
With the introduction of HD FPV and its associated transmission and display resolutions, a significantly larger area (canvas*) became a possibility to use for flight controller OSD informaton.
The first generation of the DJI FPV system supports a display resolution of 810p (1440px width x 810px height).  This allowed for a potential for a 60 * 22 grid of (mono-spaced) characters of OSD.
Prior to Betaflight(BF) 4.4, the BF OSD supported a 30 * 16 Grid, which looks large/blocky when displayed in the DJI Goggles.  This 30 * 16 grid was due to the analogue roots of the video and OSD system.

To present the OSD in a visually better way on HD FPV systems, MSP-OSD introduced a workaround called FakeHD that divided up the OSD canvas area into sections that could be configured.

[FakeHD information is available here.](FAKEHD.md)

### INAV

Select "MSP Display Port" (or "HDZero VTx" on older INAV versions) as the Peripheral. Next, select "HD" (or the "WTFOS" variant) in the OSD tab if you'd like to use the HD Canvas.

If the iNav OSD appears garbled at first, try entering the iNav menus using the RC sticks, and then exiting the menus. This will force INAV to switch into HD mode a second time.

It is recommended (now enabled by default in recent msp-osd releases) to enable [compressed transmission](#compressed-transmission) with INAV to avoid issues with the display corrupting - the artifical horizon is the most common element to show this.

### Ardupilot

Please install a recent Ardupilot version for full functionality. There was one critical bug fix for MSP telemetry not passing through a DisplayPort serial port. Additionally, there were several feature additions including HD support after the last 4.2 release.

Settings:

```
SERIALx_PROTOCOL = 42
OSD_TYPE = 5
```

Recent versions of MSP-OSD fully support Ardupilot with a specific HD FPV font.  This font is bundled with msp-osd 0.12
If you wish to use a Betaflight font instead of an Ardupilot font, you can also set `MSP_OPTIONS = 4` to allow the use of a Betaflight font.

More info: https://ardupilot.org/plane/docs/common-msp-osd-overview-4.2.html#dji-goggles-with-wtf-osd-firmware

### KISS Ultra

Select MSP on serial and select DJI WTF as canvas dialect. That's it.

### QUICKSILVER

Configure the UART under Digital VTX - see https://docs.bosshobby.com/Configuring-Quicksilver/#setup

# Fonts

We bundle in default fonts for Betaflight, Ardupilot, INAV, Quicksilver, and KISS ULTRA (INAV/Betaflight/Ardupilot fonts are SNEAKY_FPV's Unify Europa design - thanks to SNEAKYFPV for allowing us to use these - https://sites.google.com/view/sneaky-fpv/home). Since 0.12 we now use a PNG font format, the same as Walksnail. [Default fonts can be viewed here](fonts). You may also upload your own fonts to the SD card.

For the naming convention of the font file in png format see the *FC Specific Font File Names* section below.

***It is important to note the following in regards to when a font file is used from where***

When the goggles determines what font file to use in presenting the OSD, it will look in the following 3 different locations in preferential order:
1. SD Card (root) `/storage/sdcard0`
2. Goggles user font location `/blackbox` (see the *Moving fonts to the goggles file system* section below)
3. Goggles bundled fallback location `/blackbox/wtfos/opt/fonts`

### HD vs SD fonts

Due to historical support for FC firmware that did not have the full HD canvas grid size, both SD and HD font files are bundled.
SD font file/s (naming without the suffix *_hd*) are used when the FC configuration is not set to, or does not support, HD. i.e. BF 4.3 and below.
HD font file/s are used with most modern FC firmware when the equivalent HD selection is made in the FC's OSD configuration tab.

##### *Note*
You do not need to use/copy/install the non-hd font file if you only use a HD OSD canvas.

### Attaining/using fonts
* Download a font package. See below for known community fonts.
* Place these two PNG files on the root of your Goggles SD card.
* Insert the SD card and reboot the goggles.

### Using Walksnail Fonts
As of msp-osd 0.12, the format of font files are now compatible with Walksnail fonts, with the following caveats.

For INAV specific Walksnail fonts, the format of the font pages matter as historical fonts typically were formatted with pages stacked vertically.  The new requirement is for the pages to be stacked side by side. The newer format of side by side pages is supported by both msp-osd and Walksnail.  Side by Side specifially formatted Walksnail fonts for INAV will be denoted 'sbs' in the zipfile and or image names.  This does not affect Betaflight as historical fonts were single page, and newer 4 page fonts are side by side formatted pages.  Ardu is a single page font file so all historically created fonts will work without issue.

A Walksnail font package will typically contain 3 files.  An ini file and 2 png files.  The 2 png files will typically follow a naming convention that contains `_24` or `_36` in the file name.  The '24' file is the msp-osd `_hd` equivalent, and the '36' file is the non-hd equivalent.  e.g.
```
font_update.ini
WS_BFx4_Sphere_24.png
WS_BFx4_Sphere_36.png
```
From the above example, to use them for msp-osd, copy the 2 png files to the SD card root and rename them as:
|Walksnail Name|msp-osd Name|
|--------------|------------|
|`WS_BFx4_Sphere_24.png`|`font_btfl_hd.png`|
|`WS_BFx4_Sphere_36.png`|`font_btfl.png`|

### .bin Fonts

Due to the changes in 0.12, the .bin font format was superseded in favour of a wider accepted format that makes it easier for the community to create their own.

With 0.12, any fonts stored on the SD card in the .bin format will be ignored.

If you wish to retain the font from the .bin file, this open source tool will assist in conversion to png from bin.
https://github.com/shellixyz/hd_fpv_osd_font_tool/tree/main/src/bin/hd_fpv_osd_font_tool

### FC Specific Font File Names

| Flight controller | SD | HD |
| ----------------- | -- | -- |
| Betaflight       | `font_btfl.png` | `font_btfl_hd.png` |
| INAV       | `font_inav.png` | `font_inav_hd.png`|
| Ardupilot       | `font_ardu.png` | `font_ardu_hd.png`|
| KISS Ultra       | `font_ultr.png` | `font_ultr_hd.png`|
| QUICKSILVER       | `font_quic.png` | `font_quic_hd.png`|
| Generic/Fallback*       | `font.png` | `font_hd.png`|

*This uses the Betaflight font layout

Airside VTx (AU/Vista) which have a very old version of msp-osd on, as well as flight controllers which do not respond to the Variant request, like old Ardupilot versions, will use to the Generic/Fallback font.
##### *Note*
You can also add fonts for firmwares not in this list; using the generic filename, or put the MSP identifier in (lower case it) the filename - ```font_<fc_variant>.png / font_<fc_variant>_hd.png```

### Moving fonts to the goggles file system

If you wish to use a specific font different than the font stored on the goggles, for when you do not have the SD card inserted in the goggles, you can follow the below steps to do this.
1. Copy the font files you wish to be stored on the goggles firstly to your SD card
2. Connect your goggles via USB if you didn't do this for step 1.
3. Insert the SD card in the goggles then power them on
4. Navigate to https://fpv.wtf
5. After the goggles are found and connected, go to the fpv.wtf CLI and type the following
6. `cp /storage/sdcard0/font*.png /blackbox`
7. Power off the goggles, remove the SD card and confirm the newly copied font is used.

##### *Note*
To remove copied fonts repeat steps 1 to 6 and replace step 7 with `rm /blackbox/font*.png`.  Then power off and on the goggles.

### Suggested Third Party Fonts

 - [KNIFA's Material](https://github.com/Knifa/material-osd/releases) - use the Walksnail version for MSP-OSD <= 0.12
 - [SNEAKY_FPV's colour fonts for INAV, ARDU and BF](https://sites.google.com/view/sneaky-fpv/home)
 - [VICEWIZE Italic](https://github.com/vicewize/vicewizeosdfontset)
 - [Kw0ngk4n's Neue OSD](https://github.com/Kw0ngk4n/WTF-Neue-OSD)
 - [EVilm1's OSD Font](https://github.com/EVilm1/EVilm1-OSD-Font)


## Overlaying OSD on DVR
**Note the change in font file format requirements (png format) for the OSD Overlay tool.  If no font file is provided by the user, a built in font (png format) will be used.**

The overlay process uses DVR, recorded osd data and a font file, to overlay/render the OSD data onto DVR footage on your computer.
A default font will be used if no font file is supplied however.  The font look and feel will be the bundled font you would see if using this during flight.

https://fpv.wtf/osd-overlay provides a tool that will overlay captured osd information onto DVR footage.
### Pre-requisites
Unless the osd information is captured during DVR recording on the goggles you will be unable to overlay your osd onto DVR on your computer.

The following fpv.wtf CLI commands (goggles) will ensure this is enabled.

```
package-config set msp-osd rec_enabled true
package-config apply msp-osd
```

##### *Notes*
You only need to supply a font file for the canvas the DVR was recorded with.  i.e. If your FC firmware configuration was HD or a HD variant you only need to supply the '_hd.png' font file.
The 'Chroma Key' will replace the DVR with a solid colour for use within video editing software.  Be aware however that fonts have an amount of transparency around elements that will include the 'Chroma Key' bleed that will be difficult to avoid in video editing software.

See the 'Using Walksnail Fonts Section' for specific requirements that may apply to font file formats.

# Configuration options

Configuration options can be set using the WTFOS Configurator CLI.

Prefix option with `package-config set msp-osd`

e.g. `package-config set msp-osd compress_osd true`

Once desired setting changes are made then: `package-config apply msp-osd`, otherwise settings will be lost when power is off.

Visit https://fpv.wtf/package/fpv-wtf/msp-osd with your Goggles or Air Unit plugged in to edit options.

### Current available options (Goggles):

| Option | Description | Type | Default|
| ------ | ----------- | ---- |--------|
|`show_waiting`| enables or disables WAITING FOR OSD message | true/false | true |
|`show_au_data`| enables AU data (temp/voltage) overlay on the right | true/false | false |
|`rec_enabled`| enable OSD recording to .msp files alongside video | true/false | true |
|`rec_pb_enabled`| enable OSD playback if .msp file is stored alongside video | true/false | true |
|`hide_diagnostics`| hide the diagnostic information in the bottom right | true/false | false |
|`fakehd_enable`| enables [FakeHD](#FakeHD); the other FakeHD options don't do anything if this is disabled. FakeHD is force disabled if the Flight Controller supports proper HD / RealHD | true/false| false |
|`fakehd_lock_center`| Lock FakeHD in centered mode all the time; no gaps/spreading out even when you are flying. | true/false | false |
|`fakehd_menu_switch`| FakeHD will use this character as the menu switch to detect when you are in menus/postflight and triggger centering. | integer/number | 4 (Betaflight Throttle) |
|`fakehd_hide_menu_switch`| FakeHD will hide the menu switch set above; and the next 5 characters | true / false | false |
| `fakehd_columns` | FakeHD column alignment config | Single character, one of T M B S | S |
| `fakehd_rows` | FakeHD row alignment config, each character configures the alignment for one row | 16 characters, each one of L C R W T F D | WWWWWWCCWWWWWWWD |



### Current available options (Air Unit/Vista):

| Option | Description | Type | Default|
| ------ | ----------- | ---- |--------|
|`compress_osd`| Enable sending full frames of compressed data. Disable to send raw MSP data [Read more](#Compressed-Transmission) | true/false| true |
| `osd_update_rate_hz` | Configure the update rate in hz for the OSD when using compressed transmission | integer | 10 |
| `disable_betaflight_hd` | Disable HD Mode, which is otherwise set by default in Betaflight 4.4 | true/false | false |
| `fast_serial` | Change serial baud rate to 230400 baud, which can improve OSD performance in some situations - FC UART config must be changed to match. | true/false | false |
| `cache_serial` | Cache unimportant MSP messages for seldom-used features (like PID tuning in the DJI Goggles Settings Menu) to reduce serial pressure | true/false | false |

#### Compressed Transmission

As of 0.7.0, a new option, `compress_osd`, was added to the **air side** process.

If this is set to "true", then the entire character buffer will be sent using LZ4 compression at the rate defined in `osd_update_rate_hz`, instead of sending raw MSP messages over the air.

When enabled, this should fix INAV delta update related issues as well as provide better link stability.

To enable:

Visit https://fpv.wtf/package/fpv-wtf/msp-osd with your **Air Unit / Vista** plugged in to edit package options.

This option is enabled by default as of 0.10.0, however, if you upgraded from an older version, your configuration will need to be updated using the configurator.

If you continue to have issues with especially INAV character corruption, it is likely your serial link is saturated. Check that the "Custom OSD" option in your DJI goggles menus is set to _disabled_ , and also try out the cache_serial option.

## FAQ / Suggestions

### Modify / Move original DJI OSD elements

You can now modify the elements present in the original DJI OSD. These include for example : transmission speed, latency, channel used, googles battery, sd card icon and default timer.

Elements position, visibility, font and icons can be modified by editing the internal googles files.
This is possible by connecting to the googles using ADB. You can even preview changes using a Python script!

This is not a trivial thing for everyone to do, the full tutorial can be found [here](https://github.com/EVilm1/WIKI-HACK-DJI-OSD#6-advanced-setup-modify-the-dji-hud-elements).

### How do I create a new font (for INAV, Ardupilot, etc.)?

Use `mcm2img` , specifically Knifa's branch to allow you to draw using a PNG template.

https://github.com/Knifa/mcm2img/tree/templates

### Why is everything so big / can I make the text smaller (betaflight)?

For Betaflight prior to 4.4, look into FakeHD.
For Betaflight after 4.4, you should see "HD" fonts by default. Make sure your VTx (AU/Vista) is powered up and visit the Betaflight Configurator to move OSD items to the edge of the screen.

### How can I get my INAV/ArduPilot/Kiss Ultra OSD closer to the edge of the screen / Why is FakeHD closer to the edges?

 - The goggles need 60 characters to go edge to edge - so the 50 in the hd grid doesn't quite fill it
 - So, depending on the Flight Controller's setup, the RealHD grid is displayed centered in the goggles - gaps on both edges.
 - FakeHD had no compatibility constraints like this so we were able to use the full width of the screens.
 - Consequently, FakeHD can get nearer the edges.
 - Currently no solution to get RealHD closer to the edges.

### What is RealHD

Sometimes we refer to the proper MSP OSD HD grid supported by ArduPilot / Kiss Ultra / INAV / Betaflight (from 4.4) + others as RealHD, to distinguish from FakeHD.

# Compiling (development and debugging)

To build for DJI, install the [Android NDK](https://developer.android.com/ndk/downloads) and add the NDK toolchain to your PATH, then use `ndk-build` to build the targets.

To build for UNIXes, install CSFML and run:

```
make -f Makefile.unix
```

Provided targets and tools are:

* `msp_displayport_mux` - takes MSP DisplayPort messages, bundles each frame (all DisplayPort messages between Draw commands) into a single UDP Datagram, and then blasts it over UDP. Also creates a PTY that passes through all _other_ MSP messages, for `dji_hdvt_uav` to connect to.
* `libdisplayport_osd_shim.so` - Patches the `dji_glasses` process to listen for these MSP DisplayPort messages over UDP, and blits them to a DJI framebuffer screen using the DJI framebuffer HAL `libduml_hal` access library, and a converted Betaflight font stored in `font.bin`.
* `osd_sfml` - The same thing as `osd_dji`, but for a desktop PC using SFML and `bold.png`.

Additional debugging can be enabled using `-DDEBUG` as a CFLAG.

## Custom Build Installation (Goggles)

There's a slightly different process for V1 vs V2 Goggles, they renamed some bits between the two.

### FPV Goggles V1

```
ndk-build
adb shell setprop dji.dji_glasses_service 0
adb push libs/armeabi-v7a/libdisplayport_osd_shim.so /tmp
adb shell LD_PRELOAD=/tmp/libdisplayport_osd_shim.so dji_glasses_original -g
```

### FPV Goggles V2

```
ndk-build
adb shell setprop dji.glasses_wm150_service 0
adb push libs/armeabi-v7a/libdisplayport_osd_shim.so /tmp
adb shell LD_PRELOAD=/tmp/libdisplayport_osd_shim.so dji_gls_wm150_original -g
```

### Air Unit / Air Unit Lite (Vista)

```
ndk-build
adb push msp_displayport_mux /blackbox
adb shell setprop dji.hdvt_uav_service 0
adb shell mv /dev/ttyS1 /dev/ttyS1_moved
adb shell nohup /blackbox/msp_displayport_mux 192.168.41.2 /dev/ttyS1_moved /dev/ttyS1 &
adb shell setprop dji.hdvt_uav_service 1
```

This tells the displayport mux to send data from /dev/ttyS1_moved to 192.168.41.2 (goggles) and to create a fake serial port at /dev/ttyS1 with the displayport messages filtered out.

Optionally, you can add `-f`, like `nohup /blackbox/msp_displayport_mux -f 192.168.41.2 /dev/ttyS1_moved /dev/ttyS1` to put the serial port in a faster 230400 baud mode, and set the MSP serial port in your flight controller to 230400 to try to improve the framerate.

You can also omit `setprop dji.hdvt_uav_service 1` , which will improve your OSD framerate at the expense of disabling all Air Unit / Vista side coordination functionality (AU recording, channel changes, some RC features, etc.).

Enjoy.

## Additional Reading / Learning

https://github.com/fpv-wtf/margerine/wiki

## Shoutouts / Thank You

* http://github.com/fpv-wtf team, for making this all possible and very helpful random bits of advice


================================================
FILE: config/airunit/config.json
================================================
{
    "fast_serial": false,
    "cache_serial": false,
    "osd_update_rate_hz": 10,
    "compress_osd": true,
    "disable_betaflight_hd": false
}

================================================
FILE: config/airunit/schema.json
================================================
{
    "settings": {
      "fast_serial": {
        "name": "Fast Serial",
        "widget": "checkbox"
      },
      "cache_serial": {
        "name": "Cache Responses",
        "widget": "checkbox"
      },
      "compress_osd": {
        "name": "Compress OSD",
        "widget": "checkbox"
      },
      "osd_update_rate_hz": {
        "name": "OSD update rate",
        "widget": "range",
        "min": 2,
        "max": 20,
        "step":1
      },
      "disable_betaflight_hd": {
        "name": "Compress OSD",
        "widget": "checkbox"
      }
    },
    "units": [
      "msp-osd-airside"
    ]
  }

================================================
FILE: config/airunit/schemaV2.json
================================================
{
    "title": "MSP OSD",
    "description": "Airside OSD config",
    "type": "object",
    "units": [
        "msp-osd-airside"
    ],
    "required": [],
    "properties": {
        "compress_osd": {
            "title": "Compress OSD",
            "type": "boolean",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "osd_update_rate_hz": {
            "title": "OSD update rate (for Compressed OSD)",
            "type": "number",
            "description": "",
            "minimum": 1,
            "maximum": 20
        },
        "disable_betaflight_hd": {
            "title": "Disable Betaflight HD Mode",
            "type": "boolean",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "fast_serial": {
            "type": "boolean",
            "title": "Fast Serial",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "cache_serial": {
            "type": "boolean",
            "title": "Cache Responses",
            "description": "",
            "enum": [
                true,
                false
            ]
        }
    }
}


================================================
FILE: config/airunit/uiSchemaV2.json
================================================
{
    "compress_osd": {
        "ui:help": "Enable sending full frames of compressed data. Disable to send raw MSP data  - we strongly recommend leaving this on. [Read more](https://github.com/fpv-wtf/msp-osd#Compressed-Transmission)"
    },
    "osd_update_rate_hz": {
        "ui:help": "Configure the update rate in hz for the OSD when using compressed transmission (default 10)"
    },
    "disable_betaflight_hd": {
        "ui:help": "Disable HD Mode, which is otherwise set by default if configured in Betaflight 4.4"
    },
    "fast_serial": {
        "ui:help": "Change serial baud rate to 230400 baud, which can improve OSD performance in some situations - FC UART config must be changed to match."
    },
    "cache_serial": {
        "ui:help": "Cache unimportant MSP messages for seldom-used features (like PID tuning in the DJI Goggles Settings Menu) to reduce serial pressure"
    }
}

================================================
FILE: config/goggles/config.json
================================================
{
    "show_waiting": true,
    "show_au_data": false,
    "fakehd_enable": false,
    "fakehd_hide_throttle_element": false,
    "fakehd_lock_center": false,
    "fakehd_menu_switch": 4,
    "fakehd_hide_menu_switch": false,
    "fakehd_layout_debug": false,
    "fakehd_columns": "S",
    "fakehd_rows": "WWWWWWCCWWWWWWWD",
    "rec_enabled": true,
    "rec_pb_enabled": true
}


================================================
FILE: config/goggles/schema.json
================================================
{
	"settings": {
		"show_waiting": {
			"name": "Show Waiting Message",
			"widget": "checkbox"
		},
		"show_au_data": {
			"name": "Show VTx Temperature and Voltage",
			"widget": "checkbox"
		},
		"fakehd_enable": {
			"name": "Enable FakeHD Mode",
			"widget": "checkbox"
		},
		"fakehd_hide_throttle_element": {
			"name": "FakeHD hide throttle element",
			"widget": "checkbox"
		},
		"fakehd_lock_center": {
			"name": "Lock FakeHD to centered mode",
			"widget": "checkbox"
		},
		"fakehd_menu_switch": {
			"name": "FakeHD menu switch character",
			"widget": "range",
			"min": 1,
			"max": 512,
			"step":1
		},
		"fakehd_hide_menu_switch": {
			"name": "FakeHD hide the menu switch",
			"widget": "checkbox"
		},
		"fakehd_layout_debug": {
			"name": "Undocumented feature to fill the grid with numbers for layout debugging",
			"widget": "checkbox"
		},
		"fakehd_columns": {
			"name": "FakeHD column config",
			"widget": "text",
			"pattern": "[TMBS]",
			"minLength": 1,
			"maxLength": 1
		},
		"fakehd_rows": {
			"name": "FakeHD row config",
			"widget": "text",
			"pattern": "[LCRWTFD]{16}",
			"minLength": 16,
			"maxLength": 16
		},
		"rec_enabled": {
			"name": "Enable OSD recording",
			"widget": "checkbox"
		},
		"rec_pb_enabled": {
			"name": "Enable OSD playback",
			"widget": "checkbox"
		},
		"hide_diagnostics": {
			"name": "Hide diagnostic information",
			"widget": "checkbox"
		}
	},
	"units": [
		"msp-osd-goggles"
	]
}


================================================
FILE: config/goggles/schemaV2.json
================================================
{
    "title": "MSP OSD - Goggles",
    "description": "",
    "type": "object",
    "units": [ "msp-osd-goggles" ],
    "required": [],
    "properties": {
        "show_waiting": {
            "type": "boolean",
            "title": "Show Waiting Message",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "show_au_data": {
            "type": "boolean",
            "title": "Show VTx Temperature and Voltage",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "rec_enabled": {
            "type": "boolean",
            "title": "Enable OSD recording",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "rec_pb_enabled": {
            "type": "boolean",
            "title": "Enable OSD playback",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "hide_diagnostics": {
            "type": "boolean",
            "title": "Hide diagnostic information",
            "description": "",
            "enum": [
                true,
                false
            ]
        },
        "fakehd_enable": {
            "type": "boolean",
            "title": "Enable FakeHD Mode",
            "description": "",
            "enum": [
                true,
                false
            ]
        }
    },
    "dependencies": {
        "fakehd_enable": {
            "oneOf": [
                {
                    "properties": {
                        "fakehd_enable": {
                            "enum": [
                                false
                            ]
                        }
                    }
                },
                {
                    "properties": {
                        "fakehd_enable": {
                            "enum": [
                                true
                            ]
                        },
                        "fakehd_lock_center": {
                            "type": "boolean",
                            "title": "Lock FakeHD to centered mode",
                            "description": "",
                            "enum": [
                                true,
                                false
                            ]
                        },
                        "fakehd_menu_switch": {
                            "type": "number",
                            "title": "FakeHD menu switch character",
                            "description": "",
                            "minimum": 1,
                            "maximum": 512
                        },
                        "fakehd_hide_menu_switch": {
                            "type": "boolean",
                            "title": "FakeHD hide the menu switch",
                            "description": "",
                            "enum": [
                                true,
                                false
                            ]
                        },
                        "fakehd_columns": {
                            "type": "string",
                            "title": "FakeHD column config",
                            "description": "",
                            "oneOf": [
                                {
                                    "const": "T",
                                    "title": "Top"
                                },
                                {
                                    "const": "M",
                                    "title": "Middle"
                                },
                                {
                                    "const": "B",
                                    "title": "Bottom"
                                },
                                {
                                    "const": "S",
                                    "title": "Split"
                                }
                            ]
                        },
                        "fakehd_rows": {
                            "type": "string",
                            "title": "FakeHD row config",
                            "description": "16 characters; each one of LCRWTFD",
                            "maxLength": 16,
                            "minLength": 16,
                            "pattern": "^[LCRWTFD]{16}$"
                        }
                    }
                }
            ]
        }
    }
}


================================================
FILE: config/goggles/uiSchemaV2.json
================================================
{
    "show_waiting": {
        "ui:help": "Enables or disables WAITING FOR OSD message"
    },
    "show_au_data": {
        "ui:help": "Enables AU data (temp/voltage) overlay on the right"
    },
    "rec_enabled": {
        "ui:help": "Enable OSD recording to .msp files alongside video"
    },
    "rec_pb_enabled": {
        "ui:help": "Enable OSD playback if .msp file is stored alongside video (ie: OSD recording is enabled)"
    },
    "hide_diagnostics": {
        "ui:help": "Hide the diagnostic information in the bottom right"
    },
    "fakehd_enable": {
        "ui:help": "Enables FakeHD. [Read more](https://github.com/fpv-wtf/msp-osd#fakehd)"
    },
    "fakehd_lock_center": {
        "ui:help": "Lock FakeHD in centered mode all the time; no gaps/spreading out even when you are flying. [Read more](https://github.com/fpv-wtf/msp-osd#i-dont-want-gaps-at-all)"
    },
    "fakehd_menu_switch": {
        "ui:help": "FakeHD will use this character as the menu switch to detect when you are in menus/postflight and triggger centering. [Read more](https://github.com/fpv-wtf/msp-osd#menu-switching---getting-rid-of-gaps-when-displaying-menu--post-flight-stats--displaying-centered)"
    },
    "fakehd_hide_menu_switch": {
        "ui:help": "FakeHD will hide the menu switch set above; and the next 5 characters"
    },
    "fakehd_columns": {
        "ui:help": "FakeHD column alignment config. [Read more](https://github.com/fpv-wtf/msp-osd#customising-the-default-fakehd-grid)"
    },
    "fakehd_rows": {
        "ui:help": "FakeHD row alignment config, each character configures the alignment for one row. [Read more](https://github.com/fpv-wtf/msp-osd#customising-the-default-fakehd-grid)"
    }
}

================================================
FILE: docs/fonts/gen.sh
================================================
#!/bin/bash


echo "You need https://github.com/shellixyz/hd_fpv_osd_font_tool";
echo "And you need montage from imagemagick";



echo "converting";
find ../../fonts -iname '*.bin' | cut -d '/' -f 4 | cut -d '.' -f 1 | xargs -I '%' ~/.cargo/bin/hd_fpv_osd_font_tool convert djibin:../../fonts/%.bin tiledir:dir_%;

echo "montaging";
find ../../fonts -iname '*.bin' | cut -d '/' -f 4 | cut -d '.' -f 1 | xargs -I '{}' montage 'dir_{}/*.png'  -tile 16x -geometry 24x36+1+1 {}.png;

echo "cleaning";
rm -rf ./dir_font*


echo "Finished"

================================================
FILE: ipk/airunit/control/conffiles
================================================
/opt/etc/package-config/msp-osd/config.json


================================================
FILE: ipk/airunit/control/control
================================================
Package: msp-osd
Version: 0.10.1
Maintainer: bri3d
Description: MSP OSD service for the DJI HD FPV airunit.
Architecture: pigeon-airside
Depends: dinit, wtfos-opkg-config, wtfos-package-config
Homepage: https://github.com/fpv-wtf/msp-osd


================================================
FILE: ipk/airunit/control/postinst
================================================
#!/system/bin/sh
/opt/sbin/dinitctl -u enable msp-osd-airside || true


================================================
FILE: ipk/airunit/control/prerm
================================================
#!/system/bin/sh
/opt/sbin/dinitctl -u disable msp-osd-airside || true



================================================
FILE: ipk/airunit/data/opt/bin/airunit-osd-start.sh
================================================
#!/system/bin/sh
setprop dji.hdvt_uav_service 0
setprop dji.shuttle_service 0

if [ ! -e "/dev/ttyS1_moved" ]
then
  mv /dev/ttyS1 /dev/ttyS1_moved
fi

/opt/bin/msp_displayport_mux 192.168.41.2 /dev/ttyS1_moved /dev/ttyS1 &
echo $! > /opt/var/run/airunit-osd-dji.pid
setprop dji.hdvt_uav_service 1
setprop dji.shuttle_service 1



================================================
FILE: ipk/airunit/data/opt/etc/dinit.d/msp-osd-airside
================================================
type = bgprocess
command = /opt/bin/airunit-osd-start.sh
pid-file = /opt/var/run/airunit-osd-dji.pid
restart = true


================================================
FILE: ipk/goggle/control/conffiles
================================================
/opt/etc/package-config/msp-osd/config.json


================================================
FILE: ipk/goggle/control/control
================================================
Package: msp-osd
Version: 0.12.4
Maintainer: bri3d
Description: MSP OSD service for the DJI HD FPV goggles.
Architecture: pigeon-glasses
Depends: wtfos-modloader, wtfos-package-config
Homepage: https://github.com/fpv-wtf/msp-osd


================================================
FILE: ipk/goggle/control/postinst
================================================
#!/system/bin/sh
/opt/sbin/dinitctl -u enable msp-osd-goggles || true


================================================
FILE: ipk/goggle/control/preinst
================================================
#!/system/bin/sh
if [[ -f /opt/fonts ]]; then
    rm -f /opt/fonts
fi
/opt/sbin/dinitctl -u disable msp-osd-goggles || true


================================================
FILE: ipk/goggle/control/prerm
================================================
#!/system/bin/sh
/opt/sbin/dinitctl -u disable msp-osd-goggles || true


================================================
FILE: ipk/goggle/data/opt/etc/dinit.d/msp-osd-goggles
================================================
type = scripted
command = modmanager enable diy_glasses displayport_osd_shim
stop-command = modmanager disable diy_glasses displayport_osd_shim

================================================
FILE: jni/Android.mk
================================================
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := duml_hal
LOCAL_SRC_FILES := libduml_hal.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)

LOCAL_CFLAGS += -fPIC -std=c99 -O3
LOCAL_LDFLAGS += -fPIC
LOCAL_LDLIBS := -llog -lz
LOCAL_ARM_NEON := true
LOCAL_MODULE := displayport_osd_shim
LOCAL_SHARED_LIBRARIES := duml_hal
LOCAL_SRC_FILES := \
	displayport_osd_shim.c \
	fakehd/fakehd.c \
	font/font.c \
	hw/dji_display.c \
	hw/dji_radio_shm.c \
	hw/dji_services.c \
	json/osd_config.c \
	json/parson.c \
	lz4/lz4.c \
	msp/msp_displayport.c \
	msp/msp.c \
	net/network.c \
	osd_dji_overlay_udp.c \
	rec/rec_pb.c \
	rec/rec_shim.c \
	rec/rec_util.c \
	rec/rec.c \
	toast/toast.c \
	util/fs_util.c \
	libspng/spng.c
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	hw/dji_radio_shm.c \
	json/osd_config.c \
	json/parson.c \
	msp_displayport_mux.c \
	msp/msp.c \
	msp/msp_displayport.c \
	net/network.c \
	net/serial.c \
	util/fs_util.c \
	lz4/lz4.c
LOCAL_MODULE := msp_displayport_mux
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)


================================================
FILE: jni/Application.mk
================================================
APP_PLATFORM=android-23
APP_ABI=armeabi-v7a
APP_CFLAGS += -DSTDC_HEADERS
APP_OPTIM := release


================================================
FILE: jni/displayport_osd_shim.c
================================================
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>

#include "osd.h"
#include "hw/dji_display.h"
#include "hw/dji_services.h"

// Which window in the creation order is the overlay / top menu. Usually 1.
#define MENU_WINDOW_ORDER 1

static duss_disp_instance_handle_t *disp_instance = NULL;
static duss_hal_obj_handle_t ion_handle = NULL;
static int started = 0;
static int are_v2 = 0;
static int window_count = 0;
static void *menu_window = NULL;

// Patch a seemingly unused window management thread in libtp1801_gui.so to inject our code into the dji_glasses process.
void _ZN24MMSFBWindowManagerThread10threadMainEv(void *this) {
    printf("ENTERING MAIN \n");
    are_v2 = dji_goggles_are_v2();
    while(1) {
        if(started == 0 && disp_instance != NULL && ion_handle != NULL) {
            printf("ENTERING OSD! fbdev disp %x ion %x\n", disp_instance, ion_handle);
            started = 1;
            osd_directfb(disp_instance, ion_handle);
        }
        usleep(50000);
    }
}

static void (*_ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId2)(void *this, uint32_t channel_id) = NULL;
static void *tp1801_gui_lib = NULL;

void _ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId(void *this, uint32_t channel_id) {
    if (_ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId2 == NULL) {
        _ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId2 = dlsym(RTLD_NEXT, "_ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId");
        if (_ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId2 == NULL) {
            tp1801_gui_lib = dlopen("/system/lib/libtp1801_gui.so", 1);
            _ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId2 = dlsym(tp1801_gui_lib, "_ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId");
            if (_ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId2 == NULL) {
                printf("dlsym: %s\n", dlerror());
            }
        }
    }
    // RTOS video channels:
    // 1 = Playback
    // 2 = Unknown
    // 3 = Live Video
    // 4 = AV-IN
    if(channel_id == 3) {
        osd_enable();
    } else {
        osd_disable();
    }
    _ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId2(this, channel_id);
}

static void *hal_lib = NULL;

static duss_result_t (*duss_hal_mem_alloc2)(duss_hal_obj_handle_t handle, duss_hal_mem_handle_t *mem_handle, uint32_t size, uint32_t param1, uint32_t param2, uint32_t param3) = 0;
// Patch libduml_hal's duss_hal_mem_alloc.
// Use the first invocation of this to steal the duss_hal_obj_handle_t pointing to the ion shared memory service.
duss_result_t duss_hal_mem_alloc(duss_hal_obj_handle_t handle, duss_hal_mem_handle_t *mem_handle, uint32_t size, uint32_t param1, uint32_t param2, uint32_t param3) {
    if (duss_hal_mem_alloc2 == NULL) {
	    duss_hal_mem_alloc2 = dlsym(RTLD_NEXT, "duss_hal_mem_alloc");
		if (duss_hal_mem_alloc2 == 0){
			if (hal_lib == NULL){
				hal_lib = dlopen("/system/lib/libduml_hal.so", 1);
			}
			duss_hal_mem_alloc2 = dlsym(hal_lib, "duss_hal_mem_alloc");
			if (duss_hal_mem_alloc2 == 0) {
				printf("dlsym: %s\n", dlerror());
				return -1;
			}
		}
    }
    if (ion_handle == NULL) {
        ion_handle = handle;
    }
	return duss_hal_mem_alloc2(handle, mem_handle, size, param1, param2, param3);
}

static duss_result_t (*duss_hal_display_aquire_plane2)(duss_disp_instance_handle_t * , duss_disp_plane_type_t , duss_disp_plane_id_t * ) = 0;

// Patch libduml_hal's duss_hal_display_aquire_plane.
// Use the first invocation of this with plane == 5 to steal the duss_hal_instance_handle_t pointing to the display driver.
duss_result_t duss_hal_display_aquire_plane(duss_disp_instance_handle_t *disp, duss_disp_plane_type_t plane_type, duss_disp_plane_id_t *plane_id) {
	if (duss_hal_display_aquire_plane2 == NULL) {
	    duss_hal_display_aquire_plane2 = dlsym(RTLD_NEXT, "duss_hal_display_aquire_plane");
		if (duss_hal_display_aquire_plane2 == 0){
			if(hal_lib == NULL) {
				hal_lib = dlopen("/system/lib/libduml_hal.so", 1);
			}
			duss_hal_display_aquire_plane2 = dlsym(hal_lib, "duss_hal_display_aquire_plane");
			if (duss_hal_display_aquire_plane2 == 0) {
				printf("dlsym: %s\n", dlerror());
				return -1;
			}
		}
    }
	if(disp_instance == NULL && *plane_id == 5) {
		disp_instance = disp;
	}
	return duss_hal_display_aquire_plane2(disp, plane_type, plane_id);
}

duss_result_t (*duss_hal_display_plane_blending_set2)(duss_disp_instance_handle_t *disp, duss_disp_plane_id_t plane_id, duss_disp_plane_blending_t *blending) = NULL;
duss_result_t duss_hal_display_plane_blending_set(duss_disp_instance_handle_t *disp, duss_disp_plane_id_t plane_id, duss_disp_plane_blending_t *blending) {
    if (duss_hal_display_plane_blending_set2 == NULL) {
	   duss_hal_display_plane_blending_set2 = dlsym(RTLD_NEXT, "duss_hal_display_plane_blending_set");
		if (duss_hal_display_plane_blending_set2 == NULL) {
			if (hal_lib == NULL) {
				hal_lib = dlopen("/system/lib/libduml_hal.so", 1);
			}
			duss_hal_display_plane_blending_set2 = dlsym(hal_lib, "duss_hal_display_plane_blending_set");
			if (duss_hal_display_plane_blending_set2 == NULL) {
				printf("dlsym: %s\n", dlerror());
				return -1;
			}
		}
    }
    // Patch blending order for DJI UI on V1 Goggles to match V2, so we can draw under them.
    if (blending->order == 1) {
        blending->order = 4;
    }
    return duss_hal_display_plane_blending_set2(disp, plane_id, blending);
}

================================================
FILE: jni/fakehd/fakehd.c
================================================
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "json/osd_config.h"
#include "toast/toast.h"

#define FAKEHD_ENABLE_KEY "fakehd_enable"
#define FAKEHD_LOCK_CENTER_KEY "fakehd_lock_center"
#define FAKEHD_HIDE_THROTTLE_KEY "fakehd_hide_throttle_element" // for compat
#define FAKEHD_MENU_SWITCH_KEY "fakehd_menu_switch"
#define FAKEHD_HIDE_MENU_SWITCH_KEY "fakehd_hide_menu_switch" // for compat
#define FAKEHD_LAYOUT_DEBUG_KEY "fakehd_layout_debug"
#define FAKEHD_COLUMNS_KEY "fakehd_columns"
#define FAKEHD_ROWS_KEY "fakehd_rows"

#define INPUT_ROWS 16
#define INPUT_COLS 30

int fakehd_enabled = 0;
static int fakehd_hide_menu_switch = 0;
static int fakehd_lock_center = 0;
static int fakehd_layout_debug = 0;
static int fakehd_menu_switch_char = 4; // betaflight throttle icon
static int fakehd_trigger_x = 99;
static int fakehd_trigger_y = 99;
static char fakehd_columns = 'S';
static char fakehd_rows[INPUT_COLS] = "WWWWWWCCWWWWWWWD";

#ifdef DEBUG
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, fmt, ##args)
#else
#define DEBUG_PRINT(fmt, args...)
#endif

void load_fakehd_config()
{
    DEBUG_PRINT("checking for fakehd enabled\n");
    if (get_boolean_config_value(FAKEHD_ENABLE_KEY))
    {
        DEBUG_PRINT("fakehd enabled\n");
        toast("FAKEHD ENABLED");

        fakehd_enabled = 1;
    }
    else
    {
        DEBUG_PRINT("fakehd disabled\n");
    }

    DEBUG_PRINT("checking for fakehd layout debug\n");
    if (get_boolean_config_value(FAKEHD_LAYOUT_DEBUG_KEY))
    {
        DEBUG_PRINT("fakehd layout debug\n");
        fakehd_layout_debug = 1;
    }
    else
    {
        DEBUG_PRINT("fakehd layout debug off\n");
    }

    DEBUG_PRINT("checking for fakehd hide throttle \n");
    if (get_boolean_config_value(FAKEHD_HIDE_MENU_SWITCH_KEY))
    {
        DEBUG_PRINT("fakehd hide throttle\n");
        fakehd_hide_menu_switch = 1;
    }
    else
    {
        DEBUG_PRINT("fakehd no hide throttle\n");
    }
    DEBUG_PRINT("checking for fakehd lock center \n");
    if (get_boolean_config_value(FAKEHD_LOCK_CENTER_KEY))
    {
        DEBUG_PRINT("fakehd lock center\n");
        fakehd_lock_center = 1;
    }
    else
    {
        DEBUG_PRINT("fakehd no lock center\n");
    }

    int trigger = get_integer_config_value(FAKEHD_MENU_SWITCH_KEY);
    if (trigger)
    {
        DEBUG_PRINT("fakehd found custom trigger\n");
        fakehd_menu_switch_char = trigger;
        toast("FHD MENU SWITCH %c", 4);
    }
    // trigger
    // rows
    const char * rows = get_string_config_value(FAKEHD_ROWS_KEY);
    if (rows) {
        DEBUG_PRINT("fakehd found custom row conf\n");
        memcpy(fakehd_rows, rows, INPUT_COLS);
    }

    const char * cols = get_string_config_value(FAKEHD_COLUMNS_KEY);
    if (cols)
    {
        DEBUG_PRINT("fakehd found col conf\n");
        fakehd_columns = cols[0];
    }
    DEBUG_PRINT("fakehd finished config init\n");
}

static void fakehd_get_column_config(int cols[INPUT_ROWS])
{
    switch (fakehd_columns)
    {
    case 'T':
        memcpy(cols, (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, sizeof(cols[0]) * INPUT_ROWS);
        break;
    case 'M':
        memcpy(cols, (int[]){3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, sizeof(cols[0]) * INPUT_ROWS);
        break;
    case 'B':
        memcpy(cols, (int[]){6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}, sizeof(cols[0]) * INPUT_ROWS);
        break;
    case 'S':
    default:
        memcpy(cols, (int[]){0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21}, sizeof(cols[0]) * INPUT_ROWS);
        break;
    }

    // If more flexibility needed / when config allows - I suggest the 'default' switch block is separated
    // and used to lookup the mapping from the config file, letting the user define extras?

}

static void fakehd_get_row_config(int rownum, int row[INPUT_COLS])
{
    char rowmode = fakehd_rows[rownum];
    switch (rowmode)
    {
    case 'L':
        memcpy(row, (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29}, sizeof(row[0]) * INPUT_COLS);
        break;
    case 'C':
        memcpy(row, (int[]){15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44}, sizeof(row[0]) * INPUT_COLS);
        break;
    case 'R':
        memcpy(row, (int[]){30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}, sizeof(row[0]) * INPUT_COLS);
        break;
    case 'T':
        memcpy(row, (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}, sizeof(row[0]) * INPUT_COLS);
        break;
    case 'F':
        memcpy(row, (int[]){10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49}, sizeof(row[0]) * INPUT_COLS);
        break;
    case 'D':
        memcpy(row, (int[]){12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41}, sizeof(row[0]) * INPUT_COLS);
        break;
    case 'W':
    default:
        memcpy(row, (int[]){0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59}, sizeof(row[0]) * INPUT_COLS);
        break;
    }

    // If more flexibility needed / when config allows - I suggest the 'default' switch block is separated
    // and used to lookup the mapping from the config file, letting the user define extras?
}


// when possible, this should be called on reconnect. it will do what's needed to put fakehd back
// into fresh booted state
void fakehd_reset() {
    // clear saved centering trigger position
    int fakehd_trigger_x = 99;
    int fakehd_trigger_y = 99;
}

void fakehd_enable()
{
    fakehd_enabled = 1;
}

void fakehd_disable()
{
    fakehd_enabled = 0;
    fakehd_reset();
}

int fakehd_is_enabled() {
    return fakehd_enabled;
}

void fakehd_map_sd_character_map_to_hd(uint16_t sd_character_map[60][22], uint16_t hd_character_map[60][22])
{
    int row[INPUT_COLS];
    int col[INPUT_ROWS];

    fakehd_get_column_config(col);

    int render_x = 0;
    int render_y = 0;
    for (int y = INPUT_ROWS-1; y >= 0; y--)
    {
        fakehd_get_row_config(y, row);
        for (int x = INPUT_COLS-1; x >= 0; x--)
        {
            // to visualise the layout better in dev
            if (fakehd_layout_debug && sd_character_map[x][y] == 0) {
                sd_character_map[x][y] = 48 + (x % 10);
            }

            // skip if it's not a character
            if (sd_character_map[x][y] != 0)
            {
                // if current element is fly min or throttle icon
                // record the current position as the 'trigger' position
                if (fakehd_trigger_x == 99 && sd_character_map[x][y] == fakehd_menu_switch_char)
                {
                    DEBUG_PRINT("found fakehd triggger \n");
                    fakehd_trigger_x = x;
                    fakehd_trigger_y = y;
                }

                // if we have seen a trigger (see above) - and it's now gone, switch to centering
                // this is intented to center the menu + postflight stats, which don't contain
                // timer/battery symbols
                if (
                    fakehd_lock_center ||
                    (fakehd_trigger_x != 99 &&
                     sd_character_map[fakehd_trigger_x][fakehd_trigger_y] != fakehd_menu_switch_char))
                {
                    render_x = x + 15;
                    render_y = y + 3;
                }
                else
                {
                    render_y = col[y];
                    render_x = row[x];
                }
                // 0 out the throttle element if configured to do so
                // and also the three adjacent positions where the thottle percent will be
                if (fakehd_trigger_x != 99 &&
                    fakehd_hide_menu_switch &&
                    sd_character_map[x][y] == fakehd_menu_switch_char)
                {
                    hd_character_map[render_x][render_y] = 0;
                    (render_x <= 57) && (hd_character_map[render_x + 1][render_y] = 0);
                    (render_x <= 56) && (hd_character_map[render_x + 2][render_y] = 0);
                    (render_x <= 55) && (hd_character_map[render_x + 3][render_y] = 0);
                    (render_x <= 54) && (hd_character_map[render_x + 4][render_y] = 0);
                    (render_x <= 53) && (hd_character_map[render_x + 5][render_y] = 0);
                }
                else
                {
                    // otherwise, the normal path
                    hd_character_map[render_x][render_y] = sd_character_map[x][y];
                }
            }
        }
    }
}


================================================
FILE: jni/fakehd/fakehd.h
================================================
#pragma once

void load_fakehd_config();
void fakehd_disable();
void fakehd_enable();
int fakehd_is_enabled();
void fakehd_reset();
void fakehd_map_sd_character_map_to_hd(uint16_t sd_character_map[60][22], uint16_t hd_character_map[60][22]);

================================================
FILE: jni/font/font.c
================================================
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
// #include <ctype.h>

#include "../libspng/spng.h"
#include "font.h"
#include "../util/debug.h"

#define BYTES_PER_PIXEL 4
#define HD_FONT_WIDTH 24

/* Font helper methods */

void get_font_path_with_extension(char *font_path_dest, const char *font_path, const char *extension, uint8_t len, uint8_t is_hd, const char *font_variant)
{
    char name_buf[len];
    char res_buf[len];

    if (font_variant != NULL && strlen(font_variant) > 0)
    {
        snprintf(name_buf, len, "%s_%s", font_path, font_variant);
    } else {
        snprintf(name_buf, len, "%s", font_path);
    }

    if (is_hd)
    {
        // surely there's a better way...
        snprintf(res_buf, len, "%s", "_hd");
    } else {
        snprintf(res_buf, len, "%s", "");
    }
    snprintf(font_path_dest, len, "%s%s%s", name_buf, res_buf, extension);
    DEBUG_PRINT("Font path: %s\n", font_path_dest);
}

static int open_font(const char *filename, display_info_t *display_info, const char *font_variant)
{
    char file_path[255];
    int is_hd = (display_info->font_width == HD_FONT_WIDTH) ? 1 : 0;
    get_font_path_with_extension(file_path, filename, ".png", 255, is_hd, font_variant);
    DEBUG_PRINT("Opening font: %s\n", file_path);
    struct stat st;
    memset(&st, 0, sizeof(st));
    stat(file_path, &st);
    size_t filesize = st.st_size;
    if(!(filesize > 0)) {
        DEBUG_PRINT("Font file did not exist: %s\n", file_path);
        return -1;
    }

    FILE *fd = fopen(file_path, "rb");
    if (!fd) {
        DEBUG_PRINT("Could not open file %s\n", file_path);
        return -1;
    }

    spng_ctx *ctx = spng_ctx_new(0);
    DEBUG_PRINT("Allocated PNG context\n");
    // Set some kind of reasonable PNG limit so we don't get blown up
    size_t limit = 1024 * 1024 * 64;
    spng_set_chunk_limits(ctx, limit, limit);
    DEBUG_PRINT("Set PNG chunk limits\n");
    spng_set_png_file(ctx, fd);
    DEBUG_PRINT("Set PNG file\n");

    struct spng_ihdr ihdr;
    int ret = spng_get_ihdr(ctx, &ihdr);
    DEBUG_PRINT("Got PNG header\n");

    if(ret)
    {
        printf("spng_get_ihdr() error: %s\n", spng_strerror(ret));
        goto err;
    }

    if(ihdr.height != display_info->font_height * NUM_CHARS) {
        printf("font invalid height, got %d wanted %d\n", ihdr.height, display_info->font_height * NUM_CHARS);
        goto err;
    }

    if(ihdr.width % display_info->font_width != 0) {
        printf("font invalid width, not a multiple of %d\n", display_info->font_width);
        goto err;
    }

    DEBUG_PRINT("Image pixel size %d x %d\n", ihdr.width, ihdr.height);

    int num_pages = ihdr.width / display_info->font_width;

    DEBUG_PRINT("Font has %d pages\n", num_pages);

    size_t image_size = 0;
    int fmt = SPNG_FMT_RGBA8;
    ret = spng_decoded_image_size(ctx, fmt, &image_size);
    if(ret) {
        goto err;
    }

    DEBUG_PRINT("Allocating image size %d\n", image_size);

    void* font_data = malloc(image_size);
    ret = spng_decode_image(ctx, font_data, image_size, SPNG_FMT_RGBA8, 0);
    if(ret) {
        printf("Failed to decode PNG!\n");
        free(font_data);
        goto err;
    }

    for(int page = 0; page < num_pages; page++) {
        DEBUG_PRINT("Loading font page %d of %d, placing %x\n", page, num_pages, display_info->fonts);
        display_info->fonts[page] = malloc(display_info->font_width * display_info->font_height * NUM_CHARS * BYTES_PER_PIXEL);
        DEBUG_PRINT("Allocated %d bytes for font page buf at%x\n", display_info->font_width * display_info->font_height * NUM_CHARS * BYTES_PER_PIXEL, display_info->fonts[page]);
        for(int char_num = 0; char_num < NUM_CHARS; char_num++) {
            for(int y = 0; y < display_info->font_height; y++) {
                // Copy each character line at a time into the correct font buffer
                int char_width_bytes = display_info->font_width * BYTES_PER_PIXEL;
                int char_size_bytes_dest = (display_info->font_width * display_info->font_height * BYTES_PER_PIXEL);
                int char_size_bytes_src =  (ihdr.width * display_info->font_height * BYTES_PER_PIXEL);
                memcpy((uint8_t *)display_info->fonts[page] + (char_num * char_size_bytes_dest) + (y * char_width_bytes), (uint8_t *)font_data + (char_num * char_size_bytes_src) + (ihdr.width * y * BYTES_PER_PIXEL) + (page * char_width_bytes), char_width_bytes);
            }
        }
    }

    free(font_data);
    spng_ctx_free(ctx);
    fclose(fd);
    return 0;
    err:
        spng_ctx_free(ctx);
        fclose(fd);
        return -1;
}

void load_font(display_info_t *display_info, const char *font_variant) {

    // Note: load_font will not replace an existing font.
    if(display_info->fonts[0] == NULL) {
        int loaded_font = 0;
        DEBUG_PRINT("IN LOAD_FONT\n");
        // create a copy of font_variant
        char font_variant_lower[5] = "";
        if (font_variant != NULL)
        {
            DEBUG_PRINT("Lowercasing variant\n");
            size_t length = strlen(font_variant);
            for (size_t i = 0; i < length && i < 4; i++) // Ensure not to exceed array bounds
            {
                font_variant_lower[i] = tolower(font_variant[i]);
            }
        }
        else
        {
            DEBUG_PRINT("Font variant is NULL\n");
        }

        DEBUG_PRINT("Loading font %s\n", font_variant_lower);

        char *fallback_font_variant = "";
        if (strcmp(font_variant_lower, "btfl") == 0)
        {
            DEBUG_PRINT("Setting fallback font variant to bf\n");
            fallback_font_variant = "bf";
        }
        else if (strcmp(font_variant_lower, "ultr") == 0)
        {
            DEBUG_PRINT("Setting fallback font variant to ultra\n");
            fallback_font_variant = "ultra";
        }

        // try the three paths for the current font
        DEBUG_PRINT("Loading from: %s %s\n", SDCARD_FONT_PATH, font_variant_lower);
        loaded_font = open_font(SDCARD_FONT_PATH, display_info, font_variant_lower);
        if (loaded_font < 0 && strcmp(fallback_font_variant, "") != 0)
        {
            DEBUG_PRINT("Loading fallback variant from: %s %s\n", SDCARD_FONT_PATH, fallback_font_variant);
            loaded_font = open_font(SDCARD_FONT_PATH, display_info, fallback_font_variant);
        }
        if (loaded_font < 0)
        {
            DEBUG_PRINT("Loading from: %s %s\n", FALLBACK_FONT_PATH, font_variant_lower);
            loaded_font = open_font(FALLBACK_FONT_PATH, display_info, font_variant_lower);
        }
        if (loaded_font < 0 && strcmp(fallback_font_variant, "") != 0)
        {
            DEBUG_PRINT("Loading fallback variant from: %s %s\n", FALLBACK_FONT_PATH, fallback_font_variant);
            loaded_font = open_font(FALLBACK_FONT_PATH, display_info, fallback_font_variant);
        }
        if (loaded_font < 0)
        {
            DEBUG_PRINT("Loading from: %s %s\n", ENTWARE_FONT_PATH, font_variant_lower);
            loaded_font = open_font(ENTWARE_FONT_PATH, display_info, font_variant_lower);
        }


        // finally, if we have no fonts for this FC, fallback to the default font
        if (loaded_font)
        {
            DEBUG_PRINT("Loading generic from: %s\n", SDCARD_FONT_PATH);
            loaded_font = open_font(SDCARD_FONT_PATH, display_info, "");
            if (loaded_font < 0)
            {
                DEBUG_PRINT("Loading generic from: %s\n", FALLBACK_FONT_PATH);
                loaded_font = open_font(FALLBACK_FONT_PATH, display_info, "");
            }
            if (loaded_font < 0)
            {
                DEBUG_PRINT("Loading generic from: %s\n", ENTWARE_FONT_PATH);
                loaded_font = open_font(ENTWARE_FONT_PATH, display_info, "");
            }
        }
    }
}

void close_font(display_info_t *display_info) {
    for(int i = 0; i < NUM_FONT_PAGES; i++) {
        if(display_info->fonts[i] != NULL) {
            free(display_info->fonts[i]);
            display_info->fonts[i] = NULL;
        }
    }
}



================================================
FILE: jni/font/font.h
================================================
#pragma once

#include <stdint.h>

#include "../util/display_info.h"

#define FALLBACK_FONT_PATH "/blackbox/font"
#define ENTWARE_FONT_PATH "/opt/fonts/font"
#define SDCARD_FONT_PATH "/storage/sdcard0/font"

#define FALLBACK_FONT NULL

typedef enum
{
    FONT_VARIANT_GENERIC,
    FONT_VARIANT_BETAFLIGHT,
    FONT_VARIANT_INAV,
    FONT_VARIANT_ARDUPILOT,
    FONT_VARIANT_KISS_ULTRA,
    FONT_VARIANT_QUICKSILVER,
    FONT_VARIANT_COUNT
} font_variant_e;

void load_font(display_info_t *display_info, const char *font_variant);
void close_font(display_info_t *display_info);
void get_font_path_with_extension(char *font_path_dest, const char *font_path, const char *extension, uint8_t len, uint8_t is_hd, const char *font_variant);


================================================
FILE: jni/hw/dji_display.c
================================================
#include <stdlib.h>
#include "dji_display.h"
#include "util/debug.h"

#define GOGGLES_V1_VOFFSET 575
#define GOGGLES_V2_VOFFSET 215

dji_display_state_t *dji_display_state_alloc(uint8_t is_v2_goggles) {
    dji_display_state_t *display_state = calloc(1, sizeof(dji_display_state_t));
    display_state->disp_instance_handle = (duss_disp_instance_handle_t *)calloc(1, sizeof(duss_disp_instance_handle_t));
    display_state->fb_0 = (duss_frame_buffer_t *)calloc(1,sizeof(duss_frame_buffer_t));
    display_state->fb_1 = (duss_frame_buffer_t *)calloc(1,sizeof(duss_frame_buffer_t));
    display_state->pb_0 = (duss_disp_plane_blending_t *)calloc(1, sizeof(duss_disp_plane_blending_t));
    display_state->is_v2_goggles = is_v2_goggles;
    display_state->frame_drawn = 0;
    return display_state;
}

void dji_display_state_free(dji_display_state_t *display_state) {
    free(display_state->disp_instance_handle);
    free(display_state->fb_0);
    free(display_state->fb_1);
    free(display_state->pb_0);
    free(display_state);
}

void dji_display_close_framebuffer(dji_display_state_t *display_state) {
    duss_hal_display_port_enable(display_state->disp_instance_handle, 3, 0);
    duss_hal_display_release_plane(display_state->disp_instance_handle, display_state->plane_id);
    duss_hal_display_close(display_state->disp_handle, &display_state->disp_instance_handle);
    duss_hal_mem_free(display_state->ion_buf_0);
    duss_hal_mem_free(display_state->ion_buf_1);
    duss_hal_device_close(display_state->disp_handle);
    duss_hal_device_stop(display_state->ion_handle);
    duss_hal_device_close(display_state->ion_handle);
    duss_hal_deinitialize();
}

void dji_display_open_framebuffer(dji_display_state_t *display_state, duss_disp_plane_id_t plane_id) {
    uint32_t hal_device_open_unk = 0;
    duss_result_t res = 0;

    display_state->plane_id = plane_id;

    // PLANE BLENDING

    display_state->pb_0->is_enable = 1;
    display_state->pb_0->voffset = GOGGLES_V1_VOFFSET; // TODO just check hwid to figure this out
    display_state->pb_0->hoffset = 0;
    display_state->pb_0->order = 2;

    // Global alpha - disable as we want per pixel alpha.

    display_state->pb_0->glb_alpha_en = 0;
    display_state->pb_0->glb_alpha_val = 0;

    // Blending algorithm 1 seems to work.

    display_state->pb_0->blending_alg = 1;

    duss_hal_device_desc_t device_descs[3] = {
        {"/dev/dji_display", &duss_hal_attach_disp, &duss_hal_detach_disp, 0x0},
        {"/dev/ion", &duss_hal_attach_ion_mem, &duss_hal_detach_ion_mem, 0x0},
        {0,0,0,0}
    };

    duss_hal_initialize(device_descs);

    res = duss_hal_device_open("/dev/dji_display",&hal_device_open_unk,&display_state->disp_handle);
    if (res != 0) {
        printf("failed to open dji_display device");
        exit(0);
    }
    res = duss_hal_display_open(display_state->disp_handle, &display_state->disp_instance_handle, 0);
    if (res != 0) {
        printf("failed to open display hal");
        exit(0);
    }

    res = duss_hal_display_reset(display_state->disp_instance_handle);
    if (res != 0) {
        printf("failed to reset display");
        exit(0);
    }

    // No idea what this "plane mode" actually does but it's different on V2
    uint8_t acquire_plane_mode = display_state->is_v2_goggles ? 6 : 0;

    res = duss_hal_display_aquire_plane(display_state->disp_instance_handle,acquire_plane_mode,&plane_id);
    if (res != 0) {
        printf("failed to acquire plane");
        exit(0);
    }
    res = duss_hal_display_port_enable(display_state->disp_instance_handle, 3, 1);
    if (res != 0) {
        printf("failed to enable display port");
        exit(0);
    }

    res = duss_hal_display_plane_blending_set(display_state->disp_instance_handle, plane_id, display_state->pb_0);

    if (res != 0) {
        printf("failed to set blending");
        exit(0);
    }
    res = duss_hal_device_open("/dev/ion", &hal_device_open_unk, &display_state->ion_handle);
    if (res != 0) {
        printf("failed to open shared VRAM");
        exit(0);
    }
    res = duss_hal_device_start(display_state->ion_handle,0);
    if (res != 0) {
        printf("failed to start VRAM device");
        exit(0);
    }

    res = duss_hal_mem_alloc(display_state->ion_handle,&display_state->ion_buf_0,0x473100,0x400,0,0x17);
    if (res != 0) {
        printf("failed to allocate VRAM");
        exit(0);
    }
    res = duss_hal_mem_map(display_state->ion_buf_0, &display_state->fb0_virtual_addr);
    if (res != 0) {
        printf("failed to map VRAM");
        exit(0);
    }
    res = duss_hal_mem_get_phys_addr(display_state->ion_buf_0, &display_state->fb0_physical_addr);
    if (res != 0) {
        printf("failed to get FB0 phys addr");
        exit(0);
    }
    printf("first buffer VRAM mapped virtual memory is at %p : %p\n", display_state->fb0_virtual_addr, display_state->fb0_physical_addr);

    res = duss_hal_mem_alloc(display_state->ion_handle,&display_state->ion_buf_1,0x473100,0x400,0,0x17);
    if (res != 0) {
        printf("failed to allocate FB1 VRAM");
        exit(0);
    }
    res = duss_hal_mem_map(display_state->ion_buf_1,&display_state->fb1_virtual_addr);
    if (res != 0) {
        printf("failed to map FB1 VRAM");
        exit(0);
    }
    res = duss_hal_mem_get_phys_addr(display_state->ion_buf_1, &display_state->fb1_physical_addr);
    if (res != 0) {
        printf("failed to get FB1 phys addr");
        exit(0);
    }
    printf("second buffer VRAM mapped virtual memory is at %p : %p\n", display_state->fb1_virtual_addr, display_state->fb1_physical_addr);

    for(int i = 0; i < 2; i++) {
        duss_frame_buffer_t *fb = i ? display_state->fb_1 : display_state->fb_0;
        fb->buffer = i ? display_state->ion_buf_1 : display_state->ion_buf_0;
        fb->pixel_format = display_state->is_v2_goggles ? DUSS_PIXFMT_RGBA8888_GOGGLES_V2 : DUSS_PIXFMT_RGBA8888; // 20012 instead on V2
        fb->frame_id = i;
        fb->planes[0].bytes_per_line = 0x1680;
        fb->planes[0].offset = 0;
        fb->planes[0].plane_height = 810;
        fb->planes[0].bytes_written = 0x473100;
        fb->width = 1440;
        fb->height = 810;
        fb->plane_count = 1;
    }
}


void dji_display_open_framebuffer_injected(dji_display_state_t *display_state, duss_disp_instance_handle_t *disp, duss_hal_obj_handle_t ion_handle, duss_disp_plane_id_t plane_id) {
    uint32_t hal_device_open_unk = 0;
    duss_result_t res = 0;
    display_state->disp_instance_handle = disp;
    display_state->ion_handle = ion_handle;
    display_state->plane_id = plane_id;

    // PLANE BLENDING

    display_state->pb_0->is_enable = 1;

    // TODO just check hwid to figure this out. Not actually V1/V2 related but an HW version ID.

    display_state->pb_0->voffset = GOGGLES_V1_VOFFSET;
    display_state->pb_0->hoffset = 0;

    // On Goggles V1, the UI and video are in Z-Order 1.
    // On Goggles V2, they're in Z-Order 4, but we inline patch them to Z-Order 1 (see displayport_osd_shim.c)

    display_state->pb_0->order = 2;

    // Global alpha - disable as we want per pixel alpha.

    display_state->pb_0->glb_alpha_en = 0;
    display_state->pb_0->glb_alpha_val = 0;

    // These aren't documented. Blending algorithm 0 is employed for menus and 1 for screensaver.

    display_state->pb_0->blending_alg = 1;

    // No idea what this "plane mode" actually does but it's different on V2
    uint8_t acquire_plane_mode = display_state->is_v2_goggles ? 6 : 0;

    DEBUG_PRINT("acquire plane\n");
    res = duss_hal_display_aquire_plane(display_state->disp_instance_handle,acquire_plane_mode,&plane_id);
    if (res != 0) {
        DEBUG_PRINT("failed to acquire plane");
        exit(0);
    }

    res = duss_hal_display_plane_blending_set(display_state->disp_instance_handle, plane_id, display_state->pb_0);

    if (res != 0) {
        DEBUG_PRINT("failed to set blending");
        exit(0);
    }
    DEBUG_PRINT("alloc ion buf\n");
    res = duss_hal_mem_alloc(display_state->ion_handle,&display_state->ion_buf_0,0x473100,0x400,0,0x17);
    if (res != 0) {
        DEBUG_PRINT("failed to allocate VRAM");
        exit(0);
    }
    res = duss_hal_mem_map(display_state->ion_buf_0, &display_state->fb0_virtual_addr);
    if (res != 0) {
        DEBUG_PRINT("failed to map VRAM");
        exit(0);
    }
    res = duss_hal_mem_get_phys_addr(display_state->ion_buf_0, &display_state->fb0_physical_addr);
    if (res != 0) {
        DEBUG_PRINT("failed to get FB0 phys addr");
        exit(0);
    }
    DEBUG_PRINT("first buffer VRAM mapped virtual memory is at %p : %p\n", display_state->fb0_virtual_addr, display_state->fb0_physical_addr);

    res = duss_hal_mem_alloc(display_state->ion_handle,&display_state->ion_buf_1,0x473100,0x400,0,0x17);
    if (res != 0) {
        DEBUG_PRINT("failed to allocate FB1 VRAM");
        exit(0);
    }
    res = duss_hal_mem_map(display_state->ion_buf_1,&display_state->fb1_virtual_addr);
    if (res != 0) {
        DEBUG_PRINT("failed to map FB1 VRAM");
        exit(0);
    }
    res = duss_hal_mem_get_phys_addr(display_state->ion_buf_1, &display_state->fb1_physical_addr);
    if (res != 0) {
        DEBUG_PRINT("failed to get FB1 phys addr");
        exit(0);
    }
    DEBUG_PRINT("second buffer VRAM mapped virtual memory is at %p : %p\n", display_state->fb1_virtual_addr, display_state->fb1_physical_addr);

    for(int i = 0; i < 2; i++) {
        duss_frame_buffer_t *fb = i ? display_state->fb_1 : display_state->fb_0;
        fb->buffer = i ? display_state->ion_buf_1 : display_state->ion_buf_0;
        fb->pixel_format = display_state->is_v2_goggles ? DUSS_PIXFMT_RGBA8888_GOGGLES_V2 : DUSS_PIXFMT_RGBA8888; // 20012 instead on V2
        fb->frame_id = i;
        fb->planes[0].bytes_per_line = 0x1680;
        fb->planes[0].offset = 0;
        fb->planes[0].plane_height = 810;
        fb->planes[0].bytes_written = 0x473100;
        fb->width = 1440;
        fb->height = 810;
        fb->plane_count = 1;
    }
}

void dji_display_push_frame(dji_display_state_t *display_state) {
    if (display_state->frame_drawn == 0) {
        duss_frame_buffer_t *fb = display_state->fb_0;
        duss_hal_mem_sync(fb->buffer, 1);
        display_state->frame_drawn = 1;
        printf("fbdebug pushing frame\n");
        duss_hal_display_push_frame(display_state->disp_instance_handle, display_state->plane_id, fb);
    } else {
        DEBUG_PRINT("!!! Dropped frame due to pending frame push!\n");
    }
    memcpy(display_state->fb0_virtual_addr, display_state->fb1_virtual_addr, sizeof(uint32_t) * 1440 * 810);
}

void *dji_display_get_fb_address(dji_display_state_t *display_state) {
     return display_state->fb1_virtual_addr;
}



================================================
FILE: jni/hw/dji_display.h
================================================
#pragma once
#include "duml_hal.h"

typedef struct dji_display_state_s {
    duss_disp_plane_id_t plane_id;
    duss_hal_obj_handle_t disp_handle;
    duss_hal_obj_handle_t ion_handle;
    duss_disp_vop_id_t vop_id;
    duss_hal_mem_handle_t ion_buf_0;
    duss_hal_mem_handle_t ion_buf_1;
    void * fb0_virtual_addr;
    void * fb0_physical_addr;
    void * fb1_virtual_addr;
    void * fb1_physical_addr;
    duss_disp_instance_handle_t *disp_instance_handle;
    duss_frame_buffer_t *fb_0;
    duss_frame_buffer_t *fb_1;
    duss_disp_plane_blending_t *pb_0;
    uint8_t is_v2_goggles;
    uint8_t frame_drawn;
} dji_display_state_t;

void dji_display_push_frame(dji_display_state_t *display_state);
void dji_display_open_framebuffer(dji_display_state_t *display_state, duss_disp_plane_id_t plane_id);
void dji_display_open_framebuffer_injected(dji_display_state_t *display_state, duss_disp_instance_handle_t *disp, duss_hal_obj_handle_t ion_handle, duss_disp_plane_id_t plane_id);
void dji_display_close_framebuffer(dji_display_state_t *display_state);
dji_display_state_t *dji_display_state_alloc(uint8_t is_v2_goggles);
void dji_display_state_free(dji_display_state_t *display_state);
void *dji_display_get_fb_address(dji_display_state_t *display_state);


================================================
FILE: jni/hw/dji_radio_shm.c
================================================
#include <assert.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>

#include "dji_radio_shm.h"

void open_dji_radio_shm(dji_shm_state_t *shm) {
    int fd = open("/dev/mem", O_RDWR);
    assert(fd > 0);
    shm->mapped_address = mmap64(NULL, RTOS_SHM_SIZE, PROT_READ, MAP_SHARED, fd, RTOS_SHM_ADDRESS);
    assert(shm->mapped_address != MAP_FAILED);
    close(fd);
    shm->modem_info = (modem_shmem_info_t *)((uint8_t *)shm->mapped_address + 0x100);
    shm->product_info = (product_shm_info_t *)((uint8_t *)shm->mapped_address + 0xC0);
}

void close_dji_radio_shm(dji_shm_state_t *shm) {
    munmap(shm->mapped_address, RTOS_SHM_SIZE);
    shm->mapped_address = NULL;
    shm->modem_info = NULL;
    shm->product_info = NULL;
}

uint16_t dji_radio_latency_ms(dji_shm_state_t *shm) {
    return shm->product_info->frame_delay_e2e;
}

uint16_t dji_radio_mbits(dji_shm_state_t *shm) {
    return shm->modem_info->channel_status;
}

================================================
FILE: jni/hw/dji_radio_shm.h
================================================

#pragma once
#include <stdint.h>

#define RTOS_SHM_ADDRESS 0xfffc1000
#define RTOS_SHM_SIZE 0x1000

#define RTOS_PRODUCT_OFFSET 0xc0
#define RTOS_MODEM_OFFSET 0x100

typedef struct modem_shmem_info_s {
    uint32_t frm_idx;
    uint16_t frm_isI;
    uint16_t frm_len;
    uint16_t frm_dsti;
    uint16_t frm_dstf;
    uint16_t channel_status;
    uint16_t dec_err_status;
    uint16_t cur_time;
    uint16_t delta_time;
    uint16_t dbg_msc;
    uint8_t dbg_ap_ready;
    uint8_t dbg_cp_ready;
    uint32_t local_id;
    uint8_t cp_state;
    uint8_t cp_report;
    uint8_t cp_report_seq;
    uint8_t client_type;
    uint32_t cp_boot_status0;
    uint32_t cp_boot_status1;
    uint32_t board_version;
    uint32_t board_sub_version;
    uint8_t machine_role;
    uint8_t is_reverse;
    int8_t cp_tx_power;
    uint8_t gnd_type;
    uint32_t cp_sssfn;
    uint32_t ulow_en;
    uint8_t mipi_rx_response;
    uint8_t liveview_broken_status;
    uint8_t reserved01;
    uint8_t reserved02;
    uint8_t ap_reboot_flag;
    uint8_t ap_reboot_ack_flag;
    uint8_t secure_sync_flag;
    uint8_t reserve00;
    uint8_t area_state;
    uint8_t area_substate;
    uint8_t GsCtrl;
    uint8_t GsSubState;
    uint8_t WaterLevel[4];
    uint16_t RxCntStastic[4];
    uint16_t TxCntStastic[4];
    uint8_t Reserved[8];
    uint32_t com_uart_status;
    uint32_t fcr_rx_status;
    uint32_t fcr_tx_status;
    uint32_t frm_idx_for_display;
    uint32_t frm_delay_for_display;
    uint16_t wifi_sdr_mode;
    uint16_t frm_isI_for_display;
    uint32_t country_code;
    uint16_t frm_len_for_display;
    uint16_t delta_time_for_display;
    uint8_t uint8_t_reboot_reason;
    uint8_t field_0x85;
    uint8_t field_0x86;
    uint8_t field_0x87;
    uint64_t cpa7_version;
    uint64_t dsp_version;
    uint8_t u8_dual_band_capability;
} __attribute__((packed)) modem_shmem_info_t;

typedef struct product_shm_info_s {
    uint16_t frm_width;
    uint16_t frm_height;
    uint8_t fps;
    uint8_t enc_strategy;
    uint16_t lcdc_underflow_cnt;
    uint32_t enc_sto_frm_dropped;
    uint32_t enc_lv_frm_dropped;
    uint32_t mipi_csi_frm_dropped;
    uint32_t display_frm_dropped;
    uint64_t audio_pts;
    uint32_t local_fps_num;
    uint32_t local_fps_den;
    uint16_t frame_delay_e2e;
    uint16_t cam_frame_interval;
    uint16_t outliner_frame_interval;
    uint16_t outliner_frame_interval_cnt;
    uint16_t max_frame_delay_e2e;
    uint16_t min_frame_delay_e2e;
    uint16_t avg_frame_delay_e2e;
    uint16_t if_switch;
    uint8_t if_change_pipe;
    uint8_t if_pb_pause;
    uint8_t liveview_pipeline_running;
    uint8_t avIn_pipeline_running;
    uint8_t avIn_stream_type;
    uint8_t pb_flush;
    uint8_t disp_pannel_need_reset;
    uint8_t pad;
} __attribute__((packed)) product_shm_info_t;

typedef struct dji_shm_state_s {
    void *mapped_address;
    product_shm_info_t *product_info;
    modem_shmem_info_t *modem_info;
} dji_shm_state_t;

uint16_t dji_radio_latency_ms(dji_shm_state_t *shm);
uint16_t dji_radio_mbits(dji_shm_state_t *shm);
void close_dji_radio_shm(dji_shm_state_t *shm);
void open_dji_radio_shm(dji_shm_state_t *shm);

================================================
FILE: jni/hw/dji_services.c
================================================
#include <string.h>
#ifdef __ANDROID_API__
#include <sys/system_properties.h>
#endif

#define V2_SERVICE_NAME "dji.glasses_wm150_service"
#define V1_SERVICE_NAME "dji.glasses_service"
#define DEVICE_PROPERTY_NAME "ro.product.device"
#define V2_GOGGLES_DEVICE "pigeon_wm170_gls"

void dji_stop_goggles(int is_v2) {
#ifdef __ANDROID_API__
    __system_property_set(is_v2 ? V2_SERVICE_NAME : V1_SERVICE_NAME, "0");
#endif
}

void dji_start_goggles(int is_v2) {
#ifdef __ANDROID_API__
    __system_property_set(is_v2 ? V2_SERVICE_NAME : V1_SERVICE_NAME, "1");
#endif
}

int dji_goggles_are_v2() {
#ifdef __ANDROID_API__
    char goggles_version_response[255];
    int len = __system_property_get(DEVICE_PROPERTY_NAME, &goggles_version_response);
    return(strcmp(goggles_version_response, V2_GOGGLES_DEVICE) == 0);
#else
    return 0;
#endif
}

================================================
FILE: jni/hw/dji_services.h
================================================
#pragma once

void dji_stop_goggles(int is_v2);
void dji_start_goggles(int is_v2);
int dji_goggles_are_v2();

================================================
FILE: jni/hw/duml_hal.h
================================================
#pragma once
#include <stdint.h>

typedef int32_t duss_result_t;

typedef uint8_t duss_hal_state_t;
typedef uint8_t duss_hal_class_t;

struct sem_t {
    uint32_t count;
};

struct duss_osal_mutex_attrib_t {
    char * name;
};

struct duss_osal_mutex_handle_t {
    struct duss_osal_mutex_attrib_t attrib;
    struct sem_t sema;
};

typedef struct duss_osal_mutex_handle_t duss_osal_mutex_handle_t, *Pduss_osal_mutex_handle_t;


typedef struct duss_hal_obj_dev_t duss_hal_obj_dev_t, *Pduss_hal_obj_dev_t;

typedef struct duss_hal_obj * duss_hal_obj_handle_t;

struct duss_hal_obj_dev_t {
    char * name;
    duss_hal_state_t obj_state;
    duss_hal_class_t obj_class;
    uint16_t obj_index;
    int32_t obj_refcnt;
    struct duss_osal_mutex_handle_t * obj_lock;
    struct duss_osal_mutex_handle_t * app_lock;
    duss_result_t (* open)(duss_hal_obj_handle_t, void *);
    duss_result_t (* close)(duss_hal_obj_handle_t);
    duss_result_t (* set_cfg)(duss_hal_obj_handle_t, void *);
    duss_result_t (* get_cfg)(duss_hal_obj_handle_t, void *);
    duss_result_t (* start)(duss_hal_obj_handle_t, void *);
    duss_result_t (* stop)(duss_hal_obj_handle_t, void *);
};

struct duss_hal_obj {
    struct duss_hal_obj_dev_t dev;
    void * dev_class;
    void * dev_priv;
};

struct duss_hal_device_desc_t {
    char * name;
    duss_result_t (* attach)(char *, duss_hal_obj_handle_t *);
    duss_result_t (* detach)(duss_hal_obj_handle_t);
    duss_hal_obj_handle_t obj;
};

typedef enum duss_pixel_format {
    DUSS_PIXFMT_COMPRESSED_END=30002,
    DUSS_PIXFMT_DRAW_V1=30000,
    DUSS_PIXFMT_DUAL_PLANE_16BIT=40003,
    DUSS_PIXFMT_DUAL_PLANE_8BIT=40002,
    DUSS_PIXFMT_GENERAL_END=40004,
    DUSS_PIXFMT_JPEG_LS=30001,
    DUSS_PIXFMT_OPAQUE=0,
    DUSS_PIXFMT_RAW10_PACKED=10004,
    DUSS_PIXFMT_RAW12_PACKED=10005,
    DUSS_PIXFMT_RAW12_UNPACKED=10008,
    DUSS_PIXFMT_RAW14_PACKED=10006,
    DUSS_PIXFMT_RAW14_UNPACKED=10009,
    DUSS_PIXFMT_RAW16_OPAQUE=10001,
    DUSS_PIXFMT_RAW16_UNPACKED=10010,
    DUSS_PIXFMT_RAW18_PACKED=10007,
    DUSS_PIXFMT_RAW18_UNPACKED=10011,
    DUSS_PIXFMT_RAW24_OPAQUE=10002,
    DUSS_PIXFMT_RAW24_UNPACKED=10012,
    DUSS_PIXFMT_RAW32_OPAQUE=10003,
    DUSS_PIXFMT_RAW32_UNPACKED=10013,
    DUSS_PIXFMT_RAW8_OPAQUE=10000,
    DUSS_PIXFMT_RAW_END=10014,
    DUSS_PIXFMT_RGB101010=20003,
    DUSS_PIXFMT_RGB565=20001,
    DUSS_PIXFMT_RGB888=20000,
    DUSS_PIXFMT_RGBA8888=20002,
    DUSS_PIXFMT_RGBA8888_GOGGLES_V2=20012,
    DUSS_PIXFMT_RGB_END=20004,
    DUSS_PIXFMT_SINGLE_PLANE_16BIT=40001,
    DUSS_PIXFMT_SINGLE_PLANE_8BIT=40000,
    DUSS_PIXFMT_YUV10_420_END=1005,
    DUSS_PIXFMT_YUV10_422_END=1105,
    DUSS_PIXFMT_YUV10_444_END=1203,
    DUSS_PIXFMT_YUV10_P444_YUV=1202,
    DUSS_PIXFMT_YUV10_SP420_YUV=1003,
    DUSS_PIXFMT_YUV10_SP420_YUV16=1001,
    DUSS_PIXFMT_YUV10_SP420_YVU=1004,
    DUSS_PIXFMT_YUV10_SP420_YVU16=1002,
    DUSS_PIXFMT_YUV10_SP422_YUV=1103,
    DUSS_PIXFMT_YUV10_SP422_YUV16=1101,
    DUSS_PIXFMT_YUV10_SP422_YVU=1104,
    DUSS_PIXFMT_YUV10_Y422_YUYV16=1102,
    DUSS_PIXFMT_YUV10_Y444_UYVA=1201,
    DUSS_PIXFMT_YUV8_420_END=4,
    DUSS_PIXFMT_YUV8_422_END=106,
    DUSS_PIXFMT_YUV8_444_END=203,
    DUSS_PIXFMT_YUV8_P420_YUV=1,
    DUSS_PIXFMT_YUV8_P422_YUV=105,
    DUSS_PIXFMT_YUV8_P444_YUV=202,
    DUSS_PIXFMT_YUV8_SP420_YUV=2,
    DUSS_PIXFMT_YUV8_SP420_YVU=3,
    DUSS_PIXFMT_YUV8_SP422_YUV=103,
    DUSS_PIXFMT_YUV8_SP422_YVU=104,
    DUSS_PIXFMT_YUV8_Y422_UYVY=101,
    DUSS_PIXFMT_YUV8_Y422_YUYV=102,
    DUSS_PIXFMT_YUV8_Y444_UYV=201,
    DUSS_PIXFMT_YUV_END=1204
} duss_pixel_format;

typedef enum duss_pixel_format duss_pixel_format_t;

struct duss_object {
    int ref_count;
    struct duss_osal_mutex_handle_t * lock;
    void (* on_released)(struct duss_object *);
};

typedef struct duss_object duss_object_t;

typedef struct duss_hal_mem_buf * duss_hal_mem_handle_t;

typedef struct duss_frame_plane duss_frame_plane, *Pduss_frame_plane;

typedef struct duss_frame_plane duss_frame_plane_t;

struct duss_frame_plane {
    int32_t bytes_per_line;
    int32_t offset;
    int32_t plane_height;
    int32_t bytes_written;
};

struct __attribute__((__packed__)) duss_frame_buffer {
    duss_object_t obj;
    duss_hal_mem_handle_t buffer;
    duss_pixel_format_t pixel_format;
    uint32_t unknown;
    int64_t time_stamp;
    int32_t width;
    int32_t height;
    duss_frame_plane_t planes[4];
    int32_t plane_count;
    uint32_t frame_id;
};

typedef struct duss_frame_buffer duss_frame_buffer_t;

typedef struct duss_hal_device_desc_t duss_hal_device_desc_t, *Pduss_hal_device_desc_t;

typedef struct duss_hal_obj duss_hal_obj, *Pduss_hal_obj;

typedef struct duss_disp_instance_handle_t duss_disp_instance_handle_t, *Pduss_disp_instance_handle_t;

struct __attribute__((__packed__)) duss_disp_instance_handle_t {
    uint8_t is_init;
    uint8_t field_0x1;
    uint8_t field_0x2;
    uint8_t field_0x3;
    uint32_t current_vop_index;
    uint32_t ref_cnt;
    duss_hal_obj_handle_t obj;
    void * instance_private_data;
    void * global_disp_info;
};

typedef uint8_t duss_disp_vop_id_t;

typedef uint8_t duss_disp_plane_type_t;

typedef uint8_t duss_disp_port_id_t;

typedef struct duss_disp_timing_detail_t duss_disp_timing_detail_t, *Pduss_disp_timing_detail_t;

typedef enum duss_disp_timing_bitdepth_t {
    DUSS_DISP_BITDEPTH_10BIT=1,
    DUSS_DISP_BITDEPTH_12BIT=2,
    DUSS_DISP_BITDEPTH_8BIT=0
} duss_disp_timing_bitdepth_t;

typedef enum duss_disp_timing_fmt_t {
    DUSS_DISP_FMT_RGB=0,
    DUSS_DISP_FMT_YUV420=3,
    DUSS_DISP_FMT_YUV422=2,
    DUSS_DISP_FMT_YUV444=1
} duss_disp_timing_fmt_t;

struct duss_disp_timing_detail_t {
    int32_t clock;
    int32_t hdisplay;
    int32_t hsync_start;
    int32_t hsync_end;
    int32_t htotal;
    int32_t hskew;
    int32_t vdisplay;
    int32_t vsync_start;
    int32_t vsync_end;
    int32_t vtotal;
    int32_t vscan;
    enum duss_disp_timing_fmt_t disp_fmt;
    enum duss_disp_timing_bitdepth_t disp_bitdepth;
};

typedef struct duss_disp_plane_blending_t duss_disp_plane_blending_t, *Pduss_disp_plane_blending_t;

typedef uint8_t duss_disp_plane_alpha_alg_t;
typedef int8_t duss_disp_plane_id_t;

struct __attribute__((__packed__)) duss_disp_plane_blending_t {
    uint8_t is_enable;
    uint8_t glb_alpha_en;
    uint8_t field_0x2;
    uint8_t field_0x3;
    int32_t glb_alpha_val;
    duss_disp_plane_alpha_alg_t blending_alg;
    duss_disp_plane_id_t order;
    uint8_t field_0xa;
    uint8_t field_0xb;
    int32_t hoffset;
    int32_t voffset;
};

typedef duss_result_t (frame_pop_handler)(duss_disp_instance_handle_t * , duss_disp_plane_id_t , duss_frame_buffer_t * , void * );

duss_result_t duss_hal_initialize(duss_hal_device_desc_t * );
duss_result_t duss_hal_deinitialize();
duss_result_t duss_hal_device_open(char *device_name, void *unknown, duss_hal_obj_handle_t * );
duss_result_t duss_hal_device_start(duss_hal_obj_handle_t , void * );
duss_result_t duss_hal_device_close(duss_hal_obj_handle_t );
duss_result_t duss_hal_device_stop(duss_hal_obj_handle_t );

duss_result_t duss_hal_mem_alloc(duss_hal_obj_handle_t , duss_hal_mem_handle_t * , uint32_t size, uint32_t , uint32_t , uint32_t );
duss_result_t duss_hal_mem_get_phys_addr(duss_hal_mem_handle_t , void * * );
duss_result_t duss_hal_mem_map(duss_hal_mem_handle_t , void * * );
duss_result_t duss_hal_mem_free(duss_hal_mem_handle_t );
duss_result_t duss_hal_mem_sync(duss_hal_mem_handle_t , uint32_t );

duss_result_t duss_hal_display_open(duss_hal_obj_handle_t , duss_disp_instance_handle_t * * , duss_disp_vop_id_t );
duss_result_t duss_hal_display_close(duss_hal_obj_handle_t , duss_disp_instance_handle_t * *);
// sic
duss_result_t duss_hal_display_aquire_plane(duss_disp_instance_handle_t * , duss_disp_plane_type_t , duss_disp_plane_id_t * );
duss_result_t duss_hal_display_reset(duss_disp_instance_handle_t *);
duss_result_t duss_hal_display_register_frame_cycle_callback(duss_disp_instance_handle_t * , duss_disp_plane_id_t , frame_pop_handler * , void * );
duss_result_t duss_hal_display_timing_detail_get(duss_disp_instance_handle_t * , duss_disp_timing_detail_t * );
duss_result_t duss_hal_display_port_enable(duss_disp_instance_handle_t * , duss_disp_port_id_t , uint8_t );
duss_result_t duss_hal_display_plane_blending_set(duss_disp_instance_handle_t * , duss_disp_plane_id_t , duss_disp_plane_blending_t * );
duss_result_t duss_hal_display_release_plane(duss_disp_instance_handle_t * , duss_disp_plane_id_t );
duss_result_t duss_hal_display_push_frame(duss_disp_instance_handle_t * , duss_disp_plane_id_t , duss_frame_buffer_t * );

duss_result_t duss_hal_attach_disp(char *param_1,duss_hal_obj **param_2);
duss_result_t duss_hal_attach_ion_mem(char *param_1,duss_hal_obj **param_2);
duss_result_t duss_hal_detach_ion_mem();
duss_result_t duss_hal_detach_disp();


================================================
FILE: jni/json/osd_config.c
================================================
#include "parson.h"
#define JSON_CONFIG_PATH "/opt/etc/package-config/msp-osd/config.json"
static JSON_Object *root_object = NULL;
static void load_config() {
   JSON_Value *root_value = NULL;
    if(root_object == NULL) {
        root_value = json_parse_file(JSON_CONFIG_PATH);
        if (json_value_get_type(root_value) != JSONObject) {
            return;
        }
        root_object = json_value_get_object(root_value);
    }
}

int get_boolean_config_value(const char* key) {
    load_config();
    if (root_object != NULL) {
        // parson returns -1 for undefined keys, which can happen when
        // new keys are defined in the schema - ensure they come back as false
        return json_object_get_boolean(root_object, key) > 0;
    } else {
        return 0;
    }
}

const char * get_string_config_value(const char *key)
{
    load_config();
    if (root_object != NULL)
    {
        return json_object_get_string(root_object, key);
    }
    else
    {
        return NULL;
    }
}

int get_integer_config_value(const char *key)
{
    load_config();
    if (root_object != NULL)
    {
        return (int)json_object_get_number(root_object, key);
    }
    else
    {
        return 0;
    }
}

================================================
FILE: jni/json/osd_config.h
================================================
int get_boolean_config_value(const char* key);
const char *get_string_config_value(const char *key);
int get_integer_config_value(const char *key);

================================================
FILE: jni/json/parson.c
================================================
/*
 SPDX-License-Identifier: MIT

 Parson 1.4.0 (https://github.com/kgabis/parson)
 Copyright (c) 2012 - 2022 Krzysztof Gabis

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/
#ifdef _MSC_VER
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif /* _CRT_SECURE_NO_WARNINGS */
#endif /* _MSC_VER */

#include "parson.h"

#define PARSON_IMPL_VERSION_MAJOR 1
#define PARSON_IMPL_VERSION_MINOR 4
#define PARSON_IMPL_VERSION_PATCH 0

#if (PARSON_VERSION_MAJOR != PARSON_IMPL_VERSION_MAJOR)\
|| (PARSON_VERSION_MINOR != PARSON_IMPL_VERSION_MINOR)\
|| (PARSON_VERSION_PATCH != PARSON_IMPL_VERSION_PATCH)
#error "parson version mismatch between parson.c and parson.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <errno.h>

/* Apparently sscanf is not implemented in some "standard" libraries, so don't use it, if you
 * don't have to. */
#ifdef sscanf
#undef sscanf
#define sscanf THINK_TWICE_ABOUT_USING_SSCANF
#endif

/* strcpy is unsafe */
#ifdef strcpy
#undef strcpy
#endif
#define strcpy USE_MEMCPY_INSTEAD_OF_STRCPY

#define STARTING_CAPACITY 16
#define MAX_NESTING       2048

#ifndef PARSON_DEFAULT_FLOAT_FORMAT
#define PARSON_DEFAULT_FLOAT_FORMAT "%1.17g" /* do not increase precision without incresing NUM_BUF_SIZE */
#endif

#ifndef PARSON_NUM_BUF_SIZE
#define PARSON_NUM_BUF_SIZE 64 /* double printed with "%1.17g" shouldn't be longer than 25 bytes so let's be paranoid and use 64 */
#endif

#define SIZEOF_TOKEN(a)       (sizeof(a) - 1)
#define SKIP_CHAR(str)        ((*str)++)
#define SKIP_WHITESPACES(str) while (isspace((unsigned char)(**str))) { SKIP_CHAR(str); }
#define MAX(a, b)             ((a) > (b) ? (a) : (b))

#undef malloc
#undef free

#if defined(isnan) && defined(isinf)
#define IS_NUMBER_INVALID(x) (isnan((x)) || isinf((x)))
#else
#define IS_NUMBER_INVALID(x) (((x) * 0.0) != 0.0)
#endif

#define OBJECT_INVALID_IX ((size_t)-1)

static JSON_Malloc_Function parson_malloc = malloc;
static JSON_Free_Function parson_free = free;

static int parson_escape_slashes = 1;

static char *parson_float_format = NULL;

#define IS_CONT(b) (((unsigned char)(b) & 0xC0) == 0x80) /* is utf-8 continuation byte */

typedef int parson_bool_t;

#define PARSON_TRUE 1
#define PARSON_FALSE 0

typedef struct json_string {
    char *chars;
    size_t length;
} JSON_String;

/* Type definitions */
typedef union json_value_value {
    JSON_String  string;
    double       number;
    JSON_Object *object;
    JSON_Array  *array;
    int          boolean;
    int          null;
} JSON_Value_Value;

struct json_value_t {
    JSON_Value      *parent;
    JSON_Value_Type  type;
    JSON_Value_Value value;
};

struct json_object_t {
    JSON_Value    *wrapping_value;
    size_t        *cells;
    unsigned long *hashes;
    char         **names;
    JSON_Value   **values;
    size_t        *cell_ixs;
    size_t         count;
    size_t         item_capacity;
    size_t         cell_capacity;
};

struct json_array_t {
    JSON_Value  *wrapping_value;
    JSON_Value **items;
    size_t       count;
    size_t       capacity;
};

/* Various */
static char * read_file(const char *filename);
static void   remove_comments(char *string, const char *start_token, const char *end_token);
static char * parson_strndup(const char *string, size_t n);
static char * parson_strdup(const char *string);
static int    hex_char_to_int(char c);
static JSON_Status parse_utf16_hex(const char *string, unsigned int *result);
static int         num_bytes_in_utf8_sequence(unsigned char c);
static JSON_Status   verify_utf8_sequence(const unsigned char *string, int *len);
static parson_bool_t is_valid_utf8(const char *string, size_t string_len);
static parson_bool_t is_decimal(const char *string, size_t length);
static unsigned long hash_string(const char *string, size_t n);

/* JSON Object */
static JSON_Object * json_object_make(JSON_Value *wrapping_value);
static JSON_Status   json_object_init(JSON_Object *object, size_t capacity);
static void          json_object_deinit(JSON_Object *object, parson_bool_t free_keys, parson_bool_t free_values);
static JSON_Status   json_object_grow_and_rehash(JSON_Object *object);
static size_t        json_object_get_cell_ix(const JSON_Object *object, const char *key, size_t key_len, unsigned long hash, parson_bool_t *out_found);
static JSON_Status   json_object_add(JSON_Object *object, char *name, JSON_Value *value);
static JSON_Value  * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len);
static JSON_Status   json_object_remove_internal(JSON_Object *object, const char *name, parson_bool_t free_value);
static JSON_Status   json_object_dotremove_internal(JSON_Object *object, const char *name, parson_bool_t free_value);
static void          json_object_free(JSON_Object *object);

/* JSON Array */
static JSON_Array * json_array_make(JSON_Value *wrapping_value);
static JSON_Status  json_array_add(JSON_Array *array, JSON_Value *value);
static JSON_Status  json_array_resize(JSON_Array *array, size_t new_capacity);
static void         json_array_free(JSON_Array *array);

/* JSON Value */
static JSON_Value * json_value_init_string_no_copy(char *string, size_t length);
static const JSON_String * json_value_get_string_desc(const JSON_Value *value);

/* Parser */
static JSON_Status   skip_quotes(const char **string);
static JSON_Status   parse_utf16(const char **unprocessed, char **processed);
static char *        process_string(const char *input, size_t input_len, size_t *output_len);
static char *        get_quoted_string(const char **string, size_t *output_string_len);
static JSON_Value *  parse_object_value(const char **string, size_t nesting);
static JSON_Value *  parse_array_value(const char **string, size_t nesting);
static JSON_Value *  parse_string_value(const char **string);
static JSON_Value *  parse_boolean_value(const char **string);
static JSON_Value *  parse_number_value(const char **string);
static JSON_Value *  parse_null_value(const char **string);
static JSON_Value *  parse_value(const char **string, size_t nesting);

/* Serialization */
static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, parson_bool_t is_pretty, char *num_buf);
static int json_serialize_string(const char *string, size_t len, char *buf);
static int append_indent(char *buf, int level);
static int append_string(char *buf, const char *string);

/* Various */
static char * read_file(const char * filename) {
    FILE *fp = fopen(filename, "r");
    size_t size_to_read = 0;
    size_t size_read = 0;
    long pos;
    char *file_contents;
    if (!fp) {
        return NULL;
    }
    fseek(fp, 0L, SEEK_END);
    pos = ftell(fp);
    if (pos < 0) {
        fclose(fp);
        return NULL;
    }
    size_to_read = pos;
    rewind(fp);
    file_contents = (char*)parson_malloc(sizeof(char) * (size_to_read + 1));
    if (!file_contents) {
        fclose(fp);
        return NULL;
    }
    size_read = fread(file_contents, 1, size_to_read, fp);
    if (size_read == 0 || ferror(fp)) {
        fclose(fp);
        parson_free(file_contents);
        return NULL;
    }
    fclose(fp);
    file_contents[size_read] = '\0';
    return file_contents;
}

static void remove_comments(char *string, const char *start_token, const char *end_token) {
    parson_bool_t in_string = PARSON_FALSE, escaped = PARSON_FALSE;
    size_t i;
    char *ptr = NULL, current_char;
    size_t start_token_len = strlen(start_token);
    size_t end_token_len = strlen(end_token);
    if (start_token_len == 0 || end_token_len == 0) {
        return;
    }
    while ((current_char = *string) != '\0') {
        if (current_char == '\\' && !escaped) {
            escaped = PARSON_TRUE;
            string++;
            continue;
        } else if (current_char == '\"' && !escaped) {
            in_string = !in_string;
        } else if (!in_string && strncmp(string, start_token, start_token_len) == 0) {
            for(i = 0; i < start_token_len; i++) {
                string[i] = ' ';
            }
            string = string + start_token_len;
            ptr = strstr(string, end_token);
            if (!ptr) {
                return;
            }
            for (i = 0; i < (ptr - string) + end_token_len; i++) {
                string[i] = ' ';
            }
            string = ptr + end_token_len - 1;
        }
        escaped = PARSON_FALSE;
        string++;
    }
}

static char * parson_strndup(const char *string, size_t n) {
    /* We expect the caller has validated that 'n' fits within the input buffer. */
    char *output_string = (char*)parson_malloc(n + 1);
    if (!output_string) {
        return NULL;
    }
    output_string[n] = '\0';
    memcpy(output_string, string, n);
    return output_string;
}

static char * parson_strdup(const char *string) {
    return parson_strndup(string, strlen(string));
}

static int hex_char_to_int(char c) {
    if (c >= '0' && c <= '9') {
        return c - '0';
    } else if (c >= 'a' && c <= 'f') {
        return c - 'a' + 10;
    } else if (c >= 'A' && c <= 'F') {
        return c - 'A' + 10;
    }
    return -1;
}

static JSON_Status parse_utf16_hex(const char *s, unsigned int *result) {
    int x1, x2, x3, x4;
    if (s[0] == '\0' || s[1] == '\0' || s[2] == '\0' || s[3] == '\0') {
        return JSONFailure;
    }
    x1 = hex_char_to_int(s[0]);
    x2 = hex_char_to_int(s[1]);
    x3 = hex_char_to_int(s[2]);
    x4 = hex_char_to_int(s[3]);
    if (x1 == -1 || x2 == -1 || x3 == -1 || x4 == -1) {
        return JSONFailure;
    }
    *result = (unsigned int)((x1 << 12) | (x2 << 8) | (x3 << 4) | x4);
    return JSONSuccess;
}

static int num_bytes_in_utf8_sequence(unsigned char c) {
    if (c == 0xC0 || c == 0xC1 || c > 0xF4 || IS_CONT(c)) {
        return 0;
    } else if ((c & 0x80) == 0) {    /* 0xxxxxxx */
        return 1;
    } else if ((c & 0xE0) == 0xC0) { /* 110xxxxx */
        return 2;
    } else if ((c & 0xF0) == 0xE0) { /* 1110xxxx */
        return 3;
    } else if ((c & 0xF8) == 0xF0) { /* 11110xxx */
        return 4;
    }
    return 0; /* won't happen */
}

static JSON_Status verify_utf8_sequence(const unsigned char *string, int *len) {
    unsigned int cp = 0;
    *len = num_bytes_in_utf8_sequence(string[0]);

    if (*len == 1) {
        cp = string[0];
    } else if (*len == 2 && IS_CONT(string[1])) {
        cp = string[0] & 0x1F;
        cp = (cp << 6) | (string[1] & 0x3F);
    } else if (*len == 3 && IS_CONT(string[1]) && IS_CONT(string[2])) {
        cp = ((unsigned char)string[0]) & 0xF;
        cp = (cp << 6) | (string[1] & 0x3F);
        cp = (cp << 6) | (string[2] & 0x3F);
    } else if (*len == 4 && IS_CONT(string[1]) && IS_CONT(string[2]) && IS_CONT(string[3])) {
        cp = string[0] & 0x7;
        cp = (cp << 6) | (string[1] & 0x3F);
        cp = (cp << 6) | (string[2] & 0x3F);
        cp = (cp << 6) | (string[3] & 0x3F);
    } else {
        return JSONFailure;
    }

    /* overlong encodings */
    if ((cp < 0x80    && *len > 1) ||
        (cp < 0x800   && *len > 2) ||
        (cp < 0x10000 && *len > 3)) {
        return JSONFailure;
    }

    /* invalid unicode */
    if (cp > 0x10FFFF) {
        return JSONFailure;
    }

    /* surrogate halves */
    if (cp >= 0xD800 && cp <= 0xDFFF) {
        return JSONFailure;
    }

    return JSONSuccess;
}

static int is_valid_utf8(const char *string, size_t string_len) {
    int len = 0;
    const char *string_end =  string + string_len;
    while (string < string_end) {
        if (verify_utf8_sequence((const unsigned char*)string, &len) != JSONSuccess) {
            return PARSON_FALSE;
        }
        string += len;
    }
    return PARSON_TRUE;
}

static parson_bool_t is_decimal(const char *string, size_t length) {
    if (length > 1 && string[0] == '0' && string[1] != '.') {
        return PARSON_FALSE;
    }
    if (length > 2 && !strncmp(string, "-0", 2) && string[2] != '.') {
        return PARSON_FALSE;
    }
    while (length--) {
        if (strchr("xX", string[length])) {
            return PARSON_FALSE;
        }
    }
    return PARSON_TRUE;
}

static unsigned long hash_string(const char *string, size_t n) {
#ifdef PARSON_FORCE_HASH_COLLISIONS
    (void)string;
    (void)n;
    return 0;
#else
    unsigned long hash = 5381;
    unsigned char c;
    size_t i = 0;
    for (i = 0; i < n; i++) {
        c = string[i];
        if (c == '\0') {
            break;
        }
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
    }
    return hash;
#endif
}

/* JSON Object */
static JSON_Object * json_object_make(JSON_Value *wrapping_value) {
    JSON_Status res = JSONFailure;
    JSON_Object *new_obj = (JSON_Object*)parson_malloc(sizeof(JSON_Object));
    if (new_obj == NULL) {
        return NULL;
    }
    new_obj->wrapping_value = wrapping_value;
    res = json_object_init(new_obj, 0);
    if (res != JSONSuccess) {
        parson_free(new_obj);
        return NULL;
    }
    return new_obj;
}

static JSON_Status json_object_init(JSON_Object *object, size_t capacity) {
    unsigned int i = 0;

    object->cells = NULL;
    object->names = NULL;
    object->values = NULL;
    object->cell_ixs = NULL;
    object->hashes = NULL;

    object->count = 0;
    object->cell_capacity = capacity;
    object->item_capacity = (unsigned int)(capacity * 0.7f);

    if (capacity == 0) {
        return JSONSuccess;
    }

    object->cells = (size_t*)parson_malloc(object->cell_capacity * sizeof(*object->cells));
    object->names = (char**)parson_malloc(object->item_capacity * sizeof(*object->names));
    object->values = (JSON_Value**)parson_malloc(object->item_capacity * sizeof(*object->values));
    object->cell_ixs = (size_t*)parson_malloc(object->item_capacity * sizeof(*object->cell_ixs));
    object->hashes = (unsigned long*)parson_malloc(object->item_capacity * sizeof(*object->hashes));
    if (object->cells == NULL
        || object->names == NULL
        || object->values == NULL
        || object->cell_ixs == NULL
        || object->hashes == NULL) {
        goto error;
    }
    for (i = 0; i < object->cell_capacity; i++) {
        object->cells[i] = OBJECT_INVALID_IX;
    }
    return JSONSuccess;
error:
    parson_free(object->cells);
    parson_free(object->names);
    parson_free(object->values);
    parson_free(object->cell_ixs);
    parson_free(object->hashes);
    return JSONFailure;
}

static void json_object_deinit(JSON_Object *object, parson_bool_t free_keys, parson_bool_t free_values) {
    unsigned int i = 0;
    for (i = 0; i < object->count; i++) {
        if (free_keys) {
            parson_free(object->names[i]);
        }
        if (free_values) {
            json_value_free(object->values[i]);
        }
    }

    object->count = 0;
    object->item_capacity = 0;
    object->cell_capacity = 0;

    parson_free(object->cells);
    parson_free(object->names);
    parson_free(object->values);
    parson_free(object->cell_ixs);
    parson_free(object->hashes);

    object->cells = NULL;
    object->names = NULL;
    object->values = NULL;
    object->cell_ixs = NULL;
    object->hashes = NULL;
}

static JSON_Status json_object_grow_and_rehash(JSON_Object *object) {
    JSON_Value *wrapping_value = NULL;
    JSON_Object new_object;
    char *key = NULL;
    JSON_Value *value = NULL;
    unsigned int i = 0;
    size_t new_capacity = MAX(object->cell_capacity * 2, STARTING_CAPACITY);
    JSON_Status res = json_object_init(&new_object, new_capacity);
    if (res != JSONSuccess) {
        return JSONFailure;
    }

    wrapping_value = json_object_get_wrapping_value(object);
    new_object.wrapping_value = wrapping_value;

    for (i = 0; i < object->count; i++) {
        key = object->names[i];
        value = object->values[i];
        res = json_object_add(&new_object, key, value);
        if (res != JSONSuccess) {
            json_object_deinit(&new_object, PARSON_FALSE, PARSON_FALSE);
            return JSONFailure;
        }
        value->parent = wrapping_value;
    }
    json_object_deinit(object, PARSON_FALSE, PARSON_FALSE);
    *object = new_object;
    return JSONSuccess;
}

static size_t json_object_get_cell_ix(const JSON_Object *object, const char *key, size_t key_len, unsigned long hash, parson_bool_t *out_found) {
    size_t cell_ix = hash & (object->cell_capacity - 1);
    size_t cell = 0;
    size_t ix = 0;
    unsigned int i = 0;
    unsigned long hash_to_check = 0;
    const char *key_to_check = NULL;
    size_t key_to_check_len = 0;

    *out_found = PARSON_FALSE;

    for (i = 0; i < object->cell_capacity; i++) {
        ix = (cell_ix + i) & (object->cell_capacity - 1);
        cell = object->cells[ix];
        if (cell == OBJECT_INVALID_IX) {
            return ix;
        }
        hash_to_check = object->hashes[cell];
        if (hash != hash_to_check) {
            continue;
        }
        key_to_check = object->names[cell];
        key_to_check_len = strlen(key_to_check);
        if (key_to_check_len == key_len && strncmp(key, key_to_check, key_len) == 0) {
            *out_found = PARSON_TRUE;
            return ix;
        }
    }
    return OBJECT_INVALID_IX;
}

static JSON_Status json_object_add(JSON_Object *object, char *name, JSON_Value *value) {
    unsigned long hash = 0;
    parson_bool_t found = PARSON_FALSE;
    size_t cell_ix = 0;
    JSON_Status res = JSONFailure;

    if (!object || !name || !value) {
        return JSONFailure;
    }

    hash = hash_string(name, strlen(name));
    found = PARSON_FALSE;
    cell_ix = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
    if (found) {
        return JSONFailure;
    }

    if (object->count >= object->item_capacity) {
        res = json_object_grow_and_rehash(object);
        if (res != JSONSuccess) {
            return JSONFailure;
        }
        cell_ix = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
    }

    object->names[object->count] = name;
    object->cells[cell_ix] = object->count;
    object->values[object->count] = value;
    object->cell_ixs[object->count] = cell_ix;
    object->hashes[object->count] = hash;
    object->count++;
    value->parent = json_object_get_wrapping_value(object);

    return JSONSuccess;
}

static JSON_Value * json_object_getn_value(const JSON_Object *object, const char *name, size_t name_len) {
    unsigned long hash = 0;
    parson_bool_t found = PARSON_FALSE;
    size_t cell_ix = 0;
    size_t item_ix = 0;
    if (!object || !name) {
        return NULL;
    }
    hash = hash_string(name, name_len);
    found = PARSON_FALSE;
    cell_ix = json_object_get_cell_ix(object, name, name_len, hash, &found);
    if (!found) {
        return NULL;
    }
    item_ix = object->cells[cell_ix];
    return object->values[item_ix];
}

static JSON_Status json_object_remove_internal(JSON_Object *object, const char *name, parson_bool_t free_value) {
    unsigned long hash = 0;
    parson_bool_t found = PARSON_FALSE;
    size_t cell = 0;
    size_t item_ix = 0;
    size_t last_item_ix = 0;
    size_t i = 0;
    size_t j = 0;
    size_t x = 0;
    size_t k = 0;
    JSON_Value *val = NULL;

    if (object == NULL) {
        return JSONFailure;
    }

    hash = hash_string(name, strlen(name));
    found = PARSON_FALSE;
    cell = json_object_get_cell_ix(object, name, strlen(name), hash, &found);
    if (!found) {
        return JSONFailure;
    }

    item_ix = object->cells[cell];
    if (free_value) {
        val = object->values[item_ix];
        json_value_free(val);
        val = NULL;
    }

    parson_free(object->names[item_ix]);
    last_item_ix = object->count - 1;
    if (item_ix < last_item_ix) {
        object->names[item_ix] = object->names[last_item_ix];
        object->values[item_ix] = object->values[last_item_ix];
        object->cell_ixs[item_ix] = object->cell_ixs[last_item_ix];
        object->hashes[item_ix] = object->hashes[last_item_ix];
        object->cells[object->cell_ixs[item_ix]] = item_ix;
    }
    object->count--;

    i = cell;
    j = i;
    for (x = 0; x < (object->cell_capacity - 1); x++) {
        j = (j + 1) & (object->cell_capacity - 1);
        if (object->cells[j] == OBJECT_INVALID_IX) {
            break;
        }
        k = object->hashes[object->cells[j]] & (object->cell_capacity - 1);
        if ((j > i && (k <= i || k > j))
         || (j < i && (k <= i && k > j))) {
            object->cell_ixs[object->cells[j]] = i;
            object->cells[i] = object->cells[j];
            i = j;
        }
    }
    object->cells[i] = OBJECT_INVALID_IX;
    return JSONSuccess;
}

static JSON_Status json_object_dotremove_internal(JSON_Object *object, const char *name, parson_bool_t free_value) {
    JSON_Value *temp_value = NULL;
    JSON_Object *temp_object = NULL;
    const char *dot_pos = strchr(name, '.');
    if (!dot_pos) {
        return json_object_remove_internal(object, name, free_value);
    }
    temp_value = json_object_getn_value(object, name, dot_pos - name);
    if (json_value_get_type(temp_value) != JSONObject) {
        return JSONFailure;
    }
    temp_object = json_value_get_object(temp_value);
    return json_object_dotremove_internal(temp_object, dot_pos + 1, free_value);
}

static void json_object_free(JSON_Object *object) {
    json_object_deinit(object, PARSON_TRUE, PARSON_TRUE);
    parson_free(object);
}

/* JSON Array */
static JSON_Array * json_array_make(JSON_Value *wrapping_value) {
    JSON_Array *new_array = (JSON_Array*)parson_malloc(sizeof(JSON_Array));
    if (new_array == NULL) {
        return NULL;
    }
    new_array->wrapping_value = wrapping_value;
    new_array->items = (JSON_Value**)NULL;
    new_array->capacity = 0;
    new_array->count = 0;
    return new_array;
}

static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) {
    if (array->count >= array->capacity) {
        size_t new_capacity = MAX(array->capacity * 2, STARTING_CAPACITY);
        if (json_array_resize(array, new_capacity) != JSONSuccess) {
            return JSONFailure;
        }
    }
    value->parent = json_array_get_wrapping_value(array);
    array->items[array->count] = value;
    array->count++;
    return JSONSuccess;
}

static JSON_Status json_array_resize(JSON_Array *array, size_t new_capacity) {
    JSON_Value **new_items = NULL;
    if (new_capacity == 0) {
        return JSONFailure;
    }
    new_items = (JSON_Value**)parson_malloc(new_capacity * sizeof(JSON_Value*));
    if (new_items == NULL) {
        return JSONFailure;
    }
    if (array->items != NULL && array->count > 0) {
        memcpy(new_items, array->items, array->count * sizeof(JSON_Value*));
    }
    parson_free(array->items);
    array->items = new_items;
    array->capacity = new_capacity;
    return JSONSuccess;
}

static void json_array_free(JSON_Array *array) {
    size_t i;
    for (i = 0; i < array->count; i++) {
        json_value_free(array->items[i]);
    }
    parson_free(array->items);
    parson_free(array);
}

/* JSON Value */
static JSON_Value * json_value_init_string_no_copy(char *string, size_t length) {
    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
    if (!new_value) {
        return NULL;
    }
    new_value->parent = NULL;
    new_value->type = JSONString;
    new_value->value.string.chars = string;
    new_value->value.string.length = length;
    return new_value;
}

/* Parser */
static JSON_Status skip_quotes(const char **string) {
    if (**string != '\"') {
        return JSONFailure;
    }
    SKIP_CHAR(string);
    while (**string != '\"') {
        if (**string == '\0') {
            return JSONFailure;
        } else if (**string == '\\') {
            SKIP_CHAR(string);
            if (**string == '\0') {
                return JSONFailure;
            }
        }
        SKIP_CHAR(string);
    }
    SKIP_CHAR(string);
    return JSONSuccess;
}

static JSON_Status parse_utf16(const char **unprocessed, char **processed) {
    unsigned int cp, lead, trail;
    char *processed_ptr = *processed;
    const char *unprocessed_ptr = *unprocessed;
    JSON_Status status = JSONFailure;
    unprocessed_ptr++; /* skips u */
    status = parse_utf16_hex(unprocessed_ptr, &cp);
    if (status != JSONSuccess) {
        return JSONFailure;
    }
    if (cp < 0x80) {
        processed_ptr[0] = (char)cp; /* 0xxxxxxx */
    } else if (cp < 0x800) {
        processed_ptr[0] = ((cp >> 6) & 0x1F) | 0xC0; /* 110xxxxx */
        processed_ptr[1] = ((cp)      & 0x3F) | 0x80; /* 10xxxxxx */
        processed_ptr += 1;
    } else if (cp < 0xD800 || cp > 0xDFFF) {
        processed_ptr[0] = ((cp >> 12) & 0x0F) | 0xE0; /* 1110xxxx */
        processed_ptr[1] = ((cp >> 6)  & 0x3F) | 0x80; /* 10xxxxxx */
        processed_ptr[2] = ((cp)       & 0x3F) | 0x80; /* 10xxxxxx */
        processed_ptr += 2;
    } else if (cp >= 0xD800 && cp <= 0xDBFF) { /* lead surrogate (0xD800..0xDBFF) */
        lead = cp;
        unprocessed_ptr += 4; /* should always be within the buffer, otherwise previous sscanf would fail */
        if (*unprocessed_ptr++ != '\\' || *unprocessed_ptr++ != 'u') {
            return JSONFailure;
        }
        status = parse_utf16_hex(unprocessed_ptr, &trail);
        if (status != JSONSuccess || trail < 0xDC00 || trail > 0xDFFF) { /* valid trail surrogate? (0xDC00..0xDFFF) */
            return JSONFailure;
        }
        cp = ((((lead - 0xD800) & 0x3FF) << 10) | ((trail - 0xDC00) & 0x3FF)) + 0x010000;
        processed_ptr[0] = (((cp >> 18) & 0x07) | 0xF0); /* 11110xxx */
        processed_ptr[1] = (((cp >> 12) & 0x3F) | 0x80); /* 10xxxxxx */
        processed_ptr[2] = (((cp >> 6)  & 0x3F) | 0x80); /* 10xxxxxx */
        processed_ptr[3] = (((cp)       & 0x3F) | 0x80); /* 10xxxxxx */
        processed_ptr += 3;
    } else { /* trail surrogate before lead surrogate */
        return JSONFailure;
    }
    unprocessed_ptr += 3;
    *processed = processed_ptr;
    *unprocessed = unprocessed_ptr;
    return JSONSuccess;
}


/* Copies and processes passed string up to supplied length.
Example: "\u006Corem ipsum" -> lorem ipsum */
static char* process_string(const char *input, size_t input_len, size_t *output_len) {
    const char *input_ptr = input;
    size_t initial_size = (input_len + 1) * sizeof(char);
    size_t final_size = 0;
    char *output = NULL, *output_ptr = NULL, *resized_output = NULL;
    output = (char*)parson_malloc(initial_size);
    if (output == NULL) {
        goto error;
    }
    output_ptr = output;
    while ((*input_ptr != '\0') && (size_t)(input_ptr - input) < input_len) {
        if (*input_ptr == '\\') {
            input_ptr++;
            switch (*input_ptr) {
                case '\"': *output_ptr = '\"'; break;
                case '\\': *output_ptr = '\\'; break;
                case '/':  *output_ptr = '/';  break;
                case 'b':  *output_ptr = '\b'; break;
                case 'f':  *output_ptr = '\f'; break;
                case 'n':  *output_ptr = '\n'; break;
                case 'r':  *output_ptr = '\r'; break;
                case 't':  *output_ptr = '\t'; break;
                case 'u':
                    if (parse_utf16(&input_ptr, &output_ptr) != JSONSuccess) {
                        goto error;
                    }
                    break;
                default:
                    goto error;
            }
        } else if ((unsigned char)*input_ptr < 0x20) {
            goto error; /* 0x00-0x19 are invalid characters for json string (http://www.ietf.org/rfc/rfc4627.txt) */
        } else {
            *output_ptr = *input_ptr;
        }
        output_ptr++;
        input_ptr++;
    }
    *output_ptr = '\0';
    /* resize to new length */
    final_size = (size_t)(output_ptr-output) + 1;
    /* todo: don't resize if final_size == initial_size */
    resized_output = (char*)parson_malloc(final_size);
    if (resized_output == NULL) {
        goto error;
    }
    memcpy(resized_output, output, final_size);
    *output_len = final_size - 1;
    parson_free(output);
    return resized_output;
error:
    parson_free(output);
    return NULL;
}

/* Return processed contents of a string between quotes and
   skips passed argument to a matching quote. */
static char * get_quoted_string(const char **string, size_t *output_string_len) {
    const char *string_start = *string;
    size_t input_string_len = 0;
    JSON_Status status = skip_quotes(string);
    if (status != JSONSuccess) {
        return NULL;
    }
    input_string_len = *string - string_start - 2; /* length without quotes */
    return process_string(string_start + 1, input_string_len, output_string_len);
}

static JSON_Value * parse_value(const char **string, size_t nesting) {
    if (nesting > MAX_NESTING) {
        return NULL;
    }
    SKIP_WHITESPACES(string);
    switch (**string) {
        case '{':
            return parse_object_value(string, nesting + 1);
        case '[':
            return parse_array_value(string, nesting + 1);
        case '\"':
            return parse_string_value(string);
        case 'f': case 't':
            return parse_boolean_value(string);
        case '-':
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
            return parse_number_value(string);
        case 'n':
            return parse_null_value(string);
        default:
            return NULL;
    }
}

static JSON_Value * parse_object_value(const char **string, size_t nesting) {
    JSON_Status status = JSONFailure;
    JSON_Value *output_value = NULL, *new_value = NULL;
    JSON_Object *output_object = NULL;
    char *new_key = NULL;

    output_value = json_value_init_object();
    if (output_value == NULL) {
        return NULL;
    }
    if (**string != '{') {
        json_value_free(output_value);
        return NULL;
    }
    output_object = json_value_get_object(output_value);
    SKIP_CHAR(string);
    SKIP_WHITESPACES(string);
    if (**string == '}') { /* empty object */
        SKIP_CHAR(string);
        return output_value;
    }
    while (**string != '\0') {
        size_t key_len = 0;
        new_key = get_quoted_string(string, &key_len);
        /* We do not support key names with embedded \0 chars */
        if (!new_key) {
            json_value_free(output_value);
            return NULL;
        }
        if (key_len != strlen(new_key)) {
            parson_free(new_key);
            json_value_free(output_value);
            return NULL;
        }
        SKIP_WHITESPACES(string);
        if (**string != ':') {
            parson_free(new_key);
            json_value_free(output_value);
            return NULL;
        }
        SKIP_CHAR(string);
        new_value = parse_value(string, nesting);
        if (new_value == NULL) {
            parson_free(new_key);
            json_value_free(output_value);
            return NULL;
        }
        status = json_object_add(output_object, new_key, new_value);
        if (status != JSONSuccess) {
            parson_free(new_key);
            json_value_free(new_value);
            json_value_free(output_value);
            return NULL;
        }
        SKIP_WHITESPACES(string);
        if (**string != ',') {
            break;
        }
        SKIP_CHAR(string);
        SKIP_WHITESPACES(string);
        if (**string == '}') {
            break;
        }
    }
    SKIP_WHITESPACES(string);
    if (**string != '}') {
        json_value_free(output_value);
        return NULL;
    }
    SKIP_CHAR(string);
    return output_value;
}

static JSON_Value * parse_array_value(const char **string, size_t nesting) {
    JSON_Value *output_value = NULL, *new_array_value = NULL;
    JSON_Array *output_array = NULL;
    output_value = json_value_init_array();
    if (output_value == NULL) {
        return NULL;
    }
    if (**string != '[') {
        json_value_free(output_value);
        return NULL;
    }
    output_array = json_value_get_array(output_value);
    SKIP_CHAR(string);
    SKIP_WHITESPACES(string);
    if (**string == ']') { /* empty array */
        SKIP_CHAR(string);
        return output_value;
    }
    while (**string != '\0') {
        new_array_value = parse_value(string, nesting);
        if (new_array_value == NULL) {
            json_value_free(output_value);
            return NULL;
        }
        if (json_array_add(output_array, new_array_value) != JSONSuccess) {
            json_value_free(new_array_value);
            json_value_free(output_value);
            return NULL;
        }
        SKIP_WHITESPACES(string);
        if (**string != ',') {
            break;
        }
        SKIP_CHAR(string);
        SKIP_WHITESPACES(string);
        if (**string == ']') {
            break;
        }
    }
    SKIP_WHITESPACES(string);
    if (**string != ']' || /* Trim array after parsing is over */
        json_array_resize(output_array, json_array_get_count(output_array)) != JSONSuccess) {
            json_value_free(output_value);
            return NULL;
    }
    SKIP_CHAR(string);
    return output_value;
}

static JSON_Value * parse_string_value(const char **string) {
    JSON_Value *value = NULL;
    size_t new_string_len = 0;
    char *new_string = get_quoted_string(string, &new_string_len);
    if (new_string == NULL) {
        return NULL;
    }
    value = json_value_init_string_no_copy(new_string, new_string_len);
    if (value == NULL) {
        parson_free(new_string);
        return NULL;
    }
    return value;
}

static JSON_Value * parse_boolean_value(const char **string) {
    size_t true_token_size = SIZEOF_TOKEN("true");
    size_t false_token_size = SIZEOF_TOKEN("false");
    if (strncmp("true", *string, true_token_size) == 0) {
        *string += true_token_size;
        return json_value_init_boolean(1);
    } else if (strncmp("false", *string, false_token_size) == 0) {
        *string += false_token_size;
        return json_value_init_boolean(0);
    }
    return NULL;
}

static JSON_Value * parse_number_value(const char **string) {
    char *end;
    double number = 0;
    errno = 0;
    number = strtod(*string, &end);
    if (errno == ERANGE && (number <= -HUGE_VAL || number >= HUGE_VAL)) {
        return NULL;
    }
    if ((errno && errno != ERANGE) || !is_decimal(*string, end - *string)) {
        return NULL;
    }
    *string = end;
    return json_value_init_number(number);
}

static JSON_Value * parse_null_value(const char **string) {
    size_t token_size = SIZEOF_TOKEN("null");
    if (strncmp("null", *string, token_size) == 0) {
        *string += token_size;
        return json_value_init_null();
    }
    return NULL;
}

/* Serialization */
#define APPEND_STRING(str) do { written = append_string(buf, (str));\
                                if (written < 0) { return -1; }\
                                if (buf != NULL) { buf += written; }\
                                written_total += written; } while(0)

#define APPEND_INDENT(level) do { written = append_indent(buf, (level));\
                                  if (written < 0) { return -1; }\
                                  if (buf != NULL) { buf += written; }\
                                  written_total += written; } while(0)

static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf, int level, parson_bool_t is_pretty, char *num_buf)
{
    const char *key = NULL, *string = NULL;
    JSON_Value *temp_value = NULL;
    JSON_Array *array = NULL;
    JSON_Object *object = NULL;
    size_t i = 0, count = 0;
    double num = 0.0;
    int written = -1, written_total = 0;
    size_t len = 0;

    switch (json_value_get_type(value)) {
        case JSONArray:
            array = json_value_get_array(value);
            count = json_array_get_count(array);
            APPEND_STRING("[");
            if (count > 0 && is_pretty) {
                APPEND_STRING("\n");
            }
            for (i = 0; i < count; i++) {
                if (is_pretty) {
                    APPEND_INDENT(level+1);
                }
                temp_value = json_array_get_value(array, i);
                written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
                if (written < 0) {
                    return -1;
                }
                if (buf != NULL) {
                    buf += written;
                }
                written_total += written;
                if (i < (count - 1)) {
                    APPEND_STRING(",");
                }
                if (is_pretty) {
                    APPEND_STRING("\n");
                }
            }
            if (count > 0 && is_pretty) {
                APPEND_INDENT(level);
            }
            APPEND_STRING("]");
            return written_total;
        case JSONObject:
            object = json_value_get_object(value);
            count  = json_object_get_count(object);
            APPEND_STRING("{");
            if (count > 0 && is_pretty) {
                APPEND_STRING("\n");
            }
            for (i = 0; i < count; i++) {
                key = json_object_get_name(object, i);
                if (key == NULL) {
                    return -1;
                }
                if (is_pretty) {
                    APPEND_INDENT(level+1);
                }
                /* We do not support key names with embedded \0 chars */
                written = json_serialize_string(key, strlen(key), buf);
                if (written < 0) {
                    return -1;
                }
                if (buf != NULL) {
                    buf += written;
                }
                written_total += written;
                APPEND_STRING(":");
                if (is_pretty) {
                    APPEND_STRING(" ");
                }
                temp_value = json_object_get_value_at(object, i);
                written = json_serialize_to_buffer_r(temp_value, buf, level+1, is_pretty, num_buf);
                if (written < 0) {
                    return -1;
                }
                if (buf != NULL) {
                    buf += written;
                }
                written_total += written;
                if (i < (count - 1)) {
                    APPEND_STRING(",");
                }
                if (is_pretty) {
                    APPEND_STRING("\n");
                }
            }
            if (count > 0 && is_pretty) {
                APPEND_INDENT(level);
            }
            APPEND_STRING("}");
            return written_total;
        case JSONString:
            string = json_value_get_string(value);
            if (string == NULL) {
                return -1;
            }
            len = json_value_get_string_len(value);
            written = json_serialize_string(string, len, buf);
            if (written < 0) {
                return -1;
            }
            if (buf != NULL) {
                buf += written;
            }
            written_total += written;
            return written_total;
        case JSONBoolean:
            if (json_value_get_boolean(value)) {
                APPEND_STRING("true");
            } else {
                APPEND_STRING("false");
            }
            return written_total;
        case JSONNumber:
            num = json_value_get_number(value);
            if (buf != NULL) {
                num_buf = buf;
            }
            if (parson_float_format) {
                written = sprintf(num_buf, parson_float_format, num);
            } else {
                written = sprintf(num_buf, PARSON_DEFAULT_FLOAT_FORMAT, num);
            }
            if (written < 0) {
                return -1;
            }
            if (buf != NULL) {
                buf += written;
            }
            written_total += written;
            return written_total;
        case JSONNull:
            APPEND_STRING("null");
            return written_total;
        case JSONError:
            return -1;
        default:
            return -1;
    }
}

static int json_serialize_string(const char *string, size_t len, char *buf) {
    size_t i = 0;
    char c = '\0';
    int written = -1, written_total = 0;
    APPEND_STRING("\"");
    for (i = 0; i < len; i++) {
        c = string[i];
        switch (c) {
            case '\"': APPEND_STRING("\\\""); break;
            case '\\': APPEND_STRING("\\\\"); break;
            case '\b': APPEND_STRING("\\b"); break;
            case '\f': APPEND_STRING("\\f"); break;
            case '\n': APPEND_STRING("\\n"); break;
            case '\r': APPEND_STRING("\\r"); break;
            case '\t': APPEND_STRING("\\t"); break;
            case '\x00': APPEND_STRING("\\u0000"); break;
            case '\x01': APPEND_STRING("\\u0001"); break;
            case '\x02': APPEND_STRING("\\u0002"); break;
            case '\x03': APPEND_STRING("\\u0003"); break;
            case '\x04': APPEND_STRING("\\u0004"); break;
            case '\x05': APPEND_STRING("\\u0005"); break;
            case '\x06': APPEND_STRING("\\u0006"); break;
            case '\x07': APPEND_STRING("\\u0007"); break;
            /* '\x08' duplicate: '\b' */
            /* '\x09' duplicate: '\t' */
            /* '\x0a' duplicate: '\n' */
            case '\x0b': APPEND_STRING("\\u000b"); break;
            /* '\x0c' duplicate: '\f' */
            /* '\x0d' duplicate: '\r' */
            case '\x0e': APPEND_STRING("\\u000e"); break;
            case '\x0f': APPEND_STRING("\\u000f"); break;
            case '\x10': APPEND_STRING("\\u0010"); break;
            case '\x11': APPEND_STRING("\\u0011"); break;
            case '\x12': APPEND_STRING("\\u0012"); break;
            case '\x13': APPEND_STRING("\\u0013"); break;
            case '\x14': APPEND_STRING("\\u0014"); break;
            case '\x15': APPEND_STRING("\\u0015"); break;
            case '\x16': APPEND_STRING("\\u0016"); break;
            case '\x17': APPEND_STRING("\\u0017"); break;
            case '\x18': APPEND_STRING("\\u0018"); break;
            case '\x19': APPEND_STRING("\\u0019"); break;
            case '\x1a': APPEND_STRING("\\u001a"); break;
            case '\x1b': APPEND_STRING("\\u001b"); break;
            case '\x1c': APPEND_STRING("\\u001c"); break;
            case '\x1d': APPEND_STRING("\\u001d"); break;
            case '\x1e': APPEND_STRING("\\u001e"); break;
            case '\x1f': APPEND_STRING("\\u001f"); break;
            case '/':
                if (parson_escape_slashes) {
                    APPEND_STRING("\\/");  /* to make json embeddable in xml\/html */
                } else {
                    APPEND_STRING("/");
                }
                break;
            default:
                if (buf != NULL) {
                    buf[0] = c;
                    buf += 1;
                }
                written_total += 1;
                break;
        }
    }
    APPEND_STRING("\"");
    return written_total;
}

static int append_indent(char *buf, int level) {
    int i;
    int written = -1, written_total = 0;
    for (i = 0; i < level; i++) {
        APPEND_STRING("    ");
    }
    return written_total;
}

static int append_string(char *buf, const char *string) {
    if (buf == NULL) {
        return (int)strlen(string);
    }
    return sprintf(buf, "%s", string);
}

#undef APPEND_STRING
#undef APPEND_INDENT

/* Parser API */
JSON_Value * json_parse_file(const char *filename) {
    char *file_contents = read_file(filename);
    JSON_Value *output_value = NULL;
    if (file_contents == NULL) {
        return NULL;
    }
    output_value = json_parse_string(file_contents);
    parson_free(file_contents);
    return output_value;
}

JSON_Value * json_parse_file_with_comments(const char *filename) {
    char *file_contents = read_file(filename);
    JSON_Value *output_value = NULL;
    if (file_contents == NULL) {
        return NULL;
    }
    output_value = json_parse_string_with_comments(file_contents);
    parson_free(file_contents);
    return output_value;
}

JSON_Value * json_parse_string(const char *string) {
    if (string == NULL) {
        return NULL;
    }
    if (string[0] == '\xEF' && string[1] == '\xBB' && string[2] == '\xBF') {
        string = string + 3; /* Support for UTF-8 BOM */
    }
    return parse_value((const char**)&string, 0);
}

JSON_Value * json_parse_string_with_comments(const char *string) {
    JSON_Value *result = NULL;
    char *string_mutable_copy = NULL, *string_mutable_copy_ptr = NULL;
    string_mutable_copy = parson_strdup(string);
    if (string_mutable_copy == NULL) {
        return NULL;
    }
    remove_comments(string_mutable_copy, "/*", "*/");
    remove_comments(string_mutable_copy, "//", "\n");
    string_mutable_copy_ptr = string_mutable_copy;
    result = parse_value((const char**)&string_mutable_copy_ptr, 0);
    parson_free(string_mutable_copy);
    return result;
}

/* JSON Object API */

JSON_Value * json_object_get_value(const JSON_Object *object, const char *name) {
    if (object == NULL || name == NULL) {
        return NULL;
    }
    return json_object_getn_value(object, name, strlen(name));
}

const char * json_object_get_string(const JSON_Object *object, const char *name) {
    return json_value_get_string(json_object_get_value(object, name));
}

size_t json_object_get_string_len(const JSON_Object *object, const char *name) {
    return json_value_get_string_len(json_object_get_value(object, name));
}

double json_object_get_number(const JSON_Object *object, const char *name) {
    return json_value_get_number(json_object_get_value(object, name));
}

JSON_Object * json_object_get_object(const JSON_Object *object, const char *name) {
    return json_value_get_object(json_object_get_value(object, name));
}

JSON_Array * json_object_get_array(const JSON_Object *object, const char *name) {
    return json_value_get_array(json_object_get_value(object, name));
}

int json_object_get_boolean(const JSON_Object *object, const char *name) {
    return json_value_get_boolean(json_object_get_value(object, name));
}

JSON_Value * json_object_dotget_value(const JSON_Object *object, const char *name) {
    const char *dot_position = strchr(name, '.');
    if (!dot_position) {
        return json_object_get_value(object, name);
    }
    object = json_value_get_object(json_object_getn_value(object, name, dot_position - name));
    return json_object_dotget_value(object, dot_position + 1);
}

const char * json_object_dotget_string(const JSON_Object *object, const char *name) {
    return json_value_get_string(json_object_dotget_value(object, name));
}

size_t json_object_dotget_string_len(const JSON_Object *object, const char *name) {
    return json_value_get_string_len(json_object_dotget_value(object, name));
}

double json_object_dotget_number(const JSON_Object *object, const char *name) {
    return json_value_get_number(json_object_dotget_value(object, name));
}

JSON_Object * json_object_dotget_object(const JSON_Object *object, const char *name) {
    return json_value_get_object(json_object_dotget_value(object, name));
}

JSON_Array * json_object_dotget_array(const JSON_Object *object, const char *name) {
    return json_value_get_array(json_object_dotget_value(object, name));
}

int json_object_dotget_boolean(const JSON_Object *object, const char *name) {
    return json_value_get_boolean(json_object_dotget_value(object, name));
}

size_t json_object_get_count(const JSON_Object *object) {
    return object ? object->count : 0;
}

const char * json_object_get_name(const JSON_Object *object, size_t index) {
    if (object == NULL || index >= json_object_get_count(object)) {
        return NULL;
    }
    return object->names[index];
}

JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index) {
    if (object == NULL || index >= json_object_get_count(object)) {
        return NULL;
    }
    return object->values[index];
}

JSON_Value *json_object_get_wrapping_value(const JSON_Object *object) {
    if (!object) {
        return NULL;
    }
    return object->wrapping_value;
}

int json_object_has_value (const JSON_Object *object, const char *name) {
    return json_object_get_value(object, name) != NULL;
}

int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
    JSON_Value *val = json_object_get_value(object, name);
    return val != NULL && json_value_get_type(val) == type;
}

int json_object_dothas_value (const JSON_Object *object, const char *name) {
    return json_object_dotget_value(object, name) != NULL;
}

int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type) {
    JSON_Value *val = json_object_dotget_value(object, name);
    return val != NULL && json_value_get_type(val) == type;
}

/* JSON Array API */
JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
    if (array == NULL || index >= json_array_get_count(array)) {
        return NULL;
    }
    return array->items[index];
}

const char * json_array_get_string(const JSON_Array *array, size_t index) {
    return json_value_get_string(json_array_get_value(array, index));
}

size_t json_array_get_string_len(const JSON_Array *array, size_t index) {
    return json_value_get_string_len(json_array_get_value(array, index));
}

double json_array_get_number(const JSON_Array *array, size_t index) {
    return json_value_get_number(json_array_get_value(array, index));
}

JSON_Object * json_array_get_object(const JSON_Array *array, size_t index) {
    return json_value_get_object(json_array_get_value(array, index));
}

JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
    return json_value_get_array(json_array_get_value(array, index));
}

int json_array_get_boolean(const JSON_Array *array, size_t index) {
    return json_value_get_boolean(json_array_get_value(array, index));
}

size_t json_array_get_count(const JSON_Array *array) {
    return array ? array->count : 0;
}

JSON_Value * json_array_get_wrapping_value(const JSON_Array *array) {
    if (!array) {
        return NULL;
    }
    return array->wrapping_value;
}

/* JSON Value API */
JSON_Value_Type json_value_get_type(const JSON_Value *value) {
    return value ? value->type : JSONError;
}

JSON_Object * json_value_get_object(const JSON_Value *value) {
    return json_value_get_type(value) == JSONObject ? value->value.object : NULL;
}

JSON_Array * json_value_get_array(const JSON_Value *value) {
    return json_value_get_type(value) == JSONArray ? value->value.array : NULL;
}

static const JSON_String * json_value_get_string_desc(const JSON_Value *value) {
    return json_value_get_type(value) == JSONString ? &value->value.string : NULL;
}

const char * json_value_get_string(const JSON_Value *value) {
    const JSON_String *str = json_value_get_string_desc(value);
    return str ? str->chars : NULL;
}

size_t json_value_get_string_len(const JSON_Value *value) {
    const JSON_String *str = json_value_get_string_desc(value);
    return str ? str->length : 0;
}

double json_value_get_number(const JSON_Value *value) {
    return json_value_get_type(value) == JSONNumber ? value->value.number : 0;
}

int json_value_get_boolean(const JSON_Value *value) {
    return json_value_get_type(value) == JSONBoolean ? value->value.boolean : -1;
}

JSON_Value * json_value_get_parent (const JSON_Value *value) {
    return value ? value->parent : NULL;
}

void json_value_free(JSON_Value *value) {
    switch (json_value_get_type(value)) {
        case JSONObject:
            json_object_free(value->value.object);
            break;
        case JSONString:
            parson_free(value->value.string.chars);
            break;
        case JSONArray:
            json_array_free(value->value.array);
            break;
        default:
            break;
    }
    parson_free(value);
}

JSON_Value * json_value_init_object(void) {
    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
    if (!new_value) {
        return NULL;
    }
    new_value->parent = NULL;
    new_value->type = JSONObject;
    new_value->value.object = json_object_make(new_value);
    if (!new_value->value.object) {
        parson_free(new_value);
        return NULL;
    }
    return new_value;
}

JSON_Value * json_value_init_array(void) {
    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
    if (!new_value) {
        return NULL;
    }
    new_value->parent = NULL;
    new_value->type = JSONArray;
    new_value->value.array = json_array_make(new_value);
    if (!new_value->value.array) {
        parson_free(new_value);
        return NULL;
    }
    return new_value;
}

JSON_Value * json_value_init_string(const char *string) {
    if (string == NULL) {
        return NULL;
    }
    return json_value_init_string_with_len(string, strlen(string));
}

JSON_Value * json_value_init_string_with_len(const char *string, size_t length) {
    char *copy = NULL;
    JSON_Value *value;
    if (string == NULL) {
        return NULL;
    }
    if (!is_valid_utf8(string, length)) {
        return NULL;
    }
    copy = parson_strndup(string, length);
    if (copy == NULL) {
        return NULL;
    }
    value = json_value_init_string_no_copy(copy, length);
    if (value == NULL) {
        parson_free(copy);
    }
    return value;
}

JSON_Value * json_value_init_number(double number) {
    JSON_Value *new_value = NULL;
    if (IS_NUMBER_INVALID(number)) {
        return NULL;
    }
    new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
    if (new_value == NULL) {
        return NULL;
    }
    new_value->parent = NULL;
    new_value->type = JSONNumber;
    new_value->value.number = number;
    return new_value;
}

JSON_Value * json_value_init_boolean(int boolean) {
    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
    if (!new_value) {
        return NULL;
    }
    new_value->parent = NULL;
    new_value->type = JSONBoolean;
    new_value->value.boolean = boolean ? 1 : 0;
    return new_value;
}

JSON_Value * json_value_init_null(void) {
    JSON_Value *new_value = (JSON_Value*)parson_malloc(sizeof(JSON_Value));
    if (!new_value) {
        return NULL;
    }
    new_value->parent = NULL;
    new_value->type = JSONNull;
    return new_value;
}

JSON_Value * json_value_deep_copy(const JSON_Value *value) {
    size_t i = 0;
    JSON_Value *return_value = NULL, *temp_value_copy = NULL, *temp_value = NULL;
    const JSON_String *temp_string = NULL;
    const char *temp_key = NULL;
    char *temp_string_copy = NULL;
    JSON_Array *temp_array = NULL, *temp_array_copy = NULL;
    JSON_Object *temp_object = NULL, *temp_object_copy = NULL;
    JSON_Status res = JSONFailure;
    char *key_copy = NULL;

    switch (json_value_get_type(value)) {
        case JSONArray:
            temp_array = json_value_get_array(value);
            return_value = js
Download .txt
gitextract_wyjnxqch/

├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── FAKEHD.md
├── LICENSE
├── Makefile.dji
├── Makefile.unix
├── README.md
├── config/
│   ├── airunit/
│   │   ├── config.json
│   │   ├── schema.json
│   │   ├── schemaV2.json
│   │   └── uiSchemaV2.json
│   └── goggles/
│       ├── config.json
│       ├── schema.json
│       ├── schemaV2.json
│       └── uiSchemaV2.json
├── docs/
│   └── fonts/
│       └── gen.sh
├── ipk/
│   ├── airunit/
│   │   ├── control/
│   │   │   ├── conffiles
│   │   │   ├── control
│   │   │   ├── postinst
│   │   │   └── prerm
│   │   └── data/
│   │       └── opt/
│   │           ├── bin/
│   │           │   └── airunit-osd-start.sh
│   │           └── etc/
│   │               └── dinit.d/
│   │                   └── msp-osd-airside
│   └── goggle/
│       ├── control/
│       │   ├── conffiles
│       │   ├── control
│       │   ├── postinst
│       │   ├── preinst
│       │   └── prerm
│       └── data/
│           └── opt/
│               └── etc/
│                   └── dinit.d/
│                       └── msp-osd-goggles
├── jni/
│   ├── Android.mk
│   ├── Application.mk
│   ├── displayport_osd_shim.c
│   ├── fakehd/
│   │   ├── fakehd.c
│   │   └── fakehd.h
│   ├── font/
│   │   ├── font.c
│   │   └── font.h
│   ├── hw/
│   │   ├── dji_display.c
│   │   ├── dji_display.h
│   │   ├── dji_radio_shm.c
│   │   ├── dji_radio_shm.h
│   │   ├── dji_services.c
│   │   ├── dji_services.h
│   │   └── duml_hal.h
│   ├── json/
│   │   ├── osd_config.c
│   │   ├── osd_config.h
│   │   ├── parson.c
│   │   └── parson.h
│   ├── libspng/
│   │   ├── spng.c
│   │   └── spng.h
│   ├── lz4/
│   │   ├── lz4.c
│   │   └── lz4.h
│   ├── msp/
│   │   ├── msp.c
│   │   ├── msp.h
│   │   ├── msp_displayport.c
│   │   └── msp_displayport.h
│   ├── msp_displayport_mux.c
│   ├── net/
│   │   ├── data_protocol.h
│   │   ├── network.c
│   │   ├── network.h
│   │   ├── serial.c
│   │   └── serial.h
│   ├── osd.h
│   ├── osd_dji_overlay_udp.c
│   ├── osd_dji_udp.c
│   ├── osd_sfml_udp.c
│   ├── rec/
│   │   ├── rec.c
│   │   ├── rec.h
│   │   ├── rec_pb.c
│   │   ├── rec_pb.h
│   │   ├── rec_shim.c
│   │   ├── rec_shim.h
│   │   ├── rec_util.c
│   │   └── rec_util.h
│   ├── toast/
│   │   ├── toast.c
│   │   └── toast.h
│   └── util/
│       ├── debug.h
│       ├── display_info.h
│       ├── fs_util.c
│       ├── fs_util.h
│       └── time_util.h
└── libshims/
    └── duml_hal.c
Download .txt
SYMBOL INDEX (1612 symbols across 40 files)

FILE: jni/displayport_osd_shim.c
  function _ZN24MMSFBWindowManagerThread10threadMainEv (line 22) | void _ZN24MMSFBWindowManagerThread10threadMainEv(void *this) {
  function _ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChannelId (line 38) | void _ZN23GlassVideoChnlUIManager19setNextVideoChannelE19GlassVideoChann...
  function duss_result_t (line 67) | duss_result_t duss_hal_mem_alloc(duss_hal_obj_handle_t handle, duss_hal_...
  function duss_result_t (line 91) | duss_result_t duss_hal_display_aquire_plane(duss_disp_instance_handle_t ...
  function duss_result_t (line 112) | duss_result_t duss_hal_display_plane_blending_set(duss_disp_instance_han...

FILE: jni/fakehd/fakehd.c
  function load_fakehd_config (line 36) | void load_fakehd_config()
  function fakehd_get_column_config (line 107) | static void fakehd_get_column_config(int cols[INPUT_ROWS])
  function fakehd_get_row_config (line 131) | static void fakehd_get_row_config(int rownum, int row[INPUT_COLS])
  function fakehd_reset (line 167) | void fakehd_reset() {
  function fakehd_enable (line 173) | void fakehd_enable()
  function fakehd_disable (line 178) | void fakehd_disable()
  function fakehd_is_enabled (line 184) | int fakehd_is_enabled() {
  function fakehd_map_sd_character_map_to_hd (line 188) | void fakehd_map_sd_character_map_to_hd(uint16_t sd_character_map[60][22]...

FILE: jni/font/font.c
  function get_font_path_with_extension (line 18) | void get_font_path_with_extension(char *font_path_dest, const char *font...
  function open_font (line 41) | static int open_font(const char *filename, display_info_t *display_info,...
  function load_font (line 139) | void load_font(display_info_t *display_info, const char *font_variant) {
  function close_font (line 219) | void close_font(display_info_t *display_info) {

FILE: jni/font/font.h
  type font_variant_e (line 13) | typedef enum

FILE: jni/hw/dji_display.c
  function dji_display_state_t (line 8) | dji_display_state_t *dji_display_state_alloc(uint8_t is_v2_goggles) {
  function dji_display_state_free (line 19) | void dji_display_state_free(dji_display_state_t *display_state) {
  function dji_display_close_framebuffer (line 27) | void dji_display_close_framebuffer(dji_display_state_t *display_state) {
  function dji_display_open_framebuffer (line 39) | void dji_display_open_framebuffer(dji_display_state_t *display_state, du...
  function dji_display_open_framebuffer_injected (line 167) | void dji_display_open_framebuffer_injected(dji_display_state_t *display_...
  function dji_display_push_frame (line 263) | void dji_display_push_frame(dji_display_state_t *display_state) {

FILE: jni/hw/dji_display.h
  type dji_display_state_t (line 4) | typedef struct dji_display_state_s {

FILE: jni/hw/dji_radio_shm.c
  function open_dji_radio_shm (line 8) | void open_dji_radio_shm(dji_shm_state_t *shm) {
  function close_dji_radio_shm (line 18) | void close_dji_radio_shm(dji_shm_state_t *shm) {
  function dji_radio_latency_ms (line 25) | uint16_t dji_radio_latency_ms(dji_shm_state_t *shm) {
  function dji_radio_mbits (line 29) | uint16_t dji_radio_mbits(dji_shm_state_t *shm) {

FILE: jni/hw/dji_radio_shm.h
  type modem_shmem_info_t (line 11) | typedef struct modem_shmem_info_s {
  type product_shm_info_t (line 74) | typedef struct product_shm_info_s {
  type dji_shm_state_t (line 105) | typedef struct dji_shm_state_s {

FILE: jni/hw/dji_services.c
  function dji_stop_goggles (line 11) | void dji_stop_goggles(int is_v2) {
  function dji_start_goggles (line 17) | void dji_start_goggles(int is_v2) {
  function dji_goggles_are_v2 (line 23) | int dji_goggles_are_v2() {

FILE: jni/hw/duml_hal.h
  type duss_result_t (line 4) | typedef int32_t duss_result_t;
  type duss_hal_state_t (line 6) | typedef uint8_t duss_hal_state_t;
  type duss_hal_class_t (line 7) | typedef uint8_t duss_hal_class_t;
  type sem_t (line 9) | struct sem_t {
  type duss_osal_mutex_attrib_t (line 13) | struct duss_osal_mutex_attrib_t {
  type duss_osal_mutex_handle_t (line 17) | struct duss_osal_mutex_handle_t {
  type duss_osal_mutex_handle_t (line 22) | typedef struct duss_osal_mutex_handle_t duss_osal_mutex_handle_t, *Pduss...
  type duss_hal_obj_dev_t (line 25) | typedef struct duss_hal_obj_dev_t duss_hal_obj_dev_t, *Pduss_hal_obj_dev_t;
  type duss_hal_obj (line 27) | struct duss_hal_obj
  type duss_hal_obj_dev_t (line 29) | struct duss_hal_obj_dev_t {
  type duss_hal_obj (line 45) | struct duss_hal_obj {
  type duss_hal_device_desc_t (line 51) | struct duss_hal_device_desc_t {
  type duss_pixel_format (line 58) | typedef enum duss_pixel_format {
  type duss_pixel_format_t (line 118) | typedef enum duss_pixel_format duss_pixel_format_t;
  type duss_object (line 120) | struct duss_object {
  type duss_object_t (line 126) | typedef struct duss_object duss_object_t;
  type duss_hal_mem_buf (line 128) | struct duss_hal_mem_buf
  type duss_frame_plane (line 130) | typedef struct duss_frame_plane duss_frame_plane, *Pduss_frame_plane;
  type duss_frame_plane_t (line 132) | typedef struct duss_frame_plane duss_frame_plane_t;
  type duss_frame_plane (line 134) | struct duss_frame_plane {
  type duss_frame_buffer (line 141) | struct __attribute__((__packed__)) duss_frame_buffer {
  type duss_frame_buffer_t (line 154) | typedef struct duss_frame_buffer duss_frame_buffer_t;
  type duss_hal_device_desc_t (line 156) | typedef struct duss_hal_device_desc_t duss_hal_device_desc_t, *Pduss_hal...
  type duss_hal_obj (line 158) | typedef struct duss_hal_obj duss_hal_obj, *Pduss_hal_obj;
  type duss_disp_instance_handle_t (line 160) | typedef struct duss_disp_instance_handle_t duss_disp_instance_handle_t, ...
  type duss_disp_instance_handle_t (line 162) | struct __attribute__((__packed__)) duss_disp_instance_handle_t {
  type duss_disp_vop_id_t (line 174) | typedef uint8_t duss_disp_vop_id_t;
  type duss_disp_plane_type_t (line 176) | typedef uint8_t duss_disp_plane_type_t;
  type duss_disp_port_id_t (line 178) | typedef uint8_t duss_disp_port_id_t;
  type duss_disp_timing_detail_t (line 180) | typedef struct duss_disp_timing_detail_t duss_disp_timing_detail_t, *Pdu...
  type duss_disp_timing_bitdepth_t (line 182) | typedef enum duss_disp_timing_bitdepth_t {
  type duss_disp_timing_fmt_t (line 188) | typedef enum duss_disp_timing_fmt_t {
  type duss_disp_timing_detail_t (line 195) | struct duss_disp_timing_detail_t {
  type duss_disp_plane_blending_t (line 211) | typedef struct duss_disp_plane_blending_t duss_disp_plane_blending_t, *P...
  type duss_disp_plane_alpha_alg_t (line 213) | typedef uint8_t duss_disp_plane_alpha_alg_t;
  type duss_disp_plane_id_t (line 214) | typedef int8_t duss_disp_plane_id_t;
  type duss_disp_plane_blending_t (line 216) | struct __attribute__((__packed__)) duss_disp_plane_blending_t {
  type duss_result_t (line 230) | typedef duss_result_t (frame_pop_handler)(duss_disp_instance_handle_t * ...

FILE: jni/json/osd_config.c
  function load_config (line 4) | static void load_config() {
  function get_boolean_config_value (line 15) | int get_boolean_config_value(const char* key) {
  function get_integer_config_value (line 39) | int get_integer_config_value(const char *key)

FILE: jni/json/parson.c
  type parson_bool_t (line 99) | typedef int parson_bool_t;
  type JSON_String (line 104) | typedef struct json_string {
  type JSON_Value_Value (line 110) | typedef union json_value_value {
  type json_value_t (line 119) | struct json_value_t {
  type json_object_t (line 125) | struct json_object_t {
  type json_array_t (line 137) | struct json_array_t {
  function remove_comments (line 232) | static void remove_comments(char *string, const char *start_token, const...
  function hex_char_to_int (line 282) | static int hex_char_to_int(char c) {
  function JSON_Status (line 293) | static JSON_Status parse_utf16_hex(const char *s, unsigned int *result) {
  function num_bytes_in_utf8_sequence (line 309) | static int num_bytes_in_utf8_sequence(unsigned char c) {
  function JSON_Status (line 324) | static JSON_Status verify_utf8_sequence(const unsigned char *string, int...
  function is_valid_utf8 (line 366) | static int is_valid_utf8(const char *string, size_t string_len) {
  function parson_bool_t (line 378) | static parson_bool_t is_decimal(const char *string, size_t length) {
  function hash_string (line 393) | static unsigned long hash_string(const char *string, size_t n) {
  function JSON_Object (line 414) | static JSON_Object * json_object_make(JSON_Value *wrapping_value) {
  function JSON_Status (line 429) | static JSON_Status json_object_init(JSON_Object *object, size_t capacity) {
  function json_object_deinit (line 471) | static void json_object_deinit(JSON_Object *object, parson_bool_t free_k...
  function JSON_Status (line 499) | static JSON_Status json_object_grow_and_rehash(JSON_Object *object) {
  function json_object_get_cell_ix (line 529) | static size_t json_object_get_cell_ix(const JSON_Object *object, const c...
  function JSON_Status (line 560) | static JSON_Status json_object_add(JSON_Object *object, char *name, JSON...
  function JSON_Value (line 596) | static JSON_Value * json_object_getn_value(const JSON_Object *object, co...
  function JSON_Status (line 614) | static JSON_Status json_object_remove_internal(JSON_Object *object, cons...
  function JSON_Status (line 674) | static JSON_Status json_object_dotremove_internal(JSON_Object *object, c...
  function json_object_free (line 689) | static void json_object_free(JSON_Object *object) {
  function JSON_Array (line 695) | static JSON_Array * json_array_make(JSON_Value *wrapping_value) {
  function JSON_Status (line 707) | static JSON_Status json_array_add(JSON_Array *array, JSON_Value *value) {
  function JSON_Status (line 720) | static JSON_Status json_array_resize(JSON_Array *array, size_t new_capac...
  function json_array_free (line 738) | static void json_array_free(JSON_Array *array) {
  function JSON_Value (line 748) | static JSON_Value * json_value_init_string_no_copy(char *string, size_t ...
  function JSON_Status (line 761) | static JSON_Status skip_quotes(const char **string) {
  function JSON_Status (line 781) | static JSON_Status parse_utf16(const char **unprocessed, char **processe...
  function JSON_Value (line 898) | static JSON_Value * parse_value(const char **string, size_t nesting) {
  function JSON_Value (line 923) | static JSON_Value * parse_object_value(const char **string, size_t nesti...
  function JSON_Value (line 996) | static JSON_Value * parse_array_value(const char **string, size_t nestin...
  function JSON_Value (line 1045) | static JSON_Value * parse_string_value(const char **string) {
  function JSON_Value (line 1060) | static JSON_Value * parse_boolean_value(const char **string) {
  function JSON_Value (line 1073) | static JSON_Value * parse_number_value(const char **string) {
  function JSON_Value (line 1088) | static JSON_Value * parse_null_value(const char **string) {
  function json_serialize_to_buffer_r (line 1108) | static int json_serialize_to_buffer_r(const JSON_Value *value, char *buf...
  function json_serialize_string (line 1251) | static int json_serialize_string(const char *string, size_t len, char *b...
  function append_indent (line 1318) | static int append_indent(char *buf, int level) {
  function append_string (line 1327) | static int append_string(char *buf, const char *string) {
  function JSON_Value (line 1338) | JSON_Value * json_parse_file(const char *filename) {
  function JSON_Value (line 1349) | JSON_Value * json_parse_file_with_comments(const char *filename) {
  function JSON_Value (line 1360) | JSON_Value * json_parse_string(const char *string) {
  function JSON_Value (line 1370) | JSON_Value * json_parse_string_with_comments(const char *string) {
  function JSON_Value (line 1387) | JSON_Value * json_object_get_value(const JSON_Object *object, const char...
  function json_object_get_string_len (line 1398) | size_t json_object_get_string_len(const JSON_Object *object, const char ...
  function json_object_get_number (line 1402) | double json_object_get_number(const JSON_Object *object, const char *nam...
  function JSON_Object (line 1406) | JSON_Object * json_object_get_object(const JSON_Object *object, const ch...
  function JSON_Array (line 1410) | JSON_Array * json_object_get_array(const JSON_Object *object, const char...
  function json_object_get_boolean (line 1414) | int json_object_get_boolean(const JSON_Object *object, const char *name) {
  function JSON_Value (line 1418) | JSON_Value * json_object_dotget_value(const JSON_Object *object, const c...
  function json_object_dotget_string_len (line 1431) | size_t json_object_dotget_string_len(const JSON_Object *object, const ch...
  function json_object_dotget_number (line 1435) | double json_object_dotget_number(const JSON_Object *object, const char *...
  function JSON_Object (line 1439) | JSON_Object * json_object_dotget_object(const JSON_Object *object, const...
  function JSON_Array (line 1443) | JSON_Array * json_object_dotget_array(const JSON_Object *object, const c...
  function json_object_dotget_boolean (line 1447) | int json_object_dotget_boolean(const JSON_Object *object, const char *na...
  function json_object_get_count (line 1451) | size_t json_object_get_count(const JSON_Object *object) {
  function JSON_Value (line 1462) | JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t ...
  function JSON_Value (line 1469) | JSON_Value *json_object_get_wrapping_value(const JSON_Object *object) {
  function json_object_has_value (line 1476) | int json_object_has_value (const JSON_Object *object, const char *name) {
  function json_object_has_value_of_type (line 1480) | int json_object_has_value_of_type(const JSON_Object *object, const char ...
  function json_object_dothas_value (line 1485) | int json_object_dothas_value (const JSON_Object *object, const char *nam...
  function json_object_dothas_value_of_type (line 1489) | int json_object_dothas_value_of_type(const JSON_Object *object, const ch...
  function JSON_Value (line 1495) | JSON_Value * json_array_get_value(const JSON_Array *array, size_t index) {
  function json_array_get_string_len (line 1506) | size_t json_array_get_string_len(const JSON_Array *array, size_t index) {
  function json_array_get_number (line 1510) | double json_array_get_number(const JSON_Array *array, size_t index) {
  function JSON_Object (line 1514) | JSON_Object * json_array_get_object(const JSON_Array *array, size_t inde...
  function JSON_Array (line 1518) | JSON_Array * json_array_get_array(const JSON_Array *array, size_t index) {
  function json_array_get_boolean (line 1522) | int json_array_get_boolean(const JSON_Array *array, size_t index) {
  function json_array_get_count (line 1526) | size_t json_array_get_count(const JSON_Array *array) {
  function JSON_Value (line 1530) | JSON_Value * json_array_get_wrapping_value(const JSON_Array *array) {
  function JSON_Value_Type (line 1538) | JSON_Value_Type json_value_get_type(const JSON_Value *value) {
  function JSON_Object (line 1542) | JSON_Object * json_value_get_object(const JSON_Value *value) {
  function JSON_Array (line 1546) | JSON_Array * json_value_get_array(const JSON_Value *value) {
  function JSON_String (line 1550) | static const JSON_String * json_value_get_string_desc(const JSON_Value *...
  function json_value_get_string_len (line 1559) | size_t json_value_get_string_len(const JSON_Value *value) {
  function json_value_get_number (line 1564) | double json_value_get_number(const JSON_Value *value) {
  function json_value_get_boolean (line 1568) | int json_value_get_boolean(const JSON_Value *value) {
  function JSON_Value (line 1572) | JSON_Value * json_value_get_parent (const JSON_Value *value) {
  function json_value_free (line 1576) | void json_value_free(JSON_Value *value) {
  function JSON_Value (line 1593) | JSON_Value * json_value_init_object(void) {
  function JSON_Value (line 1608) | JSON_Value * json_value_init_array(void) {
  function JSON_Value (line 1623) | JSON_Value * json_value_init_string(const char *string) {
  function JSON_Value (line 1630) | JSON_Value * json_value_init_string_with_len(const char *string, size_t ...
  function JSON_Value (line 1650) | JSON_Value * json_value_init_number(double number) {
  function JSON_Value (line 1665) | JSON_Value * json_value_init_boolean(int boolean) {
  function JSON_Value (line 1676) | JSON_Value * json_value_init_null(void) {
  function JSON_Value (line 1686) | JSON_Value * json_value_deep_copy(const JSON_Value *value) {
  function json_serialization_size (line 1776) | size_t json_serialization_size(const JSON_Value *value) {
  function JSON_Status (line 1782) | JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf,...
  function JSON_Status (line 1795) | JSON_Status json_serialize_to_file(const JSON_Value *value, const char *...
  function json_serialization_size_pretty (line 1836) | size_t json_serialization_size_pretty(const JSON_Value *value) {
  function JSON_Status (line 1842) | JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, cha...
  function JSON_Status (line 1855) | JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const...
  function json_free_serialized_string (line 1896) | void json_free_serialized_string(char *string) {
  function JSON_Status (line 1900) | JSON_Status json_array_remove(JSON_Array *array, size_t ix) {
  function JSON_Status (line 1912) | JSON_Status json_array_replace_value(JSON_Array *array, size_t ix, JSON_...
  function JSON_Status (line 1922) | JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const...
  function JSON_Status (line 1934) | JSON_Status json_array_replace_string_with_len(JSON_Array *array, size_t...
  function JSON_Status (line 1946) | JSON_Status json_array_replace_number(JSON_Array *array, size_t i, doubl...
  function JSON_Status (line 1958) | JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int ...
  function JSON_Status (line 1970) | JSON_Status json_array_replace_null(JSON_Array *array, size_t i) {
  function JSON_Status (line 1982) | JSON_Status json_array_clear(JSON_Array *array) {
  function JSON_Status (line 1994) | JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value) {
  function JSON_Status (line 2001) | JSON_Status json_array_append_string(JSON_Array *array, const char *stri...
  function JSON_Status (line 2013) | JSON_Status json_array_append_string_with_len(JSON_Array *array, const c...
  function JSON_Status (line 2025) | JSON_Status json_array_append_number(JSON_Array *array, double number) {
  function JSON_Status (line 2037) | JSON_Status json_array_append_boolean(JSON_Array *array, int boolean) {
  function JSON_Status (line 2049) | JSON_Status json_array_append_null(JSON_Array *array) {
  function JSON_Status (line 2061) | JSON_Status json_object_set_value(JSON_Object *object, const char *name,...
  function JSON_Status (line 2104) | JSON_Status json_object_set_string(JSON_Object *object, const char *name...
  function JSON_Status (line 2113) | JSON_Status json_object_set_string_with_len(JSON_Object *object, const c...
  function JSON_Status (line 2122) | JSON_Status json_object_set_number(JSON_Object *object, const char *name...
  function JSON_Status (line 2131) | JSON_Status json_object_set_boolean(JSON_Object *object, const char *nam...
  function JSON_Status (line 2140) | JSON_Status json_object_set_null(JSON_Object *object, const char *name) {
  function JSON_Status (line 2149) | JSON_Status json_object_dotset_value(JSON_Object *object, const char *na...
  function JSON_Status (line 2200) | JSON_Status json_object_dotset_string(JSON_Object *object, const char *n...
  function JSON_Status (line 2212) | JSON_Status json_object_dotset_string_with_len(JSON_Object *object, cons...
  function JSON_Status (line 2224) | JSON_Status json_object_dotset_number(JSON_Object *object, const char *n...
  function JSON_Status (line 2236) | JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *...
  function JSON_Status (line 2248) | JSON_Status json_object_dotset_null(JSON_Object *object, const char *nam...
  function JSON_Status (line 2260) | JSON_Status json_object_remove(JSON_Object *object, const char *name) {
  function JSON_Status (line 2264) | JSON_Status json_object_dotremove(JSON_Object *object, const char *name) {
  function JSON_Status (line 2268) | JSON_Status json_object_clear(JSON_Object *object) {
  function JSON_Status (line 2281) | JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *va...
  function json_value_equals (line 2341) | int json_value_equals(const JSON_Value *a, const JSON_Value *b) {
  function JSON_Value_Type (line 2406) | JSON_Value_Type json_type(const JSON_Value *value) {
  function JSON_Object (line 2410) | JSON_Object * json_object (const JSON_Value *value) {
  function JSON_Array (line 2414) | JSON_Array * json_array(const JSON_Value *value) {
  function json_string_len (line 2422) | size_t json_string_len(const JSON_Value *value) {
  function json_number (line 2426) | double json_number(const JSON_Value *value) {
  function json_boolean (line 2430) | int json_boolean(const JSON_Value *value) {
  function json_set_allocation_functions (line 2434) | void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON...
  function json_set_escape_slashes (line 2439) | void json_set_escape_slashes(int escape_slashes) {
  function json_set_float_serialization_format (line 2443) | void json_set_float_serialization_format(const char *format) {

FILE: jni/json/parson.h
  type JSON_Object (line 46) | typedef struct json_object_t JSON_Object;
  type JSON_Array (line 47) | typedef struct json_array_t  JSON_Array;
  type JSON_Value (line 48) | typedef struct json_value_t  JSON_Value;
  type json_value_type (line 50) | enum json_value_type {
  type JSON_Value_Type (line 59) | typedef int JSON_Value_Type;
  type json_result_t (line 61) | enum json_result_t {
  type JSON_Status (line 65) | typedef int JSON_Status;

FILE: jni/libspng/spng.c
  type spng_state (line 85) | enum spng_state
  type spng__internal (line 101) | enum spng__internal
  type spng_subimage (line 130) | struct spng_subimage
  type spng_text2 (line 138) | struct spng_text2
  type decode_flags (line 154) | struct decode_flags
  type encode_flags (line 167) | struct encode_flags
  type spng_chunk_bitfield (line 178) | struct spng_chunk_bitfield
  type spng__iter (line 200) | struct spng__iter
  type spng_plte_entry (line 210) | struct spng_plte_entry
  type spng__zlib_options (line 216) | struct spng__zlib_options
  type spng_ctx (line 227) | struct spng_ctx
  function spng__free (line 413) | static inline void spng__free(spng_ctx *ctx, void *ptr)
  function spng__zfree (line 433) | static void spng__zfree(void *opqaue, void *ptr)
  function read_u16 (line 439) | static inline uint16_t read_u16(const void *src)
  function read_u32 (line 446) | static inline uint32_t read_u32(const void *src)
  function read_s32 (line 454) | static inline int32_t read_s32(const void *src)
  function write_u16 (line 461) | static inline void write_u16(void *dest, uint16_t x)
  function write_u32 (line 469) | static inline void write_u32(void *dest, uint32_t x)
  function write_s32 (line 479) | static inline void write_s32(void *dest, int32_t x)
  function spng__iter_init (line 486) | static struct spng__iter spng__iter_init(unsigned bit_depth, const unsig...
  function get_sample (line 501) | static inline uint8_t get_sample(struct spng__iter *iter)
  function u16_row_to_host (line 516) | static void u16_row_to_host(void *row, size_t size)
  function u16_row_to_bigendian (line 527) | static void u16_row_to_bigendian(void *row, size_t size)
  function rgb8_row_to_rgba8 (line 538) | static void rgb8_row_to_rgba8(const unsigned char *row, unsigned char *o...
  function num_channels (line 548) | static unsigned num_channels(const struct spng_ihdr *ihdr)
  function calculate_scanline_width (line 563) | static int calculate_scanline_width(const struct spng_ihdr *ihdr, uint32...
  function calculate_subimages (line 585) | static int calculate_subimages(struct spng_ctx *ctx)
  function check_decode_fmt (line 631) | static int check_decode_fmt(const struct spng_ihdr *ihdr, const int fmt)
  function calculate_image_width (line 652) | static int calculate_image_width(const struct spng_ihdr *ihdr, int fmt, ...
  function calculate_image_size (line 698) | static int calculate_image_size(const struct spng_ihdr *ihdr, int fmt, s...
  function increase_cache_usage (line 715) | static int increase_cache_usage(spng_ctx *ctx, size_t bytes, int new_chunk)
  function decrease_cache_usage (line 738) | static int decrease_cache_usage(spng_ctx *ctx, size_t usage)
  function is_critical_chunk (line 748) | static int is_critical_chunk(struct spng_chunk *chunk)
  function decode_err (line 756) | static int decode_err(spng_ctx *ctx, int err)
  function encode_err (line 763) | static int encode_err(spng_ctx *ctx, int err)
  function read_data (line 770) | static inline int read_data(spng_ctx *ctx, size_t bytes)
  function require_bytes (line 793) | static int require_bytes(spng_ctx *ctx, size_t bytes)
  function write_data (line 852) | static int write_data(spng_ctx *ctx, const void *data, size_t bytes)
  function write_header (line 886) | static int write_header(spng_ctx *ctx, const uint8_t chunk_type[4], size...
  function trim_chunk (line 910) | static int trim_chunk(spng_ctx *ctx, uint32_t length)
  function finish_chunk (line 920) | static int finish_chunk(spng_ctx *ctx)
  function write_chunk (line 980) | static int write_chunk(spng_ctx *ctx, const uint8_t type[4], const void ...
  function write_iend (line 995) | static int write_iend(spng_ctx *ctx)
  function write_unknown_chunks (line 1001) | static int write_unknown_chunks(spng_ctx *ctx, enum spng_location location)
  function read_and_check_crc (line 1021) | static inline int read_and_check_crc(spng_ctx *ctx)
  function read_header (line 1052) | static inline int read_header(spng_ctx *ctx)
  function read_chunk_bytes (line 1098) | static int read_chunk_bytes(spng_ctx *ctx, uint32_t bytes)
  function read_chunk_bytes2 (line 1117) | static int read_chunk_bytes2(spng_ctx *ctx, void *out, uint32_t bytes)
  function discard_chunk_bytes (line 1152) | static int discard_chunk_bytes(spng_ctx *ctx, uint32_t bytes)
  function spng__inflate_init (line 1182) | static int spng__inflate_init(spng_ctx *ctx, int window_bits)
  function spng__deflate_init (line 1218) | static int spng__deflate_init(spng_ctx *ctx, struct spng__zlib_options *...
  function spng__inflate_stream (line 1244) | static int spng__inflate_stream(spng_ctx *ctx, char **out, size_t *len, ...
  function read_idat_bytes (line 1359) | static int read_idat_bytes(spng_ctx *ctx, uint32_t *bytes_read)
  function read_scanline_bytes (line 1389) | static int read_scanline_bytes(spng_ctx *ctx, unsigned char *dest, size_...
  function paeth (line 1425) | static uint8_t paeth(uint8_t a, uint8_t b, uint8_t c)
  function defilter_up (line 1439) | static void defilter_up(size_t bytes, unsigned char *row, const unsigned...
  function defilter_scanline (line 1452) | static int defilter_scanline(const unsigned char *prev_scanline, unsigne...
  function filter_scanline (line 1543) | static int filter_scanline(unsigned char *filtered, const unsigned char ...
  function filter_sum (line 1604) | static int32_t filter_sum(const unsigned char *prev_scanline, const unsi...
  function get_best_filter (line 1666) | static unsigned get_best_filter(const unsigned char *prev_scanline, cons...
  function sample_to_target (line 1712) | static uint16_t sample_to_target(uint16_t sample, unsigned bit_depth, un...
  function gamma_correct_row (line 1741) | static inline void gamma_correct_row(unsigned char *row, uint32_t pixels...
  function trns_row (line 1786) | static inline void trns_row(unsigned char *row,
  function scale_row (line 1863) | static inline void scale_row(unsigned char *row, uint32_t pixels, int fm...
  function expand_row (line 1928) | static void expand_row(unsigned char *row,
  function unpack_scanline (line 1983) | static void unpack_scanline(unsigned char *out, const unsigned char *sca...
  function check_ihdr (line 2030) | static int check_ihdr(const struct spng_ihdr *ihdr, uint32_t max_width, ...
  function check_plte (line 2077) | static int check_plte(const struct spng_plte *plte, const struct spng_ih...
  function check_sbit (line 2092) | static int check_sbit(const struct spng_sbit *sbit, const struct spng_ih...
  function check_chrm_int (line 2139) | static int check_chrm_int(const struct spng_chrm_int *chrm_int)
  function check_phys (line 2155) | static int check_phys(const struct spng_phys *phys)
  function check_time (line 2167) | static int check_time(const struct spng_time *time)
  function check_offs (line 2180) | static int check_offs(const struct spng_offs *offs)
  function check_exif (line 2189) | static int check_exif(const struct spng_exif *exif)
  function check_png_keyword (line 2206) | static int check_png_keyword(const char *str)
  function check_png_text (line 2231) | static int check_png_text(const char *str, size_t len)
  function is_small_chunk (line 2249) | static int is_small_chunk(uint8_t type[4])
  function read_ihdr (line 2265) | static int read_ihdr(spng_ctx *ctx)
  function splt_undo (line 2314) | static void splt_undo(spng_ctx *ctx)
  function text_undo (line 2328) | static void text_undo(spng_ctx *ctx)
  function chunk_undo (line 2344) | static void chunk_undo(spng_ctx *ctx)
  function read_non_idat_chunks (line 2358) | static int read_non_idat_chunks(spng_ctx *ctx)
  function read_chunks (line 3103) | static int read_chunks(spng_ctx *ctx, int only_ihdr)
  function read_scanline (line 3215) | static int read_scanline(spng_ctx *ctx)
  function update_row_info (line 3256) | static int update_row_info(spng_ctx *ctx)
  function spng_decode_scanline (line 3288) | int spng_decode_scanline(spng_ctx *ctx, void *out, size_t len)
  function spng_decode_row (line 3550) | int spng_decode_row(spng_ctx *ctx, void *out, size_t len)
  function spng_decode_chunks (line 3607) | int spng_decode_chunks(spng_ctx *ctx)
  function spng_decode_image (line 3617) | int spng_decode_image(spng_ctx *ctx, void *out, size_t len, int fmt, int...
  function spng_get_row_info (line 4008) | int spng_get_row_info(spng_ctx *ctx, struct spng_row_info *row_info)
  function write_chunks_before_idat (line 4019) | static int write_chunks_before_idat(spng_ctx *ctx)
  function write_chunks_after_idat (line 4475) | static int write_chunks_after_idat(spng_ctx *ctx)
  function write_idat_bytes (line 4486) | static int write_idat_bytes(spng_ctx *ctx, const void *scanline, size_t ...
  function finish_idat (line 4522) | static int finish_idat(spng_ctx *ctx)
  function encode_scanline (line 4561) | static int encode_scanline(spng_ctx *ctx, const void *scanline, size_t len)
  function encode_row (line 4625) | static int encode_row(spng_ctx *ctx, const void *row, size_t len)
  function spng_encode_scanline (line 4684) | int spng_encode_scanline(spng_ctx *ctx, const void *scanline, size_t len)
  function spng_encode_row (line 4693) | int spng_encode_row(spng_ctx *ctx, const void *row, size_t len)
  function spng_encode_chunks (line 4702) | int spng_encode_chunks(spng_ctx *ctx)
  function spng_encode_image (line 4736) | int spng_encode_image(spng_ctx *ctx, const void *img, size_t len, int fm...
  function spng_ctx (line 4877) | spng_ctx *spng_ctx_new(int flags)
  function spng_ctx (line 4890) | spng_ctx *spng_ctx_new2(struct spng_alloc *alloc, int flags)
  function spng_ctx_free (line 4948) | void spng_ctx_free(spng_ctx *ctx)
  function buffer_read_fn (line 5009) | static int buffer_read_fn(spng_ctx *ctx, void *user, void *data, size_t n)
  function file_read_fn (line 5023) | static int file_read_fn(spng_ctx *ctx, void *user, void *data, size_t n)
  function file_write_fn (line 5037) | static int file_write_fn(spng_ctx *ctx, void *user, void *data, size_t n)
  function spng_set_png_buffer (line 5047) | int spng_set_png_buffer(spng_ctx *ctx, const void *buf, size_t size)
  function spng_set_png_stream (line 5067) | int spng_set_png_stream(spng_ctx *ctx, spng_rw_fn *rw_func, void *user)
  function spng_set_png_file (line 5103) | int spng_set_png_file(spng_ctx *ctx, FILE *file)
  function spng_set_image_limits (line 5137) | int spng_set_image_limits(spng_ctx *ctx, uint32_t width, uint32_t height)
  function spng_get_image_limits (line 5149) | int spng_get_image_limits(spng_ctx *ctx, uint32_t *width, uint32_t *height)
  function spng_set_chunk_limits (line 5159) | int spng_set_chunk_limits(spng_ctx *ctx, size_t chunk_size, size_t cache...
  function spng_get_chunk_limits (line 5170) | int spng_get_chunk_limits(spng_ctx *ctx, size_t *chunk_size, size_t *cac...
  function spng_set_crc_action (line 5181) | int spng_set_crc_action(spng_ctx *ctx, int critical, int ancillary)
  function spng_set_option (line 5197) | int spng_set_option(spng_ctx *ctx, enum spng_option option, int value)
  function spng_get_option (line 5284) | int spng_get_option(spng_ctx *ctx, enum spng_option option, int *value)
  function spng_decoded_image_size (line 5359) | int spng_decoded_image_size(spng_ctx *ctx, int fmt, size_t *len)
  function spng_get_ihdr (line 5372) | int spng_get_ihdr(spng_ctx *ctx, struct spng_ihdr *ihdr)
  function spng_get_plte (line 5384) | int spng_get_plte(spng_ctx *ctx, struct spng_plte *plte)
  function spng_get_trns (line 5393) | int spng_get_trns(spng_ctx *ctx, struct spng_trns *trns)
  function spng_get_chrm (line 5402) | int spng_get_chrm(spng_ctx *ctx, struct spng_chrm *chrm)
  function spng_get_chrm_int (line 5418) | int spng_get_chrm_int(spng_ctx *ctx, struct spng_chrm_int *chrm)
  function spng_get_gama (line 5427) | int spng_get_gama(spng_ctx *ctx, double *gamma)
  function spng_get_gama_int (line 5437) | int spng_get_gama_int(spng_ctx *ctx, uint32_t *gama_int)
  function spng_get_iccp (line 5447) | int spng_get_iccp(spng_ctx *ctx, struct spng_iccp *iccp)
  function spng_get_sbit (line 5456) | int spng_get_sbit(spng_ctx *ctx, struct spng_sbit *sbit)
  function spng_get_srgb (line 5465) | int spng_get_srgb(spng_ctx *ctx, uint8_t *rendering_intent)
  function spng_get_text (line 5475) | int spng_get_text(spng_ctx *ctx, struct spng_text *text, uint32_t *n_text)
  function spng_get_bkgd (line 5507) | int spng_get_bkgd(spng_ctx *ctx, struct spng_bkgd *bkgd)
  function spng_get_hist (line 5516) | int spng_get_hist(spng_ctx *ctx, struct spng_hist *hist)
  function spng_get_phys (line 5525) | int spng_get_phys(spng_ctx *ctx, struct spng_phys *phys)
  function spng_get_splt (line 5534) | int spng_get_splt(spng_ctx *ctx, struct spng_splt *splt, uint32_t *n_splt)
  function spng_get_time (line 5555) | int spng_get_time(spng_ctx *ctx, struct spng_time *time)
  function spng_get_unknown_chunks (line 5564) | int spng_get_unknown_chunks(spng_ctx *ctx, struct spng_unknown_chunk *ch...
  function spng_get_offs (line 5585) | int spng_get_offs(spng_ctx *ctx, struct spng_offs *offs)
  function spng_get_exif (line 5594) | int spng_get_exif(spng_ctx *ctx, struct spng_exif *exif)
  function spng_set_ihdr (line 5603) | int spng_set_ihdr(spng_ctx *ctx, struct spng_ihdr *ihdr)
  function spng_set_plte (line 5620) | int spng_set_plte(spng_ctx *ctx, struct spng_plte *plte)
  function spng_set_trns (line 5638) | int spng_set_trns(spng_ctx *ctx, struct spng_trns *trns)
  function spng_set_chrm (line 5670) | int spng_set_chrm(spng_ctx *ctx, struct spng_chrm *chrm)
  function spng_set_chrm_int (line 5695) | int spng_set_chrm_int(spng_ctx *ctx, struct spng_chrm_int *chrm_int)
  function spng_set_gama (line 5709) | int spng_set_gama(spng_ctx *ctx, double gamma)
  function spng_set_gama_int (line 5726) | int spng_set_gama_int(spng_ctx *ctx, uint32_t gamma)
  function spng_set_iccp (line 5741) | int spng_set_iccp(spng_ctx *ctx, struct spng_iccp *iccp)
  function spng_set_sbit (line 5759) | int spng_set_sbit(spng_ctx *ctx, struct spng_sbit *sbit)
  function spng_set_srgb (line 5775) | int spng_set_srgb(spng_ctx *ctx, uint8_t rendering_intent)
  function spng_set_text (line 5789) | int spng_set_text(spng_ctx *ctx, struct spng_text *text, uint32_t n_text)
  function spng_set_bkgd (line 5869) | int spng_set_bkgd(spng_ctx *ctx, struct spng_bkgd *bkgd)
  function spng_set_hist (line 5899) | int spng_set_hist(spng_ctx *ctx, struct spng_hist *hist)
  function spng_set_phys (line 5913) | int spng_set_phys(spng_ctx *ctx, struct spng_phys *phys)
  function spng_set_splt (line 5927) | int spng_set_splt(spng_ctx *ctx, struct spng_splt *splt, uint32_t n_splt)
  function spng_set_time (line 5957) | int spng_set_time(spng_ctx *ctx, struct spng_time *time)
  function spng_set_unknown_chunks (line 5971) | int spng_set_unknown_chunks(spng_ctx *ctx, struct spng_unknown_chunk *ch...
  function spng_set_offs (line 6010) | int spng_set_offs(spng_ctx *ctx, struct spng_offs *offs)
  function spng_set_exif (line 6024) | int spng_set_exif(spng_ctx *ctx, struct spng_exif *exif)
  function __m128i (line 6223) | static __m128i load4(const void* p)
  function store4 (line 6230) | static void store4(void* p, __m128i v)
  function __m128i (line 6236) | static __m128i load3(const void* p)
  function store3 (line 6243) | static void store3(void* p, __m128i v)
  function defilter_sub3 (line 6249) | static void defilter_sub3(size_t rowbytes, unsigned char *row)
  function defilter_sub4 (line 6277) | static void defilter_sub4(size_t rowbytes, unsigned char *row)
  function defilter_avg3 (line 6298) | static void defilter_avg3(size_t rowbytes, unsigned char *row, const uns...
  function defilter_avg4 (line 6349) | static void defilter_avg4(size_t rowbytes, unsigned char *row, const uns...
  function __m128i (line 6385) | __attribute__((target("ssse3")))
  function __m128i (line 6407) | static __m128i if_then_else(__m128i c, __m128i t, __m128i e)
  function defilter_paeth3 (line 6416) | static void defilter_paeth3(size_t rowbytes, unsigned char *row, const u...
  function defilter_paeth4 (line 6508) | static void defilter_paeth4(size_t rowbytes, unsigned char *row, const u...
  function defilter_sub3 (line 6611) | static void defilter_sub3(size_t rowbytes, unsigned char *row)
  function defilter_sub4 (line 6652) | static void defilter_sub4(size_t rowbytes, unsigned char *row)
  function defilter_avg3 (line 6678) | static void defilter_avg3(size_t rowbytes, unsigned char *row, const uns...
  function defilter_avg4 (line 6742) | static void defilter_avg4(size_t rowbytes, unsigned char *row, const uns...
  function uint8x8_t (line 6780) | static uint8x8_t paeth_arm(uint8x8_t a, uint8x8_t b, uint8x8_t c)
  function defilter_paeth3 (line 6806) | static void defilter_paeth3(size_t rowbytes, unsigned char *row, const u...
  function defilter_paeth4 (line 6870) | static void defilter_paeth4(size_t rowbytes, unsigned char *row, const u...
  function expand_palette_rgba8_neon (line 6929) | static uint32_t expand_palette_rgba8_neon(unsigned char *row, const unsi...
  function expand_palette_rgb8_neon (line 6953) | static uint32_t expand_palette_rgb8_neon(unsigned char *row, const unsig...

FILE: jni/libspng/spng.h
  type spng_errno (line 33) | enum spng_errno
  type spng_text_type (line 125) | enum spng_text_type
  type spng_color_type (line 132) | enum spng_color_type
  type spng_filter (line 141) | enum spng_filter
  type spng_filter_choice (line 150) | enum spng_filter_choice
  type spng_interlace_method (line 161) | enum spng_interlace_method
  type spng_format (line 168) | enum spng_format
  type spng_ctx_flags (line 184) | enum spng_ctx_flags
  type spng_decode_flags (line 190) | enum spng_decode_flags
  type spng_crc_action (line 201) | enum spng_crc_action
  type spng_encode_flags (line 215) | enum spng_encode_flags
  type spng_ihdr (line 221) | struct spng_ihdr
  type spng_plte_entry (line 232) | struct spng_plte_entry
  type spng_plte (line 241) | struct spng_plte
  type spng_trns (line 247) | struct spng_trns
  type spng_chrm_int (line 259) | struct spng_chrm_int
  type spng_chrm (line 271) | struct spng_chrm
  type spng_iccp (line 283) | struct spng_iccp
  type spng_sbit (line 290) | struct spng_sbit
  type spng_text (line 299) | struct spng_text
  type spng_bkgd (line 313) | struct spng_bkgd
  type spng_hist (line 322) | struct spng_hist
  type spng_phys (line 327) | struct spng_phys
  type spng_splt_entry (line 333) | struct spng_splt_entry
  type spng_splt (line 342) | struct spng_splt
  type spng_time (line 350) | struct spng_time
  type spng_offs (line 360) | struct spng_offs
  type spng_exif (line 366) | struct spng_exif
  type spng_chunk (line 372) | struct spng_chunk
  type spng_location (line 380) | enum spng_location
  type spng_unknown_chunk (line 387) | struct spng_unknown_chunk
  type spng_option (line 395) | enum spng_option
  type spng_alloc (line 419) | struct spng_alloc
  type spng_row_info (line 427) | struct spng_row_info
  type spng_ctx (line 435) | typedef struct spng_ctx spng_ctx;
  type spng_alloc (line 443) | struct spng_alloc
  type spng_option (line 460) | enum spng_option
  type spng_option (line 461) | enum spng_option
  type spng_row_info (line 474) | struct spng_row_info
  type spng_ihdr (line 484) | struct spng_ihdr
  type spng_plte (line 485) | struct spng_plte
  type spng_trns (line 486) | struct spng_trns
  type spng_chrm (line 487) | struct spng_chrm
  type spng_chrm_int (line 488) | struct spng_chrm_int
  type spng_iccp (line 491) | struct spng_iccp
  type spng_sbit (line 492) | struct spng_sbit
  type spng_text (line 494) | struct spng_text
  type spng_bkgd (line 495) | struct spng_bkgd
  type spng_hist (line 496) | struct spng_hist
  type spng_phys (line 497) | struct spng_phys
  type spng_splt (line 498) | struct spng_splt
  type spng_time (line 499) | struct spng_time
  type spng_unknown_chunk (line 500) | struct spng_unknown_chunk
  type spng_offs (line 503) | struct spng_offs
  type spng_exif (line 504) | struct spng_exif
  type spng_ihdr (line 507) | struct spng_ihdr
  type spng_plte (line 508) | struct spng_plte
  type spng_trns (line 509) | struct spng_trns
  type spng_chrm (line 510) | struct spng_chrm
  type spng_chrm_int (line 511) | struct spng_chrm_int
  type spng_iccp (line 514) | struct spng_iccp
  type spng_sbit (line 515) | struct spng_sbit
  type spng_text (line 517) | struct spng_text
  type spng_bkgd (line 518) | struct spng_bkgd
  type spng_hist (line 519) | struct spng_hist
  type spng_phys (line 520) | struct spng_phys
  type spng_splt (line 521) | struct spng_splt
  type spng_time (line 522) | struct spng_time
  type spng_unknown_chunk (line 523) | struct spng_unknown_chunk
  type spng_offs (line 526) | struct spng_offs
  type spng_exif (line 527) | struct spng_exif

FILE: jni/lz4/lz4.c
  function LZ4_isAligned (line 291) | static int LZ4_isAligned(const void* ptr, size_t alignment)
  type BYTE (line 303) | typedef  uint8_t BYTE;
  type U16 (line 304) | typedef uint16_t U16;
  type U32 (line 305) | typedef uint32_t U32;
  type S32 (line 306) | typedef  int32_t S32;
  type U64 (line 307) | typedef uint64_t U64;
  type uptrval (line 308) | typedef uintptr_t uptrval;
  type BYTE (line 313) | typedef unsigned char       BYTE;
  type U16 (line 314) | typedef unsigned short      U16;
  type U32 (line 315) | typedef unsigned int        U32;
  type S32 (line 316) | typedef   signed int        S32;
  type U64 (line 317) | typedef unsigned long long  U64;
  type uptrval (line 318) | typedef size_t              uptrval;
  type U64 (line 322) | typedef U64    reg_t;
  type reg_t (line 324) | typedef size_t reg_t;
  type limitedOutput_directive (line 327) | typedef enum {
  function LZ4_isLittleEndian (line 362) | static unsigned LZ4_isLittleEndian(void)
  function U16 (line 372) | static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; }
  function U32 (line 373) | static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; }
  function reg_t (line 374) | static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) ...
  function LZ4_write16 (line 376) | static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; }
  function LZ4_write32 (line 377) | static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; }
  type LZ4_unalign16 (line 383) | typedef struct { U16 u16; } __attribute__((packed)) LZ4_unalign16;
  type LZ4_unalign32 (line 384) | typedef struct { U32 u32; } __attribute__((packed)) LZ4_unalign32;
  type LZ4_unalignST (line 385) | typedef struct { reg_t uArch; } __attribute__((packed)) LZ4_unalignST;
  function U16 (line 387) | static U16 LZ4_read16(const void* ptr) { return ((const LZ4_unalign16*)p...
  function U32 (line 388) | static U32 LZ4_read32(const void* ptr) { return ((const LZ4_unalign32*)p...
  function reg_t (line 389) | static reg_t LZ4_read_ARCH(const void* ptr) { return ((const LZ4_unalign...
  function LZ4_write16 (line 391) | static void LZ4_write16(void* memPtr, U16 value) { ((LZ4_unalign16*)memP...
  function LZ4_write32 (line 392) | static void LZ4_write32(void* memPtr, U32 value) { ((LZ4_unalign32*)memP...
  function U16 (line 396) | static U16 LZ4_read16(const void* memPtr)
  function U32 (line 401) | static U32 LZ4_read32(const void* memPtr)
  function reg_t (line 406) | static reg_t LZ4_read_ARCH(const void* memPtr)
  function LZ4_write16 (line 411) | static void LZ4_write16(void* memPtr, U16 value)
  function LZ4_write32 (line 416) | static void LZ4_write32(void* memPtr, U32 value)
  function U16 (line 424) | static U16 LZ4_readLE16(const void* memPtr)
  function LZ4_writeLE16 (line 434) | static void LZ4_writeLE16(void* memPtr, U16 value)
  function LZ4_FORCE_INLINE (line 446) | LZ4_FORCE_INLINE
  function LZ4_FORCE_INLINE (line 477) | LZ4_FORCE_INLINE void
  function LZ4_FORCE_INLINE (line 503) | LZ4_FORCE_INLINE void
  function LZ4_FORCE_INLINE (line 516) | LZ4_FORCE_INLINE void
  function LZ4_NbCommonBytes (line 561) | static unsigned LZ4_NbCommonBytes (reg_t val)
  function LZ4_count (line 661) | LZ4_FORCE_INLINE
  type tableType_t (line 699) | typedef enum { clearedTable = 0, byPtr, byU32, byU16 } tableType_t;
  type dict_directive (line 724) | typedef enum { noDict = 0, withPrefix64k, usingExtDict, usingDictCtx } d...
  type dictIssue_directive (line 725) | typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
  function LZ4_versionNumber (line 731) | int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
  function LZ4_compressBound (line 733) | int LZ4_compressBound(int isize)  { return LZ4_COMPRESSBOUND(isize); }
  function LZ4_sizeofState (line 734) | int LZ4_sizeofState(void) { return sizeof(LZ4_stream_t); }
  function LZ4_FORCE_INLINE (line 759) | LZ4_FORCE_INLINE U32 LZ4_hash4(U32 sequence, tableType_t const tableType)
  function LZ4_FORCE_INLINE (line 767) | LZ4_FORCE_INLINE U32 LZ4_hash5(U64 sequence, tableType_t const tableType)
  function LZ4_FORCE_INLINE (line 779) | LZ4_FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t c...
  function LZ4_FORCE_INLINE (line 785) | LZ4_FORCE_INLINE void LZ4_clearHash(U32 h, void* tableBase, tableType_t ...
  function LZ4_FORCE_INLINE (line 797) | LZ4_FORCE_INLINE void LZ4_putIndexOnHash(U32 idx, U32 h, void* tableBase...
  function LZ4_FORCE_INLINE (line 810) | LZ4_FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h,
  function LZ4_FORCE_INLINE (line 818) | LZ4_FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, ta...
  function LZ4_FORCE_INLINE (line 830) | LZ4_FORCE_INLINE U32 LZ4_getIndexOnHash(U32 h, const void* tableBase, ta...
  function BYTE (line 846) | static const BYTE* LZ4_getPositionOnHash(U32 h, const void* tableBase, t...
  function LZ4_FORCE_INLINE (line 852) | LZ4_FORCE_INLINE const BYTE*
  function LZ4_FORCE_INLINE (line 860) | LZ4_FORCE_INLINE void
  function LZ4_FORCE_INLINE (line 907) | LZ4_FORCE_INLINE int LZ4_compress_generic_validated(
  function LZ4_FORCE_INLINE (line 1318) | LZ4_FORCE_INLINE int LZ4_compress_generic(
  function LZ4_compress_fast_extState (line 1356) | int LZ4_compress_fast_extState(void* state, const char* source, char* de...
  function LZ4_compress_fast_extState_fastReset (line 1388) | int LZ4_compress_fast_extState_fastReset(void* state, const char* src, c...
  function LZ4_compress_fast (line 1427) | int LZ4_compress_fast(const char* src, char* dest, int srcSize, int dstC...
  function LZ4_compress_default (line 1446) | int LZ4_compress_default(const char* src, char* dst, int srcSize, int ds...
  function LZ4_compress_destSize_extState (line 1455) | static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const ch...
  function LZ4_compress_destSize (line 1472) | int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, i...
  function LZ4_stream_t (line 1497) | LZ4_stream_t* LZ4_createStream(void)
  function LZ4_stream_t_alignment (line 1508) | static size_t LZ4_stream_t_alignment(void)
  function LZ4_stream_t (line 1518) | LZ4_stream_t* LZ4_initStream (void* buffer, size_t size)
  function LZ4_resetStream (line 1530) | void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
  function LZ4_resetStream_fast (line 1536) | void LZ4_resetStream_fast(LZ4_stream_t* ctx) {
  function LZ4_freeStream (line 1541) | int LZ4_freeStream (LZ4_stream_t* LZ4_stream)
  function LZ4_loadDict (line 1552) | int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int di...
  function LZ4_attach_dictionary (line 1595) | void LZ4_attach_dictionary(LZ4_stream_t* workingStream, const LZ4_stream...
  function LZ4_renormDictT (line 1624) | static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, int nextSize)
  function LZ4_compress_fast_continue (line 1644) | int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream,
  function LZ4_compress_forceExtDict (line 1724) | int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* sourc...
  function LZ4_saveDict (line 1751) | int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize)
  type earlyEnd_directive (line 1779) | typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_dire...
  function read_long_length_no_check (line 1789) | size_t read_long_length_no_check(const BYTE** pp)
  function LZ4_FORCE_INLINE (line 1806) | LZ4_FORCE_INLINE int
  type Rvl_t (line 1913) | typedef size_t Rvl_t;
  function LZ4_FORCE_INLINE (line 1915) | LZ4_FORCE_INLINE Rvl_t
  function LZ4_FORCE_O2 (line 2372) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2380) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2389) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2400) | LZ4_FORCE_O2 /* Exported, an obsolete API function. */
  function LZ4_FORCE_O2 (line 2408) | LZ4_FORCE_O2
  function LZ4_decompress_fast_withPrefix64k (line 2418) | int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, in...
  function LZ4_FORCE_O2 (line 2425) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2434) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2444) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2455) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2466) | LZ4_FORCE_O2
  function LZ4_FORCE_INLINE (line 2479) | LZ4_FORCE_INLINE
  function LZ4_streamDecode_t (line 2491) | LZ4_streamDecode_t* LZ4_createStreamDecode(void)
  function LZ4_freeStreamDecode (line 2497) | int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream)
  function LZ4_setStreamDecode (line 2511) | int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const cha...
  function LZ4_decoderRingBufferSize (line 2537) | int LZ4_decoderRingBufferSize(int maxBlockSize)
  function LZ4_FORCE_O2 (line 2552) | LZ4_FORCE_O2
  function LZ4_FORCE_O2 (line 2592) | LZ4_FORCE_O2 int
  function LZ4_decompress_safe_usingDict (line 2641) | int LZ4_decompress_safe_usingDict(const char* source, char* dest, int co...
  function LZ4_decompress_safe_partial_usingDict (line 2656) | int LZ4_decompress_safe_partial_usingDict(const char* source, char* dest...
  function LZ4_decompress_fast_usingDict (line 2671) | int LZ4_decompress_fast_usingDict(const char* source, char* dest, int or...
  function LZ4_compress_limitedOutput (line 2686) | int LZ4_compress_limitedOutput(const char* source, char* dest, int input...
  function LZ4_compress (line 2690) | int LZ4_compress(const char* src, char* dest, int srcSize)
  function LZ4_compress_limitedOutput_withState (line 2694) | int LZ4_compress_limitedOutput_withState (void* state, const char* src, ...
  function LZ4_compress_withState (line 2698) | int LZ4_compress_withState (void* state, const char* src, char* dst, int...
  function LZ4_compress_limitedOutput_continue (line 2702) | int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const...
  function LZ4_compress_continue (line 2706) | int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source,...
  function LZ4_uncompress (line 2717) | int LZ4_uncompress (const char* source, char* dest, int outputSize)
  function LZ4_uncompress_unknownOutputSize (line 2721) | int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, in...
  function LZ4_sizeofStreamState (line 2728) | int LZ4_sizeofStreamState(void) { return sizeof(LZ4_stream_t); }
  function LZ4_resetStreamState (line 2730) | int LZ4_resetStreamState(void* state, char* inputBuffer)

FILE: jni/lz4/lz4.h
  type LZ4_stream_t (line 313) | typedef union LZ4_stream_u LZ4_stream_t;
  type LZ4_streamDecode_t (line 411) | typedef union LZ4_streamDecode_u LZ4_streamDecode_t;
  type LZ4_i8 (line 680) | typedef  int8_t  LZ4_i8;
  type LZ4_byte (line 681) | typedef uint8_t  LZ4_byte;
  type LZ4_u16 (line 682) | typedef uint16_t LZ4_u16;
  type LZ4_u32 (line 683) | typedef uint32_t LZ4_u32;
  type LZ4_i8 (line 685) | typedef   signed char  LZ4_i8;
  type LZ4_byte (line 686) | typedef unsigned char  LZ4_byte;
  type LZ4_u16 (line 687) | typedef unsigned short LZ4_u16;
  type LZ4_u32 (line 688) | typedef unsigned int   LZ4_u32;
  type LZ4_stream_t_internal (line 697) | typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
  type LZ4_stream_t_internal (line 698) | struct LZ4_stream_t_internal {
  type LZ4_streamDecode_t_internal (line 737) | typedef struct {

FILE: jni/msp/msp.c
  function msp_data_from_msg (line 6) | uint16_t msp_data_from_msg(uint8_t message_buffer[], msp_msg_t *msg) {
  function msp_error_e (line 12) | msp_error_e construct_msp_command(uint8_t message_buffer[], uint8_t comm...
  function msp_error_e (line 33) | msp_error_e msp_process_data(msp_state_t *msp_state, uint8_t dat)

FILE: jni/msp/msp.h
  type msp_error_e (line 20) | typedef enum {
  type msp_state_machine_e (line 27) | typedef enum {
  type msp_direction_e (line 37) | typedef enum {
  type msp_msg_t (line 42) | typedef struct msp_msg_s {
  type msp_state_t (line 52) | typedef struct msp_state_s {

FILE: jni/msp/msp_displayport.c
  function process_draw_string (line 4) | static void process_draw_string(displayport_vtable_t *display_driver, ui...
  function process_clear_screen (line 26) | static void process_clear_screen(displayport_vtable_t *display_driver) {
  function process_draw_complete (line 31) | static void process_draw_complete(displayport_vtable_t *display_driver) {
  function process_set_options (line 36) | static void process_set_options(displayport_vtable_t *display_driver, ui...
  function process_open (line 43) | static void process_open(displayport_vtable_t *display_driver) {
  function process_close (line 47) | static void process_close(displayport_vtable_t *display_driver) {
  function displayport_process_message (line 51) | int displayport_process_message(displayport_vtable_t *display_driver, ms...

FILE: jni/msp/msp_displayport.h
  type msp_displayport_cmd_e (line 5) | typedef enum {
  type msp_hd_options_e (line 15) | typedef enum {
  type displayport_vtable_t (line 27) | typedef struct displayport_vtable_s {

FILE: jni/msp_displayport_mux.c
  type msp_cache_entry_t (line 46) | typedef struct msp_cache_entry_s {
  function sig_handler (line 77) | static void sig_handler(int _)
  function cache_msp_message (line 82) | static uint8_t cache_msp_message(msp_msg_t *msp_message) {
  function msp_msg_from_cache (line 99) | static int16_t msp_msg_from_cache(uint8_t msg_buffer[], uint8_t cmd_id) {
  function send_display_size (line 126) | static void send_display_size(int serial_fd) {
  function send_variant_request (line 133) | static void send_variant_request(int serial_fd) {
  function send_version_request (line 139) | static void send_version_request(int serial_fd) {
  function copy_to_msp_frame_buffer (line 145) | static void copy_to_msp_frame_buffer(void *buffer, uint16_t size) {
  function rx_msp_callback (line 150) | static void rx_msp_callback(msp_msg_t *msp_message)
  function tx_msp_callback (line 223) | static void tx_msp_callback(msp_msg_t *msp_message)
  function send_data_packet (line 246) | static void send_data_packet(int data_socket_fd, dji_shm_state_t *dji_sh...
  function msp_draw_character (line 259) | static void msp_draw_character(uint32_t x, uint32_t y, uint16_t c) {
  function msp_clear_screen (line 264) | static void msp_clear_screen() {
  function msp_draw_complete (line 268) | static void msp_draw_complete() {
  function msp_set_options (line 272) | static void msp_set_options(uint8_t font_num, msp_hd_options_e is_hd) {
  function send_compressed_screen (line 278) | static void send_compressed_screen(int compressed_fd) {
  function main (line 291) | int main(int argc, char *argv[]) {

FILE: jni/net/data_protocol.h
  type packet_data_t (line 3) | typedef struct packet_data_s {
  type compressed_data_header_t (line 10) | typedef struct compressed_data_header_s {

FILE: jni/net/network.c
  function connect_to_server (line 10) | int connect_to_server(char *address, int port)
  function bind_socket (line 40) | int bind_socket(int port)

FILE: jni/net/serial.c
  function open_serial_port (line 15) | int open_serial_port(const char *device, speed_t baudrate)
  function open_pty (line 35) | int open_pty(const char **pty_name)
  function openpty (line 105) | int

FILE: jni/net/serial.h
  type termios (line 9) | struct termios
  type winsize (line 10) | struct winsize

FILE: jni/osd_dji_overlay_udp.c
  type timespec (line 81) | struct timespec
  type display_mode_s (line 127) | enum display_mode_s {
  function draw_character (line 137) | static void draw_character(display_info_t *display_info, uint16_t charac...
  function msp_draw_character (line 145) | static void msp_draw_character(uint32_t x, uint32_t y, uint16_t c) {
  function draw_character_map (line 151) | static void draw_character_map(display_info_t *display_info, void* restr...
  function clear_framebuffer (line 190) | static void clear_framebuffer() {
  function draw_screen (line 196) | static void draw_screen() {
  function clear_overlay (line 210) | static void clear_overlay() {
  function msp_clear_screen (line 214) | static void msp_clear_screen() {
  function render_screen (line 219) | static void render_screen() {
  function msp_draw_complete (line 229) | static void msp_draw_complete() {
  function msp_callback (line 243) | static void msp_callback(msp_msg_t *msp_message)
  function load_fonts (line 248) | static void load_fonts(char* font_variant) {
  function close_all_fonts (line 258) | static void close_all_fonts() {
  function msp_set_options (line 265) | static void msp_set_options(uint8_t font_num, msp_hd_options_e is_hd) {
  function display_print_string (line 284) | static void display_print_string(uint8_t init_x, uint8_t y, const char *...
  function start_display (line 292) | static void start_display(uint8_t is_v2_goggles,duss_disp_instance_handl...
  function stop_display (line 305) | static void stop_display() {
  function check_is_au_overlay_enabled (line 316) | static void check_is_au_overlay_enabled()
  function process_data_packet (line 328) | static void process_data_packet(uint8_t *buf, int len, dji_shm_state_t *...
  function process_compressed_data (line 354) | static void process_compressed_data(void *buf, int len, void *dict, int ...
  function rec_msp_draw_complete_hook (line 385) | static void rec_msp_draw_complete_hook()
  function rec_pb_play_loop (line 416) | static void rec_pb_play_loop()
  function rec_pb_timeout_hook (line 443) | static void rec_pb_timeout_hook()
  function osd_disable (line 516) | void osd_disable() {
  function osd_enable (line 521) | void osd_enable() {
  function osd_directfb (line 528) | void osd_directfb(duss_disp_instance_handle_t *disp, duss_hal_obj_handle...

FILE: jni/osd_dji_udp.c
  type display_info_t (line 59) | typedef struct display_info_s {
  function sig_handler (line 112) | static void sig_handler(int _)
  function draw_character (line 117) | static void draw_character(display_info_t *display_info, uint16_t charac...
  function msp_draw_character (line 125) | static void msp_draw_character(uint32_t x, uint32_t y, uint16_t c) {
  function draw_character_map (line 129) | static void draw_character_map(display_info_t *display_info, void *fb_ad...
  function draw_screen (line 168) | static void draw_screen() {
  function msp_clear_screen (line 177) | static void msp_clear_screen()
  function msp_draw_complete (line 182) | static void msp_draw_complete() {
  function msp_callback (line 189) | static void msp_callback(msp_msg_t *msp_message)
  function get_font_path_with_prefix (line 194) | static void get_font_path_with_prefix(char *font_path_dest, const char *...
  function open_font (line 208) | static int open_font(const char *filename, void** font, uint8_t page, ui...
  function load_font (line 241) | static void load_font() {
  function close_fonts (line 274) | static void close_fonts(display_info_t *display_info) {
  function msp_set_options (line 285) | static void msp_set_options(uint8_t font_num, uint8_t is_hd) {
  function display_print_string (line 294) | static void display_print_string(uint8_t init_x, uint8_t y, const char *...
  function start_display (line 300) | static void start_display(uint8_t is_v2_goggles) {
  function stop_display (line 310) | static void stop_display() {
  function process_data_packet (line 316) | static void process_data_packet(uint8_t *buf, int len, dji_shm_state_t *...
  function main (line 335) | int main(int argc, char *argv[])

FILE: jni/osd_sfml_udp.c
  type display_info_t (line 28) | typedef struct display_info_s {
  function sig_handler (line 62) | static void sig_handler(int _)
  function draw_character (line 67) | static void draw_character(uint32_t x, uint32_t y, uint16_t c)
  function draw_screen (line 76) | static void draw_screen()
  function clear_screen (line 105) | static void clear_screen()
  function draw_complete (line 111) | static void draw_complete()
  function msp_callback (line 118) | static void msp_callback(msp_msg_t *msp_message)
  function set_options (line 123) | static void set_options(uint8_t font, uint8_t is_hd) {
  function main (line 131) | int main(int argc, char *argv[])

FILE: jni/rec/rec.c
  function rec_start (line 27) | void rec_start(rec_config_t *config)
  function rec_stop (line 71) | void rec_stop()
  function rec_write_frame (line 83) | void rec_write_frame(uint16_t *frame_data, size_t frame_size)
  function rec_load_config (line 97) | void rec_load_config()
  function rec_is_enabled (line 104) | bool rec_is_enabled()
  function rec_is_osd_recording (line 109) | bool rec_is_osd_recording()
  function rec_is_gls_recording (line 114) | bool rec_is_gls_recording()
  function rec_is_ready (line 122) | static bool rec_is_ready()
  function rec_get_frame_idx (line 127) | static uint32_t rec_get_frame_idx()

FILE: jni/rec/rec.h
  type rec_config_t (line 9) | typedef struct rec_config_t
  type rec_file_header_t (line 20) | typedef struct rec_file_header_t
  type rec_config_v1_t (line 27) | typedef struct rec_config_v1_t
  type rec_file_header_v1_t (line 38) | typedef struct rec_file_header_v1_t
  type rec_frame_header_t (line 45) | typedef struct rec_frame_header_t

FILE: jni/rec/rec_pb.c
  function rec_pb_load_config (line 46) | void rec_pb_load_config()
  function rec_pb_is_enabled (line 53) | bool rec_pb_is_enabled()
  function rec_pb_start (line 58) | int rec_pb_start()
  function rec_pb_stop (line 177) | void rec_pb_stop()
  function rec_config_t (line 194) | rec_config_t *rec_pb_get_config()
  function rec_pb_do_next_frame (line 204) | int rec_pb_do_next_frame(uint16_t *map_out)
  function rec_pb_gls_is_playing (line 236) | bool rec_pb_gls_is_playing()
  function rec_pb_is_ready (line 247) | bool rec_pb_is_ready()

FILE: jni/rec/rec_shim.c
  function duss_osal_priority_t (line 23) | duss_osal_priority_t duss_osal_task_create(

FILE: jni/rec/rec_shim.h
  type undefined (line 5) | typedef unsigned char undefined;
  type byte (line 7) | typedef unsigned char byte;
  type dword (line 8) | typedef unsigned int dword;
  type longlong (line 9) | typedef long long longlong;
  type qword (line 10) | typedef unsigned long long qword;
  type uchar (line 11) | typedef unsigned char uchar;
  type uint (line 12) | typedef unsigned int uint;
  type ulong (line 13) | typedef unsigned long ulong;
  type ulonglong (line 14) | typedef unsigned long long ulonglong;
  type undefined1 (line 15) | typedef unsigned char undefined1;
  type undefined2 (line 16) | typedef unsigned short undefined2;
  type undefined4 (line 17) | typedef unsigned int undefined4;
  type undefined8 (line 18) | typedef unsigned long long undefined8;
  type ushort (line 19) | typedef unsigned short ushort;
  type word (line 20) | typedef unsigned short word;
  type __gs_info (line 21) | typedef struct __gs_info __gs_info;
  type gs_info_t (line 23) | typedef struct __gs_info gs_info_t;
  type duss_event_client (line 25) | typedef struct duss_event_client duss_event_client;
  type duss_event_client (line 27) | struct duss_event_client
  type duss_hal_obj (line 29) | typedef struct duss_hal_obj duss_hal_obj;
  type duss_hal_obj (line 31) | struct duss_hal_obj
  type __int32_t (line 33) | typedef int __int32_t;
  type __int32_t (line 35) | typedef __int32_t int32_t;
  type gs_debug_ctrl (line 37) | typedef struct gs_debug_ctrl gs_debug_ctrl;
  type gs_debug_ctrl_t (line 39) | typedef struct gs_debug_ctrl gs_debug_ctrl_t;
  type duss_osal_task_handle_t (line 41) | typedef struct duss_osal_task_handle_t duss_osal_task_handle_t;
  type __gs_local_sd_info (line 43) | typedef struct __gs_local_sd_info __gs_local_sd_info;
  type gs_local_sd_info_t (line 45) | typedef struct __gs_local_sd_info gs_local_sd_info_t;
  type duss_osal_timer_handle_t (line 47) | typedef struct duss_osal_timer_handle_t duss_osal_timer_handle_t;
  type _DUSS_MSG_RC_BAT_INFO_t (line 49) | typedef struct _DUSS_MSG_RC_BAT_INFO_t _DUSS_MSG_RC_BAT_INFO_t;
  type DUSS_MSG_RC_BAT_INFO_t (line 51) | typedef struct _DUSS_MSG_RC_BAT_INFO_t DUSS_MSG_RC_BAT_INFO_t;
  type gs_battery_info (line 53) | typedef struct gs_battery_info gs_battery_info;
  type gs_battery_info_t (line 55) | typedef struct gs_battery_info gs_battery_info_t;
  type uchar (line 57) | typedef uchar __uint8_t;
  type __uint8_t (line 59) | typedef __uint8_t uint8_t;
  type gs_modem_ctrl (line 61) | typedef struct gs_modem_ctrl gs_modem_ctrl;
  type gs_modem_ctrl_t (line 63) | typedef struct gs_modem_ctrl gs_modem_ctrl_t;
  type _DUSS_MSG_RC_MS_LINK_STATUS (line 65) | typedef struct _DUSS_MSG_RC_MS_LINK_STATUS _DUSS_MSG_RC_MS_LINK_STATUS;
  type DUSS_MSG_RC_MS_LINK_STATUS_t (line 67) | typedef struct _DUSS_MSG_RC_MS_LINK_STATUS DUSS_MSG_RC_MS_LINK_STATUS_t;
  type __gs_use_times_info (line 69) | typedef struct __gs_use_times_info __gs_use_times_info;
  type gs_use_times_info_t (line 71) | typedef struct __gs_use_times_info gs_use_times_info_t;
  type gs_rc_ctrl (line 73) | typedef struct gs_rc_ctrl gs_rc_ctrl;
  type gs_rc_ctrl_t (line 75) | typedef struct gs_rc_ctrl gs_rc_ctrl_t;
  type keys_pack_to_racing_glass_t (line 77) | typedef struct keys_pack_to_racing_glass_t keys_pack_to_racing_glass_t;
  type duss_osal_timer_attrib_t (line 79) | typedef struct duss_osal_timer_attrib_t duss_osal_timer_attrib_t;
  type pack_for_factory_test_t (line 81) | typedef struct pack_for_factory_test_t pack_for_factory_test_t;
  type gs_buzzer_info (line 83) | typedef struct gs_buzzer_info gs_buzzer_info;
  type gs_buzzer_info_t (line 85) | typedef struct gs_buzzer_info gs_buzzer_info_t;
  type gs_fan_info (line 87) | typedef struct gs_fan_info gs_fan_info;
  type gs_fan_info_t (line 89) | typedef struct gs_fan_info gs_fan_info_t;
  type __gs_common_cmd_ctrl (line 91) | typedef struct __gs_common_cmd_ctrl __gs_common_cmd_ctrl;
  type gs_common_cmd_ctrl_t (line 93) | typedef struct __gs_common_cmd_ctrl gs_common_cmd_ctrl_t;
  type gs_camera_cmd_ctrl_t (line 95) | typedef struct gs_camera_cmd_ctrl_t gs_camera_cmd_ctrl_t;
  type _DUSS_MSG_CAMERA_STATUS_PUSH_t (line 97) | typedef struct _DUSS_MSG_CAMERA_STATUS_PUSH_t _DUSS_MSG_CAMERA_STATUS_PU...
  type DUSS_MSG_CAMERA_STATUS_PUSH_t (line 99) | typedef struct _DUSS_MSG_CAMERA_STATUS_PUSH_t DUSS_MSG_CAMERA_STATUS_PUS...
  type gs_video_channel_manager (line 101) | typedef struct gs_video_channel_manager gs_video_channel_manager;
  type gs_video_channel_manager_t (line 103) | typedef struct gs_video_channel_manager gs_video_channel_manager_t;
  type gs_wl_ctrl (line 105) | typedef struct gs_wl_ctrl gs_wl_ctrl;
  type gs_wl_ctrl_t (line 107) | typedef struct gs_wl_ctrl gs_wl_ctrl_t;
  type gs_av_in_ctrl (line 109) | typedef struct gs_av_in_ctrl gs_av_in_ctrl;
  type gs_av_in_ctrl_t (line 111) | typedef struct gs_av_in_ctrl gs_av_in_ctrl_t;
  type vdec_local_player (line 113) | typedef struct vdec_local_player vdec_local_player;
  type vdec_local_player_t (line 115) | typedef struct vdec_local_player vdec_local_player_t;
  type metadata_retriever (line 117) | typedef struct metadata_retriever metadata_retriever;
  type metadata_retriever_t (line 119) | typedef struct metadata_retriever metadata_retriever_t;
  type gs_lv_src (line 121) | typedef struct gs_lv_src gs_lv_src;
  type gs_lv_src_t (line 123) | typedef struct gs_lv_src gs_lv_src_t;
  type gs_lv_rec_ctrl (line 125) | typedef struct gs_lv_rec_ctrl gs_lv_rec_ctrl;
  type gs_lv_rec_ctrl_t (line 127) | typedef struct gs_lv_rec_ctrl gs_lv_rec_ctrl_t;
  type gs_usb_gadget_vt (line 129) | typedef struct gs_usb_gadget_vt gs_usb_gadget_vt;
  type gs_usb_gadget_vt_t (line 131) | typedef struct gs_usb_gadget_vt gs_usb_gadget_vt_t;
  type gs_lv_transcode (line 133) | typedef struct gs_lv_transcode gs_lv_transcode;
  type gs_lv_transcode_t (line 135) | typedef struct gs_lv_transcode gs_lv_transcode_t;
  type gs_aout (line 137) | typedef struct gs_aout gs_aout;
  type gs_aout_t (line 139) | typedef struct gs_aout gs_aout_t;
  type gs_audio_wl (line 141) | typedef struct gs_audio_wl gs_audio_wl;
  type gs_audio_wl_t (line 143) | typedef struct gs_audio_wl gs_audio_wl_t;
  type gs_media_cmd_chnl (line 145) | typedef struct gs_media_cmd_chnl gs_media_cmd_chnl;
  type gs_media_cmd_chnl_t (line 147) | typedef struct gs_media_cmd_chnl gs_media_cmd_chnl_t;
  type gs_bl (line 149) | typedef struct gs_bl gs_bl;
  type gs_bl_t (line 151) | typedef struct gs_bl gs_bl_t;
  type timeval (line 153) | typedef struct timeval timeval;
  type uint (line 155) | typedef uint __uint32_t;
  type __uint32_t (line 157) | typedef __uint32_t uint32_t;
  type __gs_gui (line 159) | typedef struct __gs_gui __gs_gui;
  type __gs_gui_config (line 161) | typedef struct __gs_gui_config __gs_gui_config;
  type debug_osd_info (line 163) | typedef struct debug_osd_info debug_osd_info;
  type debug_codec_osd_info_t (line 165) | typedef struct debug_osd_info debug_codec_osd_info_t;
  type debug_cam_osd_info (line 167) | typedef struct debug_cam_osd_info debug_cam_osd_info;
  type debug_cam_osd_info_t (line 169) | typedef struct debug_cam_osd_info debug_cam_osd_info_t;
  type debug_temp_osd_info (line 171) | typedef struct debug_temp_osd_info debug_temp_osd_info;
  type debug_temp_osd_info_t (line 173) | typedef struct debug_temp_osd_info debug_temp_osd_info_t;
  type debug_cp_osd_info (line 175) | typedef struct debug_cp_osd_info debug_cp_osd_info;
  type debug_cp_osd_info_t (line 177) | typedef struct debug_cp_osd_info debug_cp_osd_info_t;
  type ulonglong (line 179) | typedef ulonglong __uint64_t;
  type __uint64_t (line 181) | typedef __uint64_t uint64_t;
  type record_mode (line 183) | typedef enum record_mode
  type record_mode_t (line 189) | typedef enum record_mode record_mode_t;
  type Record_sender (line 191) | typedef enum Record_sender
  type ushort (line 197) | typedef ushort __uint16_t;
  type __uint16_t (line 199) | typedef __uint16_t uint16_t;
  type gs_battery_voltage (line 201) | typedef struct gs_battery_voltage gs_battery_voltage;
  type gs_battery_voltage_t (line 203) | typedef struct gs_battery_voltage gs_battery_voltage_t;
  type gs_gui_config_t (line 205) | typedef struct __gs_gui_config gs_gui_config_t;
  type gs_gui_event_t (line 207) | typedef struct gs_gui_event_t gs_gui_event_t;
  type gs_gui_t (line 209) | typedef struct __gs_gui gs_gui_t;
  type gs_ext_fc (line 211) | typedef struct gs_ext_fc gs_ext_fc;
  type gs_ext_fc_t (line 213) | typedef struct gs_ext_fc gs_ext_fc_t;
  type gs_shram (line 215) | typedef struct gs_shram gs_shram;
  type gs_shram_t (line 217) | typedef struct gs_shram gs_shram_t;
  type __gs_queue (line 219) | typedef struct __gs_queue __gs_queue;
  type gs_queue_t (line 221) | typedef struct __gs_queue gs_queue_t;
  type gs_user_json_root (line 223) | typedef struct gs_user_json_root gs_user_json_root;
  type gs_user_json_root_t (line 225) | typedef struct gs_user_json_root gs_user_json_root_t;
  type duss_osal_mutex_handle_t (line 227) | typedef struct duss_osal_mutex_handle_t duss_osal_mutex_handle_t;
  type __gs_avin_test_ctrl (line 229) | typedef struct __gs_avin_test_ctrl __gs_avin_test_ctrl;
  type gs_avin_test_ctrl_t (line 231) | typedef struct __gs_avin_test_ctrl gs_avin_test_ctrl_t;
  type gs_watermarker_ctrl (line 233) | typedef struct gs_watermarker_ctrl gs_watermarker_ctrl;
  type gs_watermarker_ctrl_t (line 235) | typedef struct gs_watermarker_ctrl gs_watermarker_ctrl_t;
  type duss_mb_client (line 237) | typedef struct duss_mb_client duss_mb_client;
  type duss_result_t (line 239) | typedef int32_t duss_result_t;
  type duss_msg_attrib_t (line 241) | typedef uint16_t duss_msg_attrib_t;
  type duss_msg_id_t (line 243) | typedef uint32_t duss_msg_id_t;
  type duss_mb_route_item_t (line 245) | typedef struct duss_mb_route_item_t duss_mb_route_item_t;
  type duss_mb_client (line 247) | struct duss_mb_client
  type duss_osal_msgq_handle_t (line 249) | typedef struct duss_osal_msgq_handle_t duss_osal_msgq_handle_t;
  type duss_osal_event_handle_t (line 251) | typedef struct duss_osal_event_handle_t duss_osal_event_handle_t;
  type duss_event_ack_identify (line 253) | typedef struct duss_event_ack_identify duss_event_ack_identify;
  type duss_event_ack_identify_t (line 255) | typedef struct duss_event_ack_identify duss_event_ack_identify_t;
  type duss_event_cmd_desc (line 257) | typedef struct duss_event_cmd_desc duss_event_cmd_desc;
  type duss_event (line 259) | typedef struct duss_event duss_event;
  type duss_event_t (line 261) | typedef struct duss_event duss_event_t;
  type duss_event_cmd_desc_t (line 263) | typedef struct duss_event_cmd_desc duss_event_cmd_desc_t;
  type duss_hal_obj_dev_t (line 265) | typedef struct duss_hal_obj_dev_t duss_hal_obj_dev_t;
  type product_shm_info (line 267) | typedef struct product_shm_info product_shm_info;
  type product_shm_info_t (line 269) | typedef struct product_shm_info product_shm_info_t;
  type uint (line 271) | typedef uint size_t;
  type modem_shmem_info_t (line 273) | typedef struct modem_shmem_info_t modem_shmem_info_t;
  type racing_debug_info_t (line 275) | typedef struct racing_debug_info_t racing_debug_info_t;
  type duss_osal_task_attrib_t (line 277) | typedef struct duss_osal_task_attrib_t duss_osal_task_attrib_t;
  type pthread_t (line 279) | typedef long pthread_t;
  type duss_storage_client (line 281) | typedef struct duss_storage_client duss_storage_client;
  type duss_storage_client_t (line 283) | typedef struct duss_storage_client duss_storage_client_t;
  type sd_file_type (line 285) | typedef enum sd_file_type
  type sd_file_type_t (line 293) | typedef enum sd_file_type sd_file_type_t;
  type gs_storage_listener (line 295) | typedef struct gs_storage_listener gs_storage_listener;
  type storage_event (line 297) | typedef enum storage_event
  type storage_event_t (line 303) | typedef enum storage_event storage_event_t;
  type gs_storage_listener_t (line 305) | typedef struct gs_storage_listener gs_storage_listener_t;
  type gs_sd_listener (line 307) | typedef struct gs_sd_listener gs_sd_listener;
  type sd_event (line 309) | typedef enum sd_event
  type sd_event_t (line 317) | typedef enum sd_event sd_event_t;
  type gs_sd_listener_t (line 319) | typedef struct gs_sd_listener gs_sd_listener_t;
  type gs_meta_listener (line 321) | typedef struct gs_meta_listener gs_meta_listener;
  type meta_event (line 323) | typedef enum meta_event
  type meta_event_t (line 331) | typedef enum meta_event meta_event_t;
  type gs_meta_listener_t (line 333) | typedef struct gs_meta_listener gs_meta_listener_t;
  type gs_playback_listener (line 335) | typedef struct gs_playback_listener gs_playback_listener;
  type playback_event (line 337) | typedef enum playback_event
  type playback_event_t (line 345) | typedef enum playback_event playback_event_t;
  type gs_playback_listener_t (line 347) | typedef struct gs_playback_listener gs_playback_listener_t;
  type sem_t (line 349) | typedef struct sem_t sem_t;
  type timespec (line 351) | typedef struct timespec timespec;
  type gs_modem_link_listener (line 353) | typedef struct gs_modem_link_listener gs_modem_link_listener;
  type gs_modem_link_listener_t (line 355) | typedef struct gs_modem_link_listener gs_modem_link_listener_t;
  type glass_signal_quality_t (line 357) | typedef struct glass_signal_quality_t glass_signal_quality_t;
  type _DUSS_MSG_RACING_CHANNEL_SCAN_REQ_t (line 359) | typedef struct _DUSS_MSG_RACING_CHANNEL_SCAN_REQ_t _DUSS_MSG_RACING_CHAN...
  type DUSS_MSG_RACING_CHANNEL_SCAN_REQ_t (line 361) | typedef struct _DUSS_MSG_RACING_CHANNEL_SCAN_REQ_t DUSS_MSG_RACING_CHANN...
  type _DUSS_MSG_RACING_CHANNEL_SCAN_INFO_t (line 363) | typedef struct _DUSS_MSG_RACING_CHANNEL_SCAN_INFO_t _DUSS_MSG_RACING_CHA...
  type DUSS_MSG_RACING_CHANNEL_SCAN_INFO_t (line 365) | typedef struct _DUSS_MSG_RACING_CHANNEL_SCAN_INFO_t DUSS_MSG_RACING_CHAN...
  type _DUSS_MSG_RACING_CHANNEL_ROB_INFO_t (line 367) | typedef struct _DUSS_MSG_RACING_CHANNEL_ROB_INFO_t _DUSS_MSG_RACING_CHAN...
  type DUSS_MSG_RACING_CHANNEL_ROB_INFO_t (line 369) | typedef struct _DUSS_MSG_RACING_CHANNEL_ROB_INFO_t DUSS_MSG_RACING_CHANN...
  type _DUSS_MSG_RACING_PHY_CHECK_REQ_t (line 371) | typedef struct _DUSS_MSG_RACING_PHY_CHECK_REQ_t _DUSS_MSG_RACING_PHY_CHE...
  type DUSS_MSG_RACING_PHY_CHECK_REQ_t (line 373) | typedef struct _DUSS_MSG_RACING_PHY_CHECK_REQ_t DUSS_MSG_RACING_PHY_CHEC...
  type _DUSS_MSG_RACING_PHY_CHECK_INFO_t (line 375) | typedef struct _DUSS_MSG_RACING_PHY_CHECK_INFO_t _DUSS_MSG_RACING_PHY_CH...
  type DUSS_MSG_RACING_PHY_CHECK_INFO_t (line 377) | typedef struct _DUSS_MSG_RACING_PHY_CHECK_INFO_t DUSS_MSG_RACING_PHY_CHE...
  type gs_modem_scan_type_t (line 379) | typedef enum gs_modem_scan_type_t
  type rc_set_reverse_t (line 390) | typedef union rc_set_reverse_t rc_set_reverse_t;
  type rc_set_all_st_t (line 392) | typedef struct rc_set_all_st_t rc_set_all_st_t;
  type rc_set_all_ep_t (line 394) | typedef struct rc_set_all_ep_t rc_set_all_ep_t;
  type rc_set_all_st_and_rev_t (line 396) | typedef struct rc_set_all_st_and_rev_t rc_set_all_st_and_rev_t;
  type dummy_ui_ctx_t (line 398) | typedef struct dummy_ui_ctx_t dummy_ui_ctx_t;
  type duss_osal_priority_t (line 402) | typedef enum duss_osal_priority_t
  type factory_check (line 422) | typedef struct factory_check factory_check;
  type anon_struct_conflictc3fb_for_sw (line 424) | typedef struct anon_struct_conflictc3fb_for_sw anon_struct_conflictc3fb_...
  type anon_struct_conflictc431_for_key (line 426) | typedef struct anon_struct_conflictc431_for_key anon_struct_conflictc431...
  type duss_osal_mutex_attrib_t (line 428) | typedef struct duss_osal_mutex_attrib_t duss_osal_mutex_attrib_t;
  type gs_fan_level_t (line 430) | typedef enum gs_fan_level_t
  type _DUSS_MSG_SYSTEM_STATE_t (line 441) | typedef struct _DUSS_MSG_SYSTEM_STATE_t _DUSS_MSG_SYSTEM_STATE_t;
  type DUSS_MSG_SYSTEM_STATE_t (line 443) | typedef struct _DUSS_MSG_SYSTEM_STATE_t DUSS_MSG_SYSTEM_STATE_t;
  type _DUSS_MSG_F_INDEX_MODE_t (line 445) | typedef struct _DUSS_MSG_F_INDEX_MODE_t _DUSS_MSG_F_INDEX_MODE_t;
  type DUSS_MSG_F_INDEX_MODE_t (line 447) | typedef struct _DUSS_MSG_F_INDEX_MODE_t DUSS_MSG_F_INDEX_MODE_t;
  type _DUSS_MSG_QUICKVIEW_t (line 449) | typedef struct _DUSS_MSG_QUICKVIEW_t _DUSS_MSG_QUICKVIEW_t;
  type DUSS_MSG_QUICKVIEW_t (line 451) | typedef struct _DUSS_MSG_QUICKVIEW_t DUSS_MSG_QUICKVIEW_t;
  type _DUSS_MSG_PHOTO_OSD_PARA_ (line 453) | typedef struct _DUSS_MSG_PHOTO_OSD_PARA_ _DUSS_MSG_PHOTO_OSD_PARA_;
  type DUSS_MSG_PHOTO_OSD_PARA_t (line 455) | typedef struct _DUSS_MSG_PHOTO_OSD_PARA_ DUSS_MSG_PHOTO_OSD_PARA_t;
  type _DUSS_MSG_PREVIEW_OSD_PARA_t (line 457) | typedef struct _DUSS_MSG_PREVIEW_OSD_PARA_t _DUSS_MSG_PREVIEW_OSD_PARA_t;
  type DUSS_MSG_PREVIEW_OSD_PARA_t (line 459) | typedef struct _DUSS_MSG_PREVIEW_OSD_PARA_t DUSS_MSG_PREVIEW_OSD_PARA_t;
  type _DUSS_MSG_HISTOGRAM_t (line 461) | typedef struct _DUSS_MSG_HISTOGRAM_t _DUSS_MSG_HISTOGRAM_t;
  type DUSS_MSG_HISTOGRAM_t (line 463) | typedef struct _DUSS_MSG_HISTOGRAM_t DUSS_MSG_HISTOGRAM_t;
  type _DUSS_MSG_CAMERA_AUDIO_STATUS_t (line 465) | typedef struct _DUSS_MSG_CAMERA_AUDIO_STATUS_t _DUSS_MSG_CAMERA_AUDIO_ST...
  type DUSS_MSG_CAMERA_AUDIO_STATUS_t (line 467) | typedef struct _DUSS_MSG_CAMERA_AUDIO_STATUS_t DUSS_MSG_CAMERA_AUDIO_STA...
  type _DUSS_MSG_HYPERLAPSE_LIVEVIEW_MARGIN_t (line 469) | typedef struct _DUSS_MSG_HYPERLAPSE_LIVEVIEW_MARGIN_t _DUSS_MSG_HYPERLAP...
  type DUSS_MSG_HYPERLAPSE_LIVEVIEW_MARGIN_t (line 471) | typedef struct _DUSS_MSG_HYPERLAPSE_LIVEVIEW_MARGIN_t DUSS_MSG_HYPERLAPS...
  type gs_wl_channel (line 473) | typedef struct gs_wl_channel gs_wl_channel;
  type gs_wl_channel_t (line 475) | typedef struct gs_wl_channel gs_wl_channel_t;
  type gs_local_playback_channel (line 477) | typedef struct gs_local_playback_channel gs_local_playback_channel;
  type gs_local_playback_channel_t (line 479) | typedef struct gs_local_playback_channel gs_local_playback_channel_t;
  type gs_av_in_channel (line 481) | typedef struct gs_av_in_channel gs_av_in_channel;
  type gs_av_in_channel_t (line 483) | typedef struct gs_av_in_channel gs_av_in_channel_t;
  type gs_rc_setting_channel (line 485) | typedef struct gs_rc_setting_channel gs_rc_setting_channel;
  type gs_rc_setting_channel_t (line 487) | typedef struct gs_rc_setting_channel gs_rc_setting_channel_t;
  type gs_csi_channel (line 489) | typedef struct gs_csi_channel gs_csi_channel;
  type gs_csi_channel_t (line 491) | typedef struct gs_csi_channel gs_csi_channel_t;
  type gs_non_video_channel (line 493) | typedef struct gs_non_video_channel gs_non_video_channel;
  type gs_non_video_channel_t (line 495) | typedef struct gs_non_video_channel gs_non_video_channel_t;
  type gs_video_channel (line 497) | typedef struct gs_video_channel gs_video_channel;
  type gs_video_channel_message (line 499) | typedef struct gs_video_channel_message gs_video_channel_message;
  type gs_video_channel_message_t (line 501) | typedef struct gs_video_channel_message gs_video_channel_message_t;
  type gs_video_channel_t (line 503) | typedef struct gs_video_channel gs_video_channel_t;
  type gs_video_channel_id (line 505) | typedef struct gs_video_channel_id gs_video_channel_id;
  type gs_video_channel_id_t (line 507) | typedef struct gs_video_channel_id gs_video_channel_id_t;
  type gs_avin_us (line 513) | typedef struct gs_avin_us gs_avin_us;
  type gs_avin_us_t (line 515) | typedef struct gs_avin_us gs_avin_us_t;
  type AVFormatContext (line 517) | typedef struct AVFormatContext AVFormatContext;
  type audio_dec (line 519) | typedef struct audio_dec audio_dec;
  type decoder_event (line 521) | typedef enum decoder_event
  type dec_event_t (line 528) | typedef enum decoder_event dec_event_t;
  type audio_dec_t (line 530) | typedef struct audio_dec audio_dec_t;
  type cp_vdec (line 532) | typedef struct cp_vdec cp_vdec;
  type cp_vdec_t (line 534) | typedef struct cp_vdec cp_vdec_t;
  type vdec_video_file_info (line 536) | typedef struct vdec_video_file_info vdec_video_file_info;
  type vdec_video_file_info_t (line 538) | typedef struct vdec_video_file_info vdec_video_file_info_t;
  type longlong (line 540) | typedef longlong __int64_t;
  type __int64_t (line 542) | typedef __int64_t int64_t;
  type sqlite3 (line 544) | typedef struct sqlite3 sqlite3;
  type gs_lv_csm (line 546) | typedef struct gs_lv_csm gs_lv_csm;
  type gs_lv_pkt (line 548) | typedef struct gs_lv_pkt gs_lv_pkt;
  type gs_lv_pkt_t (line 550) | typedef struct gs_lv_pkt gs_lv_pkt_t;
  type gs_lv_csm_t (line 552) | typedef struct gs_lv_csm gs_lv_csm_t;
  type duss_list_head (line 554) | typedef struct duss_list_head duss_list_head;
  type gs_usb_listener (line 556) | typedef struct gs_usb_listener gs_usb_listener;
  type usb_event (line 558) | typedef enum usb_event
  type usb_event_t (line 564) | typedef enum usb_event usb_event_t;
  type gs_usb_listener_t (line 566) | typedef struct gs_usb_listener gs_usb_listener_t;
  type ion_info (line 568) | typedef struct ion_info ion_info;
  type ion_info_t (line 570) | typedef struct ion_info ion_info_t;
  type record_state (line 572) | typedef enum record_state
  type record_state_t (line 583) | typedef enum record_state record_state_t;
  type AVCodecContext (line 585) | typedef struct AVCodecContext AVCodecContext;
  type AVFrame (line 587) | typedef struct AVFrame AVFrame;
  type AVPixelFormat (line 589) | typedef enum AVPixelFormat
  type pl_muxer_t (line 879) | typedef struct pl_muxer_t pl_muxer_t;
  type pl_muxer_t (line 881) | struct pl_muxer_t
  type __sFILE (line 883) | typedef struct __sFILE __sFILE;
  type __kernel_long_t (line 885) | typedef long __kernel_long_t;
  type __kernel_long_t (line 887) | typedef __kernel_long_t __kernel_off_t;
  type __kernel_off_t (line 889) | typedef __kernel_off_t off_t;
  type off_t (line 891) | typedef off_t fpos_t;
  type FILE (line 893) | typedef struct __sFILE FILE;
  type pcm_config (line 895) | typedef struct pcm_config pcm_config;
  type pcm (line 897) | typedef struct pcm pcm;
  type __kernel_long_t (line 899) | typedef __kernel_long_t __kernel_time_t;
  type __kernel_long_t (line 901) | typedef __kernel_long_t __kernel_suseconds_t;
  type ext_fc_ops (line 903) | typedef struct ext_fc_ops ext_fc_ops;
  type batteryState_e (line 905) | typedef enum batteryState_e
  type DUSS_MSG_FC_RACING_DRONE_OSD_PUSH (line 914) | typedef struct DUSS_MSG_FC_RACING_DRONE_OSD_PUSH DUSS_MSG_FC_RACING_DRON...
  type DUSS_MSG_FC_RACING_DRONE_OSD_PUSH_t (line 916) | typedef struct DUSS_MSG_FC_RACING_DRONE_OSD_PUSH DUSS_MSG_FC_RACING_DRON...
  type DUSS_MSG_EXT_FC_RTC (line 918) | typedef struct DUSS_MSG_EXT_FC_RTC DUSS_MSG_EXT_FC_RTC;
  type DUSS_MSG_EXT_FC_RTC_t (line 920) | typedef struct DUSS_MSG_EXT_FC_RTC DUSS_MSG_EXT_FC_RTC_t;
  type ext_fc_ops_t (line 922) | typedef struct ext_fc_ops ext_fc_ops_t;
  type vr_device_ops (line 924) | typedef struct vr_device_ops vr_device_ops;
  type __int16_t (line 926) | typedef short __int16_t;
  type __int16_t (line 928) | typedef __int16_t int16_t;
  type vr_device_ops_t (line 930) | typedef struct vr_device_ops vr_device_ops_t;
  type local_playback_ops (line 932) | typedef struct local_playback_ops local_playback_ops;
  type local_playback_ops_t (line 934) | typedef struct local_playback_ops local_playback_ops_t;
  type uav_camera_ops (line 936) | typedef struct uav_camera_ops uav_camera_ops;
  type __gs_camera_cmd (line 938) | typedef struct __gs_camera_cmd __gs_camera_cmd;
  type gs_camera_cmd_t (line 940) | typedef struct __gs_camera_cmd gs_camera_cmd_t;
  type uav_camera_ops_t (line 942) | typedef struct uav_camera_ops uav_camera_ops_t;
  type uav_gimbal_ops (line 944) | typedef struct uav_gimbal_ops uav_gimbal_ops;
  type uav_gimbal_ops_t (line 946) | typedef struct uav_gimbal_ops uav_gimbal_ops_t;
  type modem_ops (line 948) | typedef struct modem_ops modem_ops;
  type gs_link_stat_t (line 950) | typedef enum gs_link_stat_t
  type modem_ops_t (line 958) | typedef struct modem_ops modem_ops_t;
  type rc_ops (line 960) | typedef struct rc_ops rc_ops;
  type rc_set_function_pack_t (line 962) | typedef struct rc_set_function_pack_t rc_set_function_pack_t;
  type rc_set_stick_mode_pack_t (line 964) | typedef struct rc_set_stick_mode_pack_t rc_set_stick_mode_pack_t;
  type rc_set_warning_mode_pack_t (line 966) | typedef struct rc_set_warning_mode_pack_t rc_set_warning_mode_pack_t;
  type rc_monitor_pack_t (line 968) | typedef struct rc_monitor_pack_t rc_monitor_pack_t;
  type rc_ops_t (line 970) | typedef struct rc_ops rc_ops_t;
  type vcm_ops (line 972) | typedef struct vcm_ops vcm_ops;
  type gs_main_channel_id (line 974) | typedef enum gs_main_channel_id
  type gs_main_channel_id_t (line 987) | typedef enum gs_main_channel_id gs_main_channel_id_t;
  type vcm_ops_t (line 989) | typedef struct vcm_ops vcm_ops_t;
  type common_cmd_ops (line 991) | typedef struct common_cmd_ops common_cmd_ops;
  type __gs_common_cmd (line 993) | typedef struct __gs_common_cmd __gs_common_cmd;
  type gs_common_cmd_t (line 995) | typedef struct __gs_common_cmd gs_common_cmd_t;
  type common_cmd_ops_t (line 997) | typedef struct common_cmd_ops common_cmd_ops_t;
  type debug_osd_item (line 999) | typedef struct debug_osd_item debug_osd_item;
  type debug_osd_item_t (line 1001) | typedef struct debug_osd_item debug_osd_item_t;
  type uint (line 1003) | typedef uint gs_gui_event_type_t;
  type uint (line 1005) | typedef uint gs_gui_event_symbol_t;
  type DUSS_MSG_EXT_FC_PID (line 1007) | typedef struct DUSS_MSG_EXT_FC_PID DUSS_MSG_EXT_FC_PID;
  type DUSS_MSG_EXT_FC_PID_t (line 1009) | typedef struct DUSS_MSG_EXT_FC_PID DUSS_MSG_EXT_FC_PID_t;
  type DUSS_MSG_EXT_FC_AUX (line 1011) | typedef struct DUSS_MSG_EXT_FC_AUX DUSS_MSG_EXT_FC_AUX;
  type DUSS_MSG_EXT_FC_AUX_t (line 1013) | typedef struct DUSS_MSG_EXT_FC_AUX DUSS_MSG_EXT_FC_AUX_t;
  type DUSS_MSG_EXT_FC_RATE (line 1015) | typedef struct DUSS_MSG_EXT_FC_RATE DUSS_MSG_EXT_FC_RATE;
  type DUSS_MSG_EXT_FC_RATE_t (line 1017) | typedef struct DUSS_MSG_EXT_FC_RATE DUSS_MSG_EXT_FC_RATE_t;
  type DUSS_MSG_EXT_FC_SERVO (line 1019) | typedef struct DUSS_MSG_EXT_FC_SERVO DUSS_MSG_EXT_FC_SERVO;
  type DUSS_MSG_EXT_FC_SERVO_t (line 1021) | typedef struct DUSS_MSG_EXT_FC_SERVO DUSS_MSG_EXT_FC_SERVO_t;
  type DUSS_MSG_EXT_FC_FILTER (line 1023) | typedef struct DUSS_MSG_EXT_FC_FILTER DUSS_MSG_EXT_FC_FILTER;
  type DUSS_MSG_EXT_FC_FILTER_t (line 1025) | typedef struct DUSS_MSG_EXT_FC_FILTER DUSS_MSG_EXT_FC_FILTER_t;
  type DUSS_MSG_EXT_FC_ADVANCED_PID (line 1027) | typedef struct DUSS_MSG_EXT_FC_ADVANCED_PID DUSS_MSG_EXT_FC_ADVANCED_PID;
  type DUSS_MSG_EXT_FC_ADVANCED_PID_t (line 1029) | typedef struct DUSS_MSG_EXT_FC_ADVANCED_PID DUSS_MSG_EXT_FC_ADVANCED_PID_t;
  type DUSS_MSG_EXT_FC_MSP_STATUS (line 1031) | typedef struct DUSS_MSG_EXT_FC_MSP_STATUS DUSS_MSG_EXT_FC_MSP_STATUS;
  type DUSS_MSG_EXT_FC_MSP_STATUS_t (line 1033) | typedef struct DUSS_MSG_EXT_FC_MSP_STATUS DUSS_MSG_EXT_FC_MSP_STATUS_t;
  type DUSS_MSG_EXT_FC_RC (line 1035) | typedef struct DUSS_MSG_EXT_FC_RC DUSS_MSG_EXT_FC_RC;
  type DUSS_MSG_EXT_FC_RC_t (line 1037) | typedef struct DUSS_MSG_EXT_FC_RC DUSS_MSG_EXT_FC_RC_t;
  type DUSS_MSG_EXT_FC_BATTERY_STATE (line 1039) | typedef struct DUSS_MSG_EXT_FC_BATTERY_STATE DUSS_MSG_EXT_FC_BATTERY_STATE;
  type DUSS_MSG_EXT_FC_BATTERY_STATE_t (line 1041) | typedef struct DUSS_MSG_EXT_FC_BATTERY_STATE DUSS_MSG_EXT_FC_BATTERY_STA...
  type DUSS_MSG_EXT_FC_OSD_CONFIG (line 1043) | typedef struct DUSS_MSG_EXT_FC_OSD_CONFIG DUSS_MSG_EXT_FC_OSD_CONFIG;
  type DUSS_MSG_EXT_FC_OSD_CONFIG_t (line 1045) | typedef struct DUSS_MSG_EXT_FC_OSD_CONFIG DUSS_MSG_EXT_FC_OSD_CONFIG_t;
  type DUSS_MSG_EXT_FC_ESC_DATA (line 1047) | typedef struct DUSS_MSG_EXT_FC_ESC_DATA DUSS_MSG_EXT_FC_ESC_DATA;
  type DUSS_MSG_EXT_FC_ESC_DATA_t (line 1049) | typedef struct DUSS_MSG_EXT_FC_ESC_DATA DUSS_MSG_EXT_FC_ESC_DATA_t;
  type DUSS_MSG_EXT_FC_VERSION (line 1051) | typedef struct DUSS_MSG_EXT_FC_VERSION DUSS_MSG_EXT_FC_VERSION;
  type DUSS_MSG_EXT_FC_VERSION_t (line 1053) | typedef struct DUSS_MSG_EXT_FC_VERSION DUSS_MSG_EXT_FC_VERSION_t;
  type GS_EXT_FC_OSD_STATUS (line 1055) | typedef enum GS_EXT_FC_OSD_STATUS
  type cJSON (line 1061) | typedef struct cJSON cJSON;
  type gs_watermarker_us (line 1063) | typedef struct gs_watermarker_us gs_watermarker_us;
  type gs_watermarker_us_t (line 1065) | typedef struct gs_watermarker_us gs_watermarker_us_t;
  type duss_mb_channel_t (line 1067) | typedef uint8_t duss_mb_channel_t;
  type duss_mb_pack_ver_t (line 1069) | typedef uint8_t duss_mb_pack_ver_t;
  type anon_union_conflict1232_for_channel (line 1071) | typedef union anon_union_conflict1232_for_channel anon_union_conflict123...
  type duss_mb_filter_t (line 1073) | typedef struct duss_mb_filter_t duss_mb_filter_t;
  type duss_mb_route_table_t (line 1075) | typedef struct duss_mb_route_table_t duss_mb_route_table_t;
  type fd_set (line 1077) | typedef struct fd_set fd_set;
  type duss_osal_msgq_attrib_t (line 1079) | typedef struct duss_osal_msgq_attrib_t duss_osal_msgq_attrib_t;
  type duss_osal_event_attrib_t (line 1081) | typedef struct duss_osal_event_attrib_t duss_osal_event_attrib_t;
  type duss_hal_state_t (line 1083) | typedef uint8_t duss_hal_state_t;
  type duss_hal_class_t (line 1085) | typedef uint8_t duss_hal_class_t;
  type duss_hal_storage_params (line 1089) | typedef struct duss_hal_storage_params duss_hal_storage_params;
  type duss_hal_storage_info (line 1091) | typedef struct duss_hal_storage_info duss_hal_storage_info;
  type _DUSS_MSG_RACING_CHANNEL_OCCUPIED_IPSD_t (line 1093) | typedef struct _DUSS_MSG_RACING_CHANNEL_OCCUPIED_IPSD_t _DUSS_MSG_RACING...
  type DUSS_MSG_RACING_CHANNEL_OCCUPIED_IPSD_t (line 1095) | typedef struct _DUSS_MSG_RACING_CHANNEL_OCCUPIED_IPSD_t DUSS_MSG_RACING_...
  type anon_struct_conflict47e0 (line 1097) | typedef struct anon_struct_conflict47e0 anon_struct_conflict47e0;
  type rc_set_subtrim_t (line 1099) | typedef struct rc_set_subtrim_t rc_set_subtrim_t;
  type rc_set_endpoint_t (line 1101) | typedef struct rc_set_endpoint_t rc_set_endpoint_t;
  type rc_set_subtrim_reverse_t (line 1103) | typedef struct rc_set_subtrim_reverse_t rc_set_subtrim_reverse_t;
  type _DUSS_MSG_CAM_STATE_t (line 1105) | typedef struct _DUSS_MSG_CAM_STATE_t _DUSS_MSG_CAM_STATE_t;
  type DUSS_MSG_CAM_STATE_t (line 1107) | typedef struct _DUSS_MSG_CAM_STATE_t DUSS_MSG_CAM_STATE_t;
  type anon_union_conflict23e3_for_u (line 1109) | typedef union anon_union_conflict23e3_for_u anon_union_conflict23e3_for_u;
  type anon_union_conflict2544_for_u (line 1111) | typedef union anon_union_conflict2544_for_u anon_union_conflict2544_for_u;
  type gs_video_channel_message_id_t (line 1113) | typedef enum gs_video_channel_message_id_t
  type anon_union_conflict3b31_for_field_1 (line 1133) | typedef union anon_union_conflict3b31_for_field_1 anon_union_conflict3b3...
  type gs_sub_channel_id (line 1135) | typedef enum gs_sub_channel_id
  type gs_sub_channel_id_t (line 1148) | typedef enum gs_sub_channel_id gs_sub_channel_id_t;
  type AVClass (line 1150) | typedef struct AVClass AVClass;
  type AVClassCategory (line 1152) | typedef enum AVClassCategory
  type AVOptionRanges (line 1174) | typedef struct AVOptionRanges AVOptionRanges;
  type AVInputFormat (line 1176) | typedef struct AVInputFormat AVInputFormat;
  type AVProbeData (line 1178) | typedef struct AVProbeData AVProbeData;
  type AVPacket (line 1180) | typedef struct AVPacket AVPacket;
  type AVDeviceInfoList (line 1182) | typedef struct AVDeviceInfoList AVDeviceInfoList;
  type AVDeviceCapabilitiesQuery (line 1184) | typedef struct AVDeviceCapabilitiesQuery AVDeviceCapabilitiesQuery;
  type AVOutputFormat (line 1186) | typedef struct AVOutputFormat AVOutputFormat;
  type AVCodecID (line 1188) | typedef enum AVCodecID
  type AVIOContext (line 1943) | typedef struct AVIOContext AVIOContext;
  type AVStream (line 1945) | typedef struct AVStream AVStream;
  type AVProgram (line 1947) | typedef struct AVProgram AVProgram;
  type AVChapter (line 1949) | typedef struct AVChapter AVChapter;
  type AVDictionary (line 1951) | typedef struct AVDictionary AVDictionary;
  type AVIOInterruptCB (line 1953) | typedef struct AVIOInterruptCB AVIOInterruptCB;
  type AVDurationEstimationMethod (line 1955) | typedef enum AVDurationEstimationMethod
  type AVPacketList (line 1962) | typedef struct AVPacketList AVPacketList;
  type AVRational (line 1964) | typedef struct AVRational AVRational;
  type AVFormatInternal (line 1966) | typedef struct AVFormatInternal AVFormatInternal;
  type AVCodec (line 1968) | typedef struct AVCodec AVCodec;
  type AVSubtitle (line 1970) | typedef struct AVSubtitle AVSubtitle;
  type AUDIO_PB_STATE (line 1972) | typedef enum AUDIO_PB_STATE
  type audio_pb_state_t (line 1983) | typedef enum AUDIO_PB_STATE audio_pb_state_t;
  type pl_decoder_t (line 1985) | typedef struct pl_decoder_t pl_decoder_t;
  type pl_decoder_t (line 1987) | struct pl_decoder_t
  type pl_decoder_itf_t (line 1989) | typedef struct pl_decoder_itf_t pl_decoder_itf_t;
  type audio_resampler_t (line 1995) | typedef struct audio_resampler_t audio_resampler_t;
  type audio_resampler_t (line 1997) | struct audio_resampler_t
  type VDEC_STATE (line 1999) | typedef enum VDEC_STATE
  type vdec_state_t (line 2010) | typedef enum VDEC_STATE vdec_state_t;
  type DUSS_FILE_FORMAT (line 2012) | typedef enum DUSS_FILE_FORMAT
  type bridge_io_pkt (line 2034) | typedef struct bridge_io_pkt bridge_io_pkt;
  type bridge_io_pkt_t (line 2036) | typedef struct bridge_io_pkt bridge_io_pkt_t;
  type duss_hal_mem_config_t (line 2040) | typedef struct duss_hal_mem_config_t duss_hal_mem_config_t;
  type duss_hal_mem_param_t (line 2042) | typedef struct duss_hal_mem_param_t duss_hal_mem_param_t;
  type duss_hal_mem_buf (line 2044) | typedef struct duss_hal_mem_buf duss_hal_mem_buf;
  type duss_hal_mem_buf (line 2046) | struct duss_hal_mem_buf
  type AVMediaType (line 2048) | typedef enum AVMediaType
  type AVCodecInternal (line 2059) | typedef struct AVCodecInternal AVCodecInternal;
  type AVPictureType (line 2061) | typedef enum AVPictureType
  type AVPanScan (line 2073) | typedef struct AVPanScan AVPanScan;
  type AVBufferRef (line 2075) | typedef struct AVBufferRef AVBufferRef;
  type AVFrameSideData (line 2077) | typedef struct AVFrameSideData AVFrameSideData;
  type AVColorRange (line 2079) | typedef enum AVColorRange
  type AVColorPrimaries (line 2087) | typedef enum AVColorPrimaries
  type AVColorTransferCharacteristic (line 2102) | typedef enum AVColorTransferCharacteristic
  type AVColorSpace (line 2123) | typedef enum AVColorSpace
  type AVChromaLocation (line 2139) | typedef enum AVChromaLocation
  type AVFieldOrder (line 2151) | typedef enum AVFieldOrder
  type AVSampleFormat (line 2161) | typedef enum AVSampleFormat
  type AVAudioServiceType (line 2177) | typedef enum AVAudioServiceType
  type RcOverride (line 2191) | typedef struct RcOverride RcOverride;
  type AVHWAccel (line 2193) | typedef struct AVHWAccel AVHWAccel;
  type MpegEncContext (line 2195) | typedef struct MpegEncContext MpegEncContext;
  type AVDiscard (line 2197) | typedef enum AVDiscard
  type AVCodecDescriptor (line 2208) | typedef struct AVCodecDescriptor AVCodecDescriptor;
  type pl_muxer_itf_t (line 2210) | typedef struct pl_muxer_itf_t pl_muxer_itf_t;
  type pl_muxer_config_index_t (line 2212) | typedef enum pl_muxer_config_index_t
  type __sbuf (line 2219) | typedef struct __sbuf __sbuf;
  type pcm_format (line 2221) | typedef enum pcm_format
  type pcm_tstamp (line 2232) | typedef enum pcm_tstamp
  type snd_pcm_mmap_status (line 2240) | typedef struct snd_pcm_mmap_status snd_pcm_mmap_status;
  type snd_pcm_mmap_control (line 2242) | typedef struct snd_pcm_mmap_control snd_pcm_mmap_control;
  type snd_pcm_sync_ptr (line 2244) | typedef struct snd_pcm_sync_ptr snd_pcm_sync_ptr;
  type anon_union_conflict2c9b_for_field_3 (line 2246) | typedef union anon_union_conflict2c9b_for_field_3 anon_union_conflict2c9...
  type stick_mode_self_define_t (line 2248) | typedef struct stick_mode_self_define_t stick_mode_self_define_t;
  type loc_channel_addr (line 2250) | typedef struct loc_channel_addr loc_channel_addr;
  type ip_channel_addr (line 2252) | typedef struct ip_channel_addr ip_channel_addr;
  type wl_channel_addr (line 2254) | typedef struct wl_channel_addr wl_channel_addr;
  type uart_channel_addr (line 2256) | typedef struct uart_channel_addr uart_channel_addr;
  type can_channel_addr (line 2258) | typedef struct can_channel_addr can_channel_addr;
  type i2c_channel_addr (line 2260) | typedef struct i2c_channel_addr i2c_channel_addr;
  type spi_channel_addr (line 2262) | typedef struct spi_channel_addr spi_channel_addr;
  type hpi_channel_addr (line 2264) | typedef struct hpi_channel_addr hpi_channel_addr;
  type usb_channel_addr (line 2266) | typedef struct usb_channel_addr usb_channel_addr;
  type usbacc_channel_addr (line 2268) | typedef struct usbacc_channel_addr usbacc_channel_addr;
  type icc_channel_addr (line 2270) | typedef struct icc_channel_addr icc_channel_addr;
  type netlink_channel_addr (line 2272) | typedef struct netlink_channel_addr netlink_channel_addr;
  type bulk_channel_addr (line 2274) | typedef struct bulk_channel_addr bulk_channel_addr;
  type duss_storage_client_type_t (line 2276) | typedef enum duss_storage_client_type_t
  type anon_struct_conflict2349 (line 2284) | typedef struct anon_struct_conflict2349 anon_struct_conflict2349;
  type anon_struct_conflict242a (line 2286) | typedef struct anon_struct_conflict242a anon_struct_conflict242a;
  type gs_local_video_info (line 2288) | typedef struct gs_local_video_info gs_local_video_info;
  type gs_local_video_info_t (line 2290) | typedef struct gs_local_video_info gs_local_video_info_t;
  type gs_local_panorama_info (line 2292) | typedef struct gs_local_panorama_info gs_local_panorama_info;
  type gs_local_panorama_info_t (line 2294) | typedef struct gs_local_panorama_info gs_local_panorama_info_t;
  type AVOption (line 2296) | typedef struct AVOption AVOption;
  type AVOptionRange (line 2298) | typedef struct AVOptionRange AVOptionRange;
  type AVCodecTag (line 2300) | typedef struct AVCodecTag AVCodecTag;
  type AVPacketSideData (line 2302) | typedef struct AVPacketSideData AVPacketSideData;
  type AVFrac (line 2304) | typedef struct AVFrac AVFrac;
  type anon_struct_conflict69b3c_for_info (line 2306) | typedef struct anon_struct_conflict69b3c_for_info anon_struct_conflict69...
  type AVStreamParseType (line 2308) | typedef enum AVStreamParseType
  type AVCodecParserContext (line 2318) | typedef struct AVCodecParserContext AVCodecParserContext;
  type AVIndexEntry (line 2320) | typedef struct AVIndexEntry AVIndexEntry;
  type AVProfile (line 2322) | typedef struct AVProfile AVProfile;
  type AVCodecDefault (line 2324) | typedef struct AVCodecDefault AVCodecDefault;
  type AVSubtitleRect (line 2326) | typedef struct AVSubtitleRect AVSubtitleRect;
  type SwrContext (line 2328) | typedef struct SwrContext SwrContext;
  type AVBuffer (line 2330) | typedef struct AVBuffer AVBuffer;
  type AVFrameSideDataType (line 2332) | typedef enum AVFrameSideDataType
  type _DUSS_MSG_APERTURE_t (line 2346) | typedef struct _DUSS_MSG_APERTURE_t _DUSS_MSG_APERTURE_t;
  type DUSS_MSG_APERTURE_t (line 2348) | typedef struct _DUSS_MSG_APERTURE_t DUSS_MSG_APERTURE_t;
  type _DUSS_MSG_SHUTTER_SPEED_t (line 2350) | typedef struct _DUSS_MSG_SHUTTER_SPEED_t _DUSS_MSG_SHUTTER_SPEED_t;
  type DUSS_MSG_SHUTTER_SPEED_t (line 2352) | typedef struct _DUSS_MSG_SHUTTER_SPEED_t DUSS_MSG_SHUTTER_SPEED_t;
  type _DUSS_MSG_ISO_t (line 2354) | typedef struct _DUSS_MSG_ISO_t _DUSS_MSG_ISO_t;
  type DUSS_MSG_ISO_t (line 2356) | typedef struct _DUSS_MSG_ISO_t DUSS_MSG_ISO_t;
  type _DUSS_MSG_EXPO_MODE_t (line 2358) | typedef struct _DUSS_MSG_EXPO_MODE_t _DUSS_MSG_EXPO_MODE_t;
  type DUSS_MSG_EXPO_MODE_t (line 2360) | typedef struct _DUSS_MSG_EXPO_MODE_t DUSS_MSG_EXPO_MODE_t;
  type _DUSS_MSG_EV_BIAS_t (line 2362) | typedef struct _DUSS_MSG_EV_BIAS_t _DUSS_MSG_EV_BIAS_t;
  type DUSS_MSG_EV_BIAS_t (line 2364) | typedef struct _DUSS_MSG_EV_BIAS_t DUSS_MSG_EV_BIAS_t;
  type _DUSS_MSG_P_STORAGE_FMT_t (line 2366) | typedef struct _DUSS_MSG_P_STORAGE_FMT_t _DUSS_MSG_P_STORAGE_FMT_t;
  type DUSS_MSG_P_STORAGE_FMT_t (line 2368) | typedef struct _DUSS_MSG_P_STORAGE_FMT_t DUSS_MSG_P_STORAGE_FMT_t;
  type _DUSS_MSG_WB_t (line 2370) | typedef struct _DUSS_MSG_WB_t _DUSS_MSG_WB_t;
  type DUSS_MSG_WB_t (line 2372) | typedef struct _DUSS_MSG_WB_t DUSS_MSG_WB_t;
  type _DUSS_MSG_SCENE_MODE_t (line 2374) | typedef struct _DUSS_MSG_SCENE_MODE_t _DUSS_MSG_SCENE_MODE_t;
  type DUSS_MSG_SCENE_MODE_t (line 2376) | typedef struct _DUSS_MSG_SCENE_MODE_t DUSS_MSG_SCENE_MODE_t;
  type _DUSS_MSG_DIGITAL_EFFECT_t (line 2378) | typedef struct _DUSS_MSG_DIGITAL_EFFECT_t _DUSS_MSG_DIGITAL_EFFECT_t;
  type DUSS_MSG_DIGITAL_EFFECT_t (line 2380) | typedef struct _DUSS_MSG_DIGITAL_EFFECT_t DUSS_MSG_DIGITAL_EFFECT_t;
  type _DUSS_MSG_P_SIZE_t (line 2382) | typedef struct _DUSS_MSG_P_SIZE_t _DUSS_MSG_P_SIZE_t;
  type DUSS_MSG_P_SIZE_t (line 2384) | typedef struct _DUSS_MSG_P_SIZE_t DUSS_MSG_P_SIZE_t;
  type _DUSS_MSG_SET_FOCUS_REGION_t (line 2386) | typedef struct _DUSS_MSG_SET_FOCUS_REGION_t _DUSS_MSG_SET_FOCUS_REGION_t;
  type DUSS_MSG_SET_FOCUS_REGION_t (line 2388) | typedef struct _DUSS_MSG_SET_FOCUS_REGION_t DUSS_MSG_SET_FOCUS_REGION_t;
  type _DUSS_MSG_CAPTURE_MODE_t (line 2390) | typedef struct _DUSS_MSG_CAPTURE_MODE_t _DUSS_MSG_CAPTURE_MODE_t;
  type DUSS_MSG_CAPTURE_MODE_t (line 2392) | typedef struct _DUSS_MSG_CAPTURE_MODE_t DUSS_MSG_CAPTURE_MODE_t;
  type _DUSS_MSG_CONTICAP_PARAM_t (line 2394) | typedef struct _DUSS_MSG_CONTICAP_PARAM_t _DUSS_MSG_CONTICAP_PARAM_t;
  type DUSS_MSG_CONTICAP_PARAM_t (line 2396) | typedef struct _DUSS_MSG_CONTICAP_PARAM_t DUSS_MSG_CONTICAP_PARAM_t;
  type _DUSS_MSG_V_STORAGE_FMT_t (line 2398) | typedef struct _DUSS_MSG_V_STORAGE_FMT_t _DUSS_MSG_V_STORAGE_FMT_t;
  type DUSS_MSG_V_STORAGE_FMT_t (line 2400) | typedef struct _DUSS_MSG_V_STORAGE_FMT_t DUSS_MSG_V_STORAGE_FMT_t;
  type _DUSS_MSG_V_FORMAT_t (line 2402) | typedef struct _DUSS_MSG_V_FORMAT_t _DUSS_MSG_V_FORMAT_t;
  type DUSS_MSG_V_FORMAT_t (line 2404) | typedef struct _DUSS_MSG_V_FORMAT_t DUSS_MSG_V_FORMAT_t;
  type _DUSS_MSG_VIDEO_STANDARD_t (line 2406) | typedef struct _DUSS_MSG_VIDEO_STANDARD_t _DUSS_MSG_VIDEO_STANDARD_t;
  type DUSS_MSG_VIDEO_STANDARD_t (line 2408) | typedef struct _DUSS_MSG_VIDEO_STANDARD_t DUSS_MSG_VIDEO_STANDARD_t;
  type _DUSS_MSG_WORKMODE_t (line 2410) | typedef struct _DUSS_MSG_WORKMODE_t _DUSS_MSG_WORKMODE_t;
  type DUSS_MSG_WORKMODE_t (line 2412) | typedef struct _DUSS_MSG_WORKMODE_t DUSS_MSG_WORKMODE_t;
  type _DUSS_MSG_SINGLE_PLAY_CRTL_t (line 2414) | typedef struct _DUSS_MSG_SINGLE_PLAY_CRTL_t _DUSS_MSG_SINGLE_PLAY_CRTL_t;
  type DUSS_MSG_SINGLE_PLAY_CRTL_t (line 2416) | typedef struct _DUSS_MSG_SINGLE_PLAY_CRTL_t DUSS_MSG_SINGLE_PLAY_CRTL_t;
  type _DUSS_MSG_V_CRTL_t (line 2418) | typedef struct _DUSS_MSG_V_CRTL_t _DUSS_MSG_V_CRTL_t;
  type DUSS_MSG_V_CRTL_t (line 2420) | typedef struct _DUSS_MSG_V_CRTL_t DUSS_MSG_V_CRTL_t;
  type _DUSS_MSG_SD_INFO_t (line 2422) | typedef struct _DUSS_MSG_SD_INFO_t _DUSS_MSG_SD_INFO_t;
  type DUSS_MSG_SD_INFO_t (line 2424) | typedef struct _DUSS_MSG_SD_INFO_t DUSS_MSG_SD_INFO_t;
  type _DUSS_MSG_ZOOM_PARAM_t (line 2426) | typedef struct _DUSS_MSG_ZOOM_PARAM_t _DUSS_MSG_ZOOM_PARAM_t;
  type DUSS_MSG_ZOOM_PARAM_t (line 2428) | typedef struct _DUSS_MSG_ZOOM_PARAM_t DUSS_MSG_ZOOM_PARAM_t;
  type _DUSS_MSG_FLIP (line 2430) | typedef struct _DUSS_MSG_FLIP _DUSS_MSG_FLIP;
  type DUSS_MSG_FLIP_t (line 2432) | typedef struct _DUSS_MSG_FLIP DUSS_MSG_FLIP_t;
  type _DUSS_MSG_SHARPNESS_t (line 2434) | typedef struct _DUSS_MSG_SHARPNESS_t _DUSS_MSG_SHARPNESS_t;
  type DUSS_MSG_SHARPNESS_t (line 2436) | typedef struct _DUSS_MSG_SHARPNESS_t DUSS_MSG_SHARPNESS_t;
  type _DUSS_MSG_CONTRAST_t (line 2438) | typedef struct _DUSS_MSG_CONTRAST_t _DUSS_MSG_CONTRAST_t;
  type DUSS_MSG_CONTRAST_t (line 2440) | typedef struct _DUSS_MSG_CONTRAST_t DUSS_MSG_CONTRAST_t;
  type _DUSS_MSG_SATURATION_t (line 2442) | typedef struct _DUSS_MSG_SATURATION_t _DUSS_MSG_SATURATION_t;
  type DUSS_MSG_SATURATION_t (line 2444) | typedef struct _DUSS_MSG_SATURATION_t DUSS_MSG_SATURATION_t;
  type _DUSS_MSG_CAPTURE_t (line 2446) | typedef struct _DUSS_MSG_CAPTURE_t _DUSS_MSG_CAPTURE_t;
  type DUSS_MSG_CAPTURE_t (line 2448) | typedef struct _DUSS_MSG_CAPTURE_t DUSS_MSG_CAPTURE_t;
  type _DUSS_MSG_RECORD_t (line 2450) | typedef struct _DUSS_MSG_RECORD_t _DUSS_MSG_RECORD_t;
  type DUSS_MSG_RECORD_t (line 2452) | typedef struct _DUSS_MSG_RECORD_t DUSS_MSG_RECORD_t;
  type _UAV_RECORD_MODE_t (line 2454) | typedef struct _UAV_RECORD_MODE_t _UAV_RECORD_MODE_t;
  type UAV_RECORD_MODE_t (line 2456) | typedef struct _UAV_RECORD_MODE_t UAV_RECORD_MODE_t;
  type duss_wl_prot_type_t (line 2458) | typedef uint8_t duss_wl_prot_type_t;
  type duss_wl_prio_t (line 2460) | typedef uint8_t duss_wl_prio_t;
  type duss_hal_uart_config_t (line 2462) | typedef struct duss_hal_uart_config_t duss_hal_uart_config_t;
  type duss_hal_can_config_t (line 2464) | typedef struct duss_hal_can_config_t duss_hal_can_config_t;
  type duss_hal_i2c_config_t (line 2466) | typedef struct duss_hal_i2c_config_t duss_hal_i2c_config_t;
  type duss_hal_spi_config_t (line 2468) | typedef struct duss_hal_spi_config_t duss_hal_spi_config_t;
  type hpi_channel (line 2470) | typedef struct hpi_channel hpi_channel;
  type duss_hal_hpi_config_t (line 2472) | typedef struct hpi_channel duss_hal_hpi_config_t;
  type duss_hal_usbacc_config_t (line 2474) | typedef struct duss_hal_usbacc_config_t duss_hal_usbacc_config_t;
  type duss_hal_icc_config_t (line 2476) | typedef struct duss_hal_icc_config_t duss_hal_icc_config_t;
  type duss_hal_bulk_config_t (line 2478) | typedef struct duss_hal_bulk_config_t duss_hal_bulk_config_t;
  type AVOptionType (line 2480) | typedef enum AVOptionType
  type anon_union_conflictac8f4_for_default_val (line 2510) | typedef union anon_union_conflictac8f4_for_default_val anon_union_confli...
  type AVPacketSideDataType (line 2512) | typedef enum AVPacketSideDataType
  type AVCodecParser (line 2531) | typedef struct AVCodecParser AVCodecParser;
  type AVPictureStructure (line 2533) | typedef enum AVPictureStructure
  type AVPicture (line 2541) | typedef struct AVPicture AVPicture;
  type AVSubtitleType (line 2543) | typedef enum AVSubtitleType
  type _DUSS_MSG_SHUTTER_A_t (line 2551) | typedef struct _DUSS_MSG_SHUTTER_A_t _DUSS_MSG_SHUTTER_A_t;
  type DUSS_MSG_SHUTTER_A_t (line 2553) | typedef struct _DUSS_MSG_SHUTTER_A_t DUSS_MSG_SHUTTER_A_t;
  type _DUSS_MSG_V_SS_CONFIG_t (line 2555) | typedef struct _DUSS_MSG_V_SS_CONFIG_t _DUSS_MSG_V_SS_CONFIG_t;
  type DUSS_MSG_V_SS_CONFIG_t (line 2557) | typedef struct _DUSS_MSG_V_SS_CONFIG_t DUSS_MSG_V_SS_CONFIG_t;
  type _DUSS_MSG_SD_STATUS_t (line 2559) | typedef struct _DUSS_MSG_SD_STATUS_t _DUSS_MSG_SD_STATUS_t;
  type DUSS_MSG_SD_STATUS_t (line 2561) | typedef struct _DUSS_MSG_SD_STATUS_t DUSS_MSG_SD_STATUS_t;
  type _DUSS_MSG_ZOOM_CTRL_MODE_t_ (line 2563) | typedef struct _DUSS_MSG_ZOOM_CTRL_MODE_t_ _DUSS_MSG_ZOOM_CTRL_MODE_t_;
  type DUSS_MSG_ZOOM_CTRL_MODE_t (line 2565) | typedef struct _DUSS_MSG_ZOOM_CTRL_MODE_t_ DUSS_MSG_ZOOM_CTRL_MODE_t;
  type anon_union_conflict21a2_for_OZoomRaUnion (line 2567) | typedef union anon_union_conflict21a2_for_OZoomRaUnion anon_union_confli...
  type duss_uart_parity_t (line 2569) | typedef uint8_t duss_uart_parity_t;
  type duss_uart_stopbit_t (line 2571) | typedef uint8_t duss_uart_stopbit_t;
  type duss_uart_wordlen_t (line 2573) | typedef uint8_t duss_uart_wordlen_t;
  type duss_mb_can_chip_t (line 2575) | typedef uint8_t duss_mb_can_chip_t;
  type duss_mb_host_id_t (line 2577) | typedef uint16_t duss_mb_host_id_t;
  type duss_i2c_addr_len_t (line 2579) | typedef uint8_t duss_i2c_addr_len_t;
  type uint (line 2581) | typedef uint __u32;
  type uchar (line 2583) | typedef uchar __u8;
  type ushort (line 2585) | typedef ushort __u16;
  type duss_usbacc_port_t (line 2587) | typedef uint16_t duss_usbacc_port_t;
  type duss_hal_icc_role_t (line 2589) | typedef enum duss_hal_icc_role_t
  type duss_hal_icc_shm_type_t (line 2596) | typedef enum duss_hal_icc_shm_type_t
  type _DUSS_MSG_ZOOM_S_t (line 2603) | typedef struct _DUSS_MSG_ZOOM_S_t _DUSS_MSG_ZOOM_S_t;
  type DUSS_MSG_ZOOM_S_t (line 2605) | typedef struct _DUSS_MSG_ZOOM_S_t DUSS_MSG_ZOOM_S_t;
  type _DUSS_MSG_ZOOM_P_t (line 2607) | typedef struct _DUSS_MSG_ZOOM_P_t _DUSS_MSG_ZOOM_P_t;
  type DUSS_MSG_ZOOM_P_t (line 2609) | typedef struct _DUSS_MSG_ZOOM_P_t DUSS_MSG_ZOOM_P_t;
  type _DUSS_MSG_ZOOM_C_t (line 2611) | typedef struct _DUSS_MSG_ZOOM_C_t _DUSS_MSG_ZOOM_C_t;
  type DUSS_MSG_ZOOM_C_t (line 2613) | typedef struct _DUSS_MSG_ZOOM_C_t DUSS_MSG_ZOOM_C_t;
  type _DUSS_MSG_RACING_CHANNEL_OCCUPIED_IPSD_t (line 2615) | struct _DUSS_MSG_RACING_CHANNEL_OCCUPIED_IPSD_t
  type __gs_avin_test_ctrl (line 2623) | struct __gs_avin_test_ctrl
  type gs_lv_csm (line 2632) | struct gs_lv_csm
  type gs_usb_gadget_vt (line 2645) | struct gs_usb_gadget_vt
  type gs_battery_voltage (line 2663) | struct gs_battery_voltage
  type gs_battery_info (line 2674) | struct gs_battery_info
  type gs_meta_listener (line 2681) | struct gs_meta_listener
  type metadata_retriever (line 2687) | struct metadata_retriever
  type __gs_common_cmd_ctrl (line 2699) | struct __gs_common_cmd_ctrl
  type gs_media_cmd_chnl (line 2715) | struct gs_media_cmd_chnl
  type keys_pack_to_racing_glass_t (line 2724) | struct keys_pack_to_racing_glass_t
  type gs_audio_wl (line 2736) | struct gs_audio_wl
  type anon_struct_conflictc3fb_for_sw (line 2741) | struct anon_struct_conflictc3fb_for_sw
  type anon_struct_conflictc431_for_key (line 2748) | struct anon_struct_conflictc431_for_key
  type factory_check (line 2760) | struct factory_check
  type pack_for_factory_test_t (line 2766) | struct pack_for_factory_test_t
  type gs_shram (line 2775) | struct gs_shram
  type gs_watermarker_us (line 2784) | struct gs_watermarker_us
  type gs_watermarker_ctrl (line 2796) | struct gs_watermarker_ctrl
  type __gs_queue (line 2802) | struct __gs_queue
  type __gs_gui (line 2811) | struct __gs_gui
  type __gs_local_sd_info (line 2826) | struct __gs_local_sd_info
  type rc_set_endpoint_t (line 2848) | struct rc_set_endpoint_t
  type rc_set_all_ep_t (line 2854) | struct rc_set_all_ep_t
  type dummy_ui_ctx_t (line 2862) | struct dummy_ui_ctx_t
  type rc_set_subtrim_reverse_t (line 2880) | struct rc_set_subtrim_reverse_t
  type rc_set_all_st_and_rev_t (line 2887) | struct rc_set_all_st_and_rev_t
  type rc_set_subtrim_t (line 2895) | struct rc_set_subtrim_t
  type rc_set_all_st_t (line 2900) | struct rc_set_all_st_t
  type anon_struct_conflict47e0 (line 2908) | struct anon_struct_conflict47e0
  type anon_struct_conflict47e0 (line 2919) | struct anon_struct_conflict47e0
  type gs_rc_ctrl (line 2923) | struct gs_rc_ctrl
  type gs_wl_ctrl (line 2952) | struct gs_wl_ctrl
  type racing_debug_info_t (line 2961) | struct racing_debug_info_t
  type gs_debug_ctrl (line 3013) | struct gs_debug_ctrl
  type timeval (line 3027) | struct timeval
  type pcm_config (line 3033) | struct pcm_config
  type gs_aout (line 3048) | struct gs_aout
  type gs_lv_src (line 3055) | struct gs_lv_src
  type gs_user_json_root (line 3077) | struct gs_user_json_root
  type gs_video_channel (line 3083) | struct gs_video_channel
  type gs_wl_channel (line 3102) | struct gs_wl_channel
  type gs_local_playback_channel (line 3111) | struct gs_local_playback_channel
  type gs_csi_channel (line 3118) | struct gs_csi_channel
  type gs_rc_setting_channel (line 3127) | struct gs_rc_setting_channel
  type gs_non_video_channel (line 3132) | struct gs_non_video_channel
  type gs_video_channel_id (line 3137) | struct gs_video_channel_id
  type gs_av_in_channel (line 3143) | struct gs_av_in_channel
  type gs_video_channel_manager (line 3152) | struct gs_video_channel_manager
  type duss_osal_mutex_attrib_t (line 3188) | struct duss_osal_mutex_attrib_t
  type gs_buzzer_info (line 3193) | struct gs_buzzer_info
  type _DUSS_MSG_RC_BAT_INFO_t (line 3211) | struct _DUSS_MSG_RC_BAT_INFO_t
  type glass_signal_quality_t (line 3218) | struct glass_signal_quality_t
  type _DUSS_MSG_RACING_PHY_CHECK_REQ_t (line 3226) | struct _DUSS_MSG_RACING_PHY_CHECK_REQ_t
  type _DUSS_MSG_RACING_PHY_CHECK_INFO_t (line 3232) | struct _DUSS_MSG_RACING_PHY_CHECK_INFO_t
  type _DUSS_MSG_RACING_CHANNEL_SCAN_INFO_t (line 3241) | struct _DUSS_MSG_RACING_CHANNEL_SCAN_INFO_t
  type _DUSS_MSG_RACING_CHANNEL_SCAN_REQ_t (line 3249) | struct _DUSS_MSG_RACING_CHANNEL_SCAN_REQ_t
  type gs_modem_link_listener (line 3256) | struct gs_modem_link_listener
  type _DUSS_MSG_RACING_CHANNEL_ROB_INFO_t (line 3262) | struct _DUSS_MSG_RACING_CHANNEL_ROB_INFO_t
  type gs_modem_ctrl (line 3268) | struct gs_modem_ctrl
  type DUSS_MSG_EXT_FC_RTC (line 3313) | struct DUSS_MSG_EXT_FC_RTC
  type DUSS_MSG_EXT_FC_RATE (line 3324) | struct DUSS_MSG_EXT_FC_RATE
  type DUSS_MSG_EXT_FC_FILTER (line 3346) | struct DUSS_MSG_EXT_FC_FILTER
  type DUSS_MSG_EXT_FC_AUX (line 3378) | struct DUSS_MSG_EXT_FC_AUX
  type DUSS_MSG_EXT_FC_BATTERY_STATE (line 3386) | struct DUSS_MSG_EXT_FC_BATTERY_STATE
  type DUSS_MSG_EXT_FC_RC (line 3397) | struct DUSS_MSG_EXT_FC_RC
  type DUSS_MSG_EXT_FC_MSP_STATUS (line 3419) | struct DUSS_MSG_EXT_FC_MSP_STATUS
  type DUSS_MSG_EXT_FC_ESC_DATA (line 3435) | struct DUSS_MSG_EXT_FC_ESC_DATA
  type DUSS_MSG_EXT_FC_OSD_CONFIG (line 3441) | struct DUSS_MSG_EXT_FC_OSD_CONFIG
  type DUSS_MSG_EXT_FC_SERVO (line 3464) | struct DUSS_MSG_EXT_FC_SERVO
  type DUSS_MSG_EXT_FC_VERSION (line 3474) | struct DUSS_MSG_EXT_FC_VERSION
  type DUSS_MSG_EXT_FC_ADVANCED_PID (line 3481) | struct DUSS_MSG_EXT_FC_ADVANCED_PID
  type DUSS_MSG_FC_RACING_DRONE_OSD_PUSH (line 3521) | struct DUSS_MSG_FC_RACING_DRONE_OSD_PUSH
  type DUSS_MSG_EXT_FC_PID (line 3542) | struct DUSS_MSG_EXT_FC_PID
  type gs_ext_fc (line 3561) | struct gs_ext_fc
  type _DUSS_MSG_HISTOGRAM_t (line 3588) | struct _DUSS_MSG_HISTOGRAM_t
  type anon_struct_conflict2349 (line 3594) | struct anon_struct_conflict2349
  type anon_struct_conflict2349 (line 3609) | struct anon_struct_conflict2349
  type _DUSS_MSG_PHOTO_OSD_PARA_ (line 3613) | struct _DUSS_MSG_PHOTO_OSD_PARA_
  type anon_struct_conflict242a (line 3618) | struct anon_struct_conflict242a
  type anon_struct_conflict242a (line 3641) | struct anon_struct_conflict242a
  type _DUSS_MSG_PREVIEW_OSD_PARA_t (line 3645) | struct _DUSS_MSG_PREVIEW_OSD_PARA_t
  type _DUSS_MSG_QUICKVIEW_t (line 3650) | struct _DUSS_MSG_QUICKVIEW_t
  type _DUSS_MSG_CAMERA_AUDIO_STATUS_t (line 3656) | struct _DUSS_MSG_CAMERA_AUDIO_STATUS_t
  type _DUSS_MSG_F_INDEX_MODE_t (line 3664) | struct _DUSS_MSG_F_INDEX_MODE_t
  type _DUSS_MSG_CAM_STATE_t (line 3669) | struct _DUSS_MSG_CAM_STATE_t
  type _DUSS_MSG_SYSTEM_STATE_t (line 3696) | struct _DUSS_MSG_SYSTEM_STATE_t
  type _DUSS_MSG_HYPERLAPSE_LIVEVIEW_MARGIN_t (line 3702) | struct _DUSS_MSG_HYPERLAPSE_LIVEVIEW_MARGIN_t
  type _DUSS_MSG_CAMERA_STATUS_PUSH_t (line 3708) | struct _DUSS_MSG_CAMERA_STATUS_PUSH_t
  type duss_list_head (line 3738) | struct duss_list_head
  type gs_storage_listener (line 3744) | struct gs_storage_listener
  type gs_lv_rec_ctrl (line 3750) | struct gs_lv_rec_ctrl
  type gs_avin_us (line 3768) | struct gs_avin_us
  type gs_av_in_ctrl (line 3780) | struct gs_av_in_ctrl
  type gs_camera_cmd_ctrl_t (line 3790) | struct gs_camera_cmd_ctrl_t
  type gs_bl (line 3811) | struct gs_bl
  type _DUSS_MSG_RC_MS_LINK_STATUS (line 3826) | struct _DUSS_MSG_RC_MS_LINK_STATUS
  type duss_osal_timer_attrib_t (line 3837) | struct duss_osal_timer_attrib_t
  type gs_fan_info (line 3847) | struct gs_fan_info
  type __gs_use_times_info (line 3863) | struct __gs_use_times_info
  type gs_usb_listener (line 3870) | struct gs_usb_listener
  type gs_sd_listener (line 3876) | struct gs_sd_listener
  type gs_lv_transcode (line 3882) | struct gs_lv_transcode
  type __gs_info (line 3953) | struct __gs_info
  type ip_channel_addr (line 4072) | struct ip_channel_addr
  type pthread_cond_t (line 4084) | struct pthread_cond_t
  type AVFrac (line 4089) | struct AVFrac
  type duss_hal_storage_info (line 4096) | struct duss_hal_storage_info
  type AVIndexEntry (line 4112) | struct AVIndexEntry
  type AVBuffer (line 4121) | struct AVBuffer
  type AVRational (line 4125) | struct AVRational
  type AVChapter (line 4131) | struct AVChapter
  type gs_gui_event_t (line 4148) | struct gs_gui_event_t
  type _DUSS_MSG_V_CRTL_t (line 4161) | struct _DUSS_MSG_V_CRTL_t
  type pthread_mutex_t (line 4167) | struct pthread_mutex_t
  type duss_osal_event_attrib_t (line 4172) | struct duss_osal_event_attrib_t
  type duss_osal_event_handle_t (line 4177) | struct duss_osal_event_handle_t
  type modem_ops (line 4186) | struct modem_ops
  type _UAV_RECORD_MODE_t (line 4233) | struct _UAV_RECORD_MODE_t
  type AVFrameSideData (line 4239) | struct AVFrameSideData
  type _DUSS_MSG_APERTURE_t (line 4247) | struct _DUSS_MSG_APERTURE_t
  type _DUSS_MSG_VIDEO_STANDARD_t (line 4252) | struct _DUSS_MSG_VIDEO_STANDARD_t
  type AVCodecParser (line 4257) | struct AVCodecParser
  type hpi_channel (line 4268) | struct hpi_channel
  type hpi_channel_addr (line 4277) | struct hpi_channel_addr
  type _DUSS_MSG_WORKMODE_t (line 4283) | struct _DUSS_MSG_WORKMODE_t
  type timespec (line 4288) | struct timespec
  type ext_fc_ops (line 4294) | struct ext_fc_ops
  type duss_hal_usbacc_config_t (line 4356) | struct duss_hal_usbacc_config_t
  type usbacc_channel_addr (line 4361) | struct usbacc_channel_addr
  type AVCodecContext (line 4369) | struct AVCodecContext
  type _DUSS_MSG_SATURATION_t (line 4604) | struct _DUSS_MSG_SATURATION_t
  type _DUSS_MSG_ZOOM_P_t (line 4609) | struct _DUSS_MSG_ZOOM_P_t
  type _DUSS_MSG_ZOOM_S_t (line 4614) | struct _DUSS_MSG_ZOOM_S_t
  type _DUSS_MSG_ZOOM_C_t (line 4621) | struct _DUSS_MSG_ZOOM_C_t
  type _DUSS_MSG_ZOOM_CTRL_MODE_t_ (line 4635) | struct _DUSS_MSG_ZOOM_CTRL_MODE_t_
  type _DUSS_MSG_ZOOM_PARAM_t (line 4645) | struct _DUSS_MSG_ZOOM_PARAM_t
  type _DUSS_MSG_CAPTURE_MODE_t (line 4652) | struct _DUSS_MSG_CAPTURE_MODE_t
  type _DUSS_MSG_ISO_t (line 4661) | struct _DUSS_MSG_ISO_t
  type _DUSS_MSG_SD_STATUS_t (line 4666) | struct _DUSS_MSG_SD_STATUS_t
  type _DUSS_MSG_SD_INFO_t (line 4673) | struct _DUSS_MSG_SD_INFO_t
  type _DUSS_MSG_EXPO_MODE_t (line 4682) | struct _DUSS_MSG_EXPO_MODE_t
  type _DUSS_MSG_FLIP (line 4688) | struct _DUSS_MSG_FLIP
  type _DUSS_MSG_SHARPNESS_t (line 4694) | struct _DUSS_MSG_SHARPNESS_t
  type _DUSS_MSG_CONTICAP_PARAM_t (line 4699) | struct _DUSS_MSG_CONTICAP_PARAM_t
  type _DUSS_MSG_P_STORAGE_FMT_t (line 4706) | struct _DUSS_MSG_P_STORAGE_FMT_t
  type _DUSS_MSG_RECORD_t (line 4711) | struct _DUSS_MSG_RECORD_t
  type _DUSS_MSG_WB_t (line 4718) | struct _DUSS_MSG_WB_t
  type _DUSS_MSG_CONTRAST_t (line 4724) | struct _DUSS_MSG_CONTRAST_t
  type _DUSS_MSG_SHUTTER_A_t (line 4729) | struct _DUSS_MSG_SHUTTER_A_t
  type _DUSS_MSG_SHUTTER_SPEED_t (line 4736) | struct _DUSS_MSG_SHUTTER_SPEED_t
  type _DUSS_MSG_DIGITAL_EFFECT_t (line 4742) | struct _DUSS_MSG_DIGITAL_EFFECT_t
  type _DUSS_MSG_EV_BIAS_t (line 4747) | struct _DUSS_MSG_EV_BIAS_t
  type _DUSS_MSG_V_STORAGE_FMT_t (line 4752) | struct _DUSS_MSG_V_STORAGE_FMT_t
  type _DUSS_MSG_SINGLE_PLAY_CRTL_t (line 4757) | struct _DUSS_MSG_SINGLE_PLAY_CRTL_t
  type _DUSS_MSG_SCENE_MODE_t (line 4762) | struct _DUSS_MSG_SCENE_MODE_t
  type _DUSS_MSG_SET_FOCUS_REGION_t (line 4767) | struct _DUSS_MSG_SET_FOCUS_REGION_t
  type _DUSS_MSG_V_SS_CONFIG_t (line 4773) | struct _DUSS_MSG_V_SS_CONFIG_t
  type _DUSS_MSG_V_FORMAT_t (line 4779) | struct _DUSS_MSG_V_FORMAT_t
  type _DUSS_MSG_P_SIZE_t (line 4788) | struct _DUSS_MSG_P_SIZE_t
  type _DUSS_MSG_CAPTURE_t (line 4794) | struct _DUSS_MSG_CAPTURE_t
  type __gs_camera_cmd (line 4837) | struct __gs_camera_cmd
  type bridge_io_pkt (line 4848) | struct bridge_io_pkt
  type gs_lv_pkt (line 4858) | struct gs_lv_pkt
  type uav_gimbal_ops (line 4868) | struct uav_gimbal_ops
  type duss_hal_icc_config_t (line 4884) | struct duss_hal_icc_config_t
  type RcOverride (line 4891) | struct RcOverride
  type uav_camera_ops (line 4899) | struct uav_camera_ops
  type duss_event_cmd_desc (line 4906) | struct duss_event_cmd_desc
  type cJSON (line 4913) | struct cJSON
  type vr_device_ops (line 4929) | struct vr_device_ops
  type pl_decoder_itf_t (line 4963) | struct pl_decoder_itf_t
  type duss_event_ack_identify (line 4977) | struct duss_event_ack_identify
  type vcm_ops (line 4989) | struct vcm_ops
  type AVOptionRange (line 5004) | struct AVOptionRange
  type debug_osd_item (line 5022) | struct debug_osd_item
  type debug_cam_osd_info (line 5028) | struct debug_cam_osd_info
  type AVPanScan (line 5034) | struct AVPanScan
  type AVProfile (line 5042) | struct AVProfile
  type loc_channel_addr (line 5048) | struct loc_channel_addr
  type __gs_common_cmd (line 5053) | struct __gs_common_cmd
  type duss_hal_mem_config_t (line 5069) | struct duss_hal_mem_config_t
  type wl_channel_addr (line 5074) | struct wl_channel_addr
  type AVDeviceCapabilitiesQuery (line 5090) | struct AVDeviceCapabilitiesQuery
  type __sbuf (line 5094) | struct __sbuf
  type vdec_video_file_info (line 5100) | struct vdec_video_file_info
  type fd_set (line 5113) | struct fd_set
  type duss_mb_client (line 5118) | struct duss_mb_client
  type AVPacket (line 5142) | struct AVPacket
  type icc_channel_addr (line 5173) | struct icc_channel_addr
  type duss_mb_route_table_t (line 5181) | struct duss_mb_route_table_t
  type AVCodecInternal (line 5188) | struct AVCodecInternal
  type pl_decoder_t (line 5192) | struct pl_decoder_t
  type gs_local_panorama_info (line 5207) | struct gs_local_panorama_info
  type duss_hal_i2c_config_t (line 5217) | struct duss_hal_i2c_config_t
  type duss_hal_storage_params (line 5226) | struct duss_hal_storage_params
  type AVBufferRef (line 5233) | struct AVBufferRef
  type sem_t (line 5240) | struct sem_t
  type duss_osal_mutex_handle_t (line 5245) | struct duss_osal_mutex_handle_t
  type stick_mode_self_define_t (line 5251) | struct stick_mode_self_define_t
  type rc_set_stick_mode_pack_t (line 5257) | struct rc_set_stick_mode_pack_t
  type duss_osal_task_attrib_t (line 5263) | struct duss_osal_task_attrib_t
  type SwrContext (line 5278) | struct SwrContext
  type AVHWAccel (line 5282) | struct AVHWAccel
  type netlink_channel_addr (line 5301) | struct netlink_channel_addr
  type duss_hal_uart_config_t (line 5308) | struct duss_hal_uart_config_t
  type uart_channel_addr (line 5317) | struct uart_channel_addr
  type usb_channel_addr (line 5323) | struct usb_channel_addr
  type duss_hal_spi_config_t (line 5336) | struct duss_hal_spi_config_t
  type spi_channel_addr (line 5344) | struct spi_channel_addr
  type duss_hal_can_config_t (line 5350) | struct duss_hal_can_config_t
  type can_channel_addr (line 5364) | struct can_channel_addr
  type duss_hal_bulk_config_t (line 5370) | struct duss_hal_bulk_config_t
  type bulk_channel_addr (line 5374) | struct bulk_channel_addr
  type i2c_channel_addr (line 5380) | struct i2c_channel_addr
  type loc_channel_addr (line 5388) | struct loc_channel_addr
  type ip_channel_addr (line 5389) | struct ip_channel_addr
  type wl_channel_addr (line 5390) | struct wl_channel_addr
  type uart_channel_addr (line 5391) | struct uart_channel_addr
  type can_channel_addr (line 5392) | struct can_channel_addr
  type i2c_channel_addr (line 5393) | struct i2c_channel_addr
  type spi_channel_addr (line 5394) | struct spi_channel_addr
  type hpi_channel_addr (line 5395) | struct hpi_channel_addr
  type usb_channel_addr (line 5396) | struct usb_channel_addr
  type usbacc_channel_addr (line 5397) | struct usbacc_channel_addr
  type icc_channel_addr (line 5398) | struct icc_channel_addr
  type netlink_channel_addr (line 5399) | struct netlink_channel_addr
  type bulk_channel_addr (line 5400) | struct bulk_channel_addr
  type AVPicture (line 5403) | struct AVPicture
  type debug_cp_osd_info (line 5409) | struct debug_cp_osd_info
  type AVDictionary (line 5415) | struct AVDictionary
  type duss_hal_mem_param_t (line 5419) | struct duss_hal_mem_param_t
  type ion_info (line 5424) | struct ion_info
  type audio_resampler_t (line 5438) | struct audio_resampler_t
  type pcm (line 5449) | struct pcm
  type duss_mb_filter_t (line 5485) | struct duss_mb_filter_t
  type duss_hal_obj_dev_t (line 5495) | struct duss_hal_obj_dev_t
  type duss_hal_obj (line 5512) | struct duss_hal_obj
  type duss_event (line 5519) | struct duss_event
  type common_cmd_ops (line 5531) | struct common_cmd_ops
  type local_playback_ops (line 5536) | struct local_playback_ops
  type rc_ops (line 5553) | struct rc_ops
  type __gs_gui_config (line 5585) | struct __gs_gui_config
  type AVCodecParserContext (line 5654) | struct AVCodecParserContext
  type duss_osal_msgq_attrib_t (line 5701) | struct duss_osal_msgq_attrib_t
  type duss_osal_msgq_handle_t (line 5707) | struct duss_osal_msgq_handle_t
  type duss_mb_route_item_t (line 5720) | struct duss_mb_route_item_t
  type rc_monitor_pack_t (line 5735) | struct rc_monitor_pack_t
  type AVFormatInternal (line 5741) | struct AVFormatInternal
  type debug_osd_info (line 5745) | struct debug_osd_info
  type AVOptionRanges (line 5751) | struct AVOptionRanges
  type snd_pcm_sync_ptr (line 5758) | struct snd_pcm_sync_ptr
  type AVRational (line 5767) | struct AVRational
  type gs_playback_listener (line 5770) | struct gs_playback_listener
  type gs_local_video_info (line 5776) | struct gs_local_video_info
  type gs_video_channel_message (line 5797) | struct gs_video_channel_message
  type snd_pcm_mmap_status (line 5803) | struct snd_pcm_mmap_status
  type audio_dec (line 5807) | struct audio_dec
  type AVCodecDefault (line 5859) | struct AVCodecDefault
  type AVCodecTag (line 5863) | struct AVCodecTag
  type AVProgram (line 5867) | struct AVProgram
  type AVInputFormat (line 5892) | struct AVInputFormat
  type anon_struct_conflict69b3c_for_info (line 5918) | struct anon_struct_conflict69b3c_for_info
  type duss_storage_client (line 5955) | struct duss_storage_client
  type duss_osal_timer_handle_t (line 5965) | struct duss_osal_timer_handle_t
  type rc_set_warning_mode_pack_t (line 5979) | struct rc_set_warning_mode_pack_t
  type AVClass (line 5987) | struct AVClass
  type AVIOInterruptCB (line 6002) | struct AVIOInterruptCB
  type AVPacketSideData (line 6008) | struct AVPacketSideData
  type product_shm_info (line 6015) | struct product_shm_info
  type debug_temp_osd_info (line 6047) | struct debug_temp_osd_info
  type pl_muxer_itf_t (line 6053) | struct pl_muxer_itf_t
  type AVFrame (line 6065) | struct AVFrame
  type vdec_local_player (line 6153) | struct vdec_local_player
  type AVDeviceInfoList (line 6187) | struct AVDeviceInfoList
  type AVCodecDescriptor (line 6191) | struct AVCodecDescriptor
  type AVFormatContext (line 6201) | struct AVFormatContext
  type duss_event_client (line 6301) | struct duss_event_client
  type MpegEncContext (line 6322) | struct MpegEncContext
  type AVPacketList (line 6326) | struct AVPacketList
  type AVProbeData (line 6336) | struct AVProbeData
  type AVStream (line 6344) | struct AVStream
  type duss_hal_mem_buf (line 6433) | struct duss_hal_mem_buf
  type AVSubtitleRect (line 6437) | struct AVSubtitleRect
  type AVIOContext (line 6451) | struct AVIOContext
  type AVOption (line 6498) | struct AVOption
  type AVSubtitle (line 6511) | struct AVSubtitle
  type duss_osal_task_handle_t (line 6527) | struct duss_osal_task_handle_t
  type modem_shmem_info_t (line 6533) | struct modem_shmem_info_t
  type sqlite3 (line 6604) | struct sqlite3
  type cp_vdec (line 6608) | struct cp_vdec
  type AVOutputFormat (line 6631) | struct AVOutputFormat
  type rc_set_function_pack_t (line 6658) | struct rc_set_function_pack_t
  type pl_muxer_t (line 6666) | struct pl_muxer_t
  type AVCodec (line 6673) | struct AVCodec
  type snd_pcm_mmap_control (line 6705) | struct snd_pcm_mmap_control

FILE: jni/rec/rec_util.c
  function rec_util_osd_path_from_video_path (line 4) | void rec_util_osd_path_from_video_path(const char *video_path, char *osd...

FILE: jni/toast/toast.c
  type ToastItem (line 20) | typedef struct ToastItem
  type timespec (line 30) | struct timespec
  function toast_load_config (line 32) | void toast_load_config()
  function toast_pop (line 40) | int toast_pop()
  function toast (line 56) | int toast(char *data, ...)
  function do_toast (line 88) | void do_toast(void (*display_print_string)(uint8_t init_x, uint8_t y, co...

FILE: jni/util/display_info.h
  type display_info_t (line 8) | typedef struct display_info_s {

FILE: jni/util/fs_util.c
  function get_int_from_fs (line 15) | int32_t get_int_from_fs(char* path) {
  type stat (line 34) | struct stat

FILE: jni/util/time_util.h
  function timespec_subtract (line 9) | static inline void timespec_subtract(struct timespec *res, const struct ...
  function timespec_subtract_ns (line 19) | static inline int64_t timespec_subtract_ns(const struct timespec *a, con...

FILE: libshims/duml_hal.c
  function duss_result_t (line 3) | duss_result_t duss_hal_initialize(duss_hal_device_desc_t *)
  function duss_result_t (line 11) | duss_result_t duss_hal_deinitialize()
  function duss_result_t (line 19) | duss_result_t duss_hal_device_open(char *device_name, void *unknown, dus...
  function duss_result_t (line 27) | duss_result_t duss_hal_device_start(duss_hal_obj_handle_t, void *)
  function duss_result_t (line 35) | duss_result_t duss_hal_device_close(duss_hal_obj_handle_t)
  function duss_result_t (line 43) | duss_result_t duss_hal_device_stop(duss_hal_obj_handle_t)
  function duss_result_t (line 51) | duss_result_t duss_hal_mem_alloc(duss_hal_obj_handle_t, duss_hal_mem_han...
  function duss_result_t (line 59) | duss_result_t duss_hal_mem_get_phys_addr(duss_hal_mem_handle_t, void **)
  function duss_result_t (line 67) | duss_result_t duss_hal_mem_map(duss_hal_mem_handle_t, void **)
  function duss_result_t (line 75) | duss_result_t duss_hal_mem_free(duss_hal_mem_handle_t)
  function duss_result_t (line 83) | duss_result_t duss_hal_mem_sync(duss_hal_mem_handle_t, uint32_t)
  function duss_result_t (line 91) | duss_result_t duss_hal_display_open(duss_hal_obj_handle_t, duss_disp_ins...
  function duss_result_t (line 99) | duss_result_t duss_hal_display_close(duss_hal_obj_handle_t, duss_disp_in...
  function duss_result_t (line 107) | duss_result_t duss_hal_display_aquire_plane(duss_disp_instance_handle_t ...
  function duss_result_t (line 115) | duss_result_t duss_hal_display_reset(duss_disp_instance_handle_t *)
  function duss_result_t (line 123) | duss_result_t duss_hal_display_register_frame_cycle_callback(duss_disp_i...
  function duss_result_t (line 131) | duss_result_t duss_hal_display_timing_detail_get(duss_disp_instance_hand...
  function duss_result_t (line 139) | duss_result_t duss_hal_display_port_enable(duss_disp_instance_handle_t *...
  function duss_result_t (line 147) | duss_result_t duss_hal_display_plane_blending_set(duss_disp_instance_han...
  function duss_result_t (line 155) | duss_result_t duss_hal_display_release_plane(duss_disp_instance_handle_t...
  function duss_result_t (line 163) | duss_result_t duss_hal_display_push_frame(duss_disp_instance_handle_t *,...
  function duss_result_t (line 171) | duss_result_t duss_hal_attach_disp(char *param_1, duss_hal_obj **param_2)
  function duss_result_t (line 179) | duss_result_t duss_hal_attach_ion_mem(char *param_1, duss_hal_obj **para...
  function duss_result_t (line 187) | duss_result_t duss_hal_detach_ion_mem()
  function duss_result_t (line 195) | duss_result_t duss_hal_detach_disp()
Condensed preview — 80 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (914K chars).
[
  {
    "path": ".github/workflows/build.yml",
    "chars": 3086,
    "preview": "on:\r\n  # Triggers the workflow on push or pull request events but only for the main branch\r\n  push:\r\n    branches: [ mai"
  },
  {
    "path": ".gitignore",
    "chars": 86,
    "preview": "*.o\nosd_dji\nmsp_displayport_mux\nipk/goggle/build\nipk/airunit/build\n*.ipk\nrepo\nobj\nlibs"
  },
  {
    "path": "FAKEHD.md",
    "chars": 7439,
    "preview": "# FakeHD\n\nBetaflight's (before 4.4) OSD supports a 30 * 16 Grid, which looks large/blocky when displayed in the DJI Gogg"
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "Makefile.dji",
    "chars": 3263,
    "preview": "CC=armv7a-linux-androideabi19-clang\nCFLAGS=-I. -O2\nLIB_SHIMS = libshims/libduml_hal.so\n\n.PHONY: repo\n\n%.o: %.c $(DEPS)\n\t"
  },
  {
    "path": "Makefile.unix",
    "chars": 609,
    "preview": "CC=gcc\nCFLAGS=-I. -O2\nSRCDIR = jni/\nDEPS = $(addprefix $(SRCDIR), msp/msp.h msp/msp_displayport.h net/network.h net/seri"
  },
  {
    "path": "README.md",
    "chars": 23133,
    "preview": "# IMPORTANT\nAs of msp-osd v0.12+, the required font format has now changed for the goggles and the OSD Overlay tool.  Su"
  },
  {
    "path": "config/airunit/config.json",
    "chars": 147,
    "preview": "{\n    \"fast_serial\": false,\n    \"cache_serial\": false,\n    \"osd_update_rate_hz\": 10,\n    \"compress_osd\": true,\n    \"disa"
  },
  {
    "path": "config/airunit/schema.json",
    "chars": 615,
    "preview": "{\n    \"settings\": {\n      \"fast_serial\": {\n        \"name\": \"Fast Serial\",\n        \"widget\": \"checkbox\"\n      },\n      \"c"
  },
  {
    "path": "config/airunit/schemaV2.json",
    "chars": 1289,
    "preview": "{\n    \"title\": \"MSP OSD\",\n    \"description\": \"Airside OSD config\",\n    \"type\": \"object\",\n    \"units\": [\n        \"msp-osd"
  },
  {
    "path": "config/airunit/uiSchemaV2.json",
    "chars": 900,
    "preview": "{\n    \"compress_osd\": {\n        \"ui:help\": \"Enable sending full frames of compressed data. Disable to send raw MSP data "
  },
  {
    "path": "config/goggles/config.json",
    "chars": 380,
    "preview": "{\n    \"show_waiting\": true,\n    \"show_au_data\": false,\n    \"fakehd_enable\": false,\n    \"fakehd_hide_throttle_element\": f"
  },
  {
    "path": "config/goggles/schema.json",
    "chars": 1460,
    "preview": "{\n\t\"settings\": {\n\t\t\"show_waiting\": {\n\t\t\t\"name\": \"Show Waiting Message\",\n\t\t\t\"widget\": \"checkbox\"\n\t\t},\n\t\t\"show_au_data\": {"
  },
  {
    "path": "config/goggles/schemaV2.json",
    "chars": 4642,
    "preview": "{\n    \"title\": \"MSP OSD - Goggles\",\n    \"description\": \"\",\n    \"type\": \"object\",\n    \"units\": [ \"msp-osd-goggles\" ],\n   "
  },
  {
    "path": "config/goggles/uiSchemaV2.json",
    "chars": 1720,
    "preview": "{\n    \"show_waiting\": {\n        \"ui:help\": \"Enables or disables WAITING FOR OSD message\"\n    },\n    \"show_au_data\": {\n  "
  },
  {
    "path": "docs/fonts/gen.sh",
    "chars": 533,
    "preview": "#!/bin/bash\n\n\necho \"You need https://github.com/shellixyz/hd_fpv_osd_font_tool\";\necho \"And you need montage from imagema"
  },
  {
    "path": "ipk/airunit/control/conffiles",
    "chars": 44,
    "preview": "/opt/etc/package-config/msp-osd/config.json\n"
  },
  {
    "path": "ipk/airunit/control/control",
    "chars": 238,
    "preview": "Package: msp-osd\nVersion: 0.10.1\nMaintainer: bri3d\nDescription: MSP OSD service for the DJI HD FPV airunit.\nArchitecture"
  },
  {
    "path": "ipk/airunit/control/postinst",
    "chars": 70,
    "preview": "#!/system/bin/sh\n/opt/sbin/dinitctl -u enable msp-osd-airside || true\n"
  },
  {
    "path": "ipk/airunit/control/prerm",
    "chars": 72,
    "preview": "#!/system/bin/sh\n/opt/sbin/dinitctl -u disable msp-osd-airside || true\n\n"
  },
  {
    "path": "ipk/airunit/data/opt/bin/airunit-osd-start.sh",
    "chars": 329,
    "preview": "#!/system/bin/sh\nsetprop dji.hdvt_uav_service 0\nsetprop dji.shuttle_service 0\n\nif [ ! -e \"/dev/ttyS1_moved\" ]\nthen\n  mv "
  },
  {
    "path": "ipk/airunit/data/opt/etc/dinit.d/msp-osd-airside",
    "chars": 116,
    "preview": "type = bgprocess\ncommand = /opt/bin/airunit-osd-start.sh\npid-file = /opt/var/run/airunit-osd-dji.pid\nrestart = true\n"
  },
  {
    "path": "ipk/goggle/control/conffiles",
    "chars": 44,
    "preview": "/opt/etc/package-config/msp-osd/config.json\n"
  },
  {
    "path": "ipk/goggle/control/control",
    "chars": 229,
    "preview": "Package: msp-osd\nVersion: 0.12.4\nMaintainer: bri3d\nDescription: MSP OSD service for the DJI HD FPV goggles.\nArchitecture"
  },
  {
    "path": "ipk/goggle/control/postinst",
    "chars": 70,
    "preview": "#!/system/bin/sh\n/opt/sbin/dinitctl -u enable msp-osd-goggles || true\n"
  },
  {
    "path": "ipk/goggle/control/preinst",
    "chars": 124,
    "preview": "#!/system/bin/sh\nif [[ -f /opt/fonts ]]; then\n    rm -f /opt/fonts\nfi\n/opt/sbin/dinitctl -u disable msp-osd-goggles || t"
  },
  {
    "path": "ipk/goggle/control/prerm",
    "chars": 71,
    "preview": "#!/system/bin/sh\n/opt/sbin/dinitctl -u disable msp-osd-goggles || true\n"
  },
  {
    "path": "ipk/goggle/data/opt/etc/dinit.d/msp-osd-goggles",
    "chars": 143,
    "preview": "type = scripted\ncommand = modmanager enable diy_glasses displayport_osd_shim\nstop-command = modmanager disable diy_glass"
  },
  {
    "path": "jni/Android.mk",
    "chars": 1135,
    "preview": "LOCAL_PATH := $(call my-dir)\ninclude $(CLEAR_VARS)\n\nLOCAL_MODULE := duml_hal\nLOCAL_SRC_FILES := libduml_hal.so\nLOCAL_EXP"
  },
  {
    "path": "jni/Application.mk",
    "chars": 94,
    "preview": "APP_PLATFORM=android-23\nAPP_ABI=armeabi-v7a\nAPP_CFLAGS += -DSTDC_HEADERS\nAPP_OPTIM := release\n"
  },
  {
    "path": "jni/displayport_osd_shim.c",
    "chars": 5641,
    "preview": "#include <stdlib.h>\n#include <stdbool.h>\n#include <unistd.h>\n#include <dlfcn.h>\n#include <string.h>\n\n#include \"osd.h\"\n#i"
  },
  {
    "path": "jni/fakehd/fakehd.c",
    "chars": 8922,
    "preview": "#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n\n#include \"json/osd_config.h\"\n#include \"toast/toast.h\"\n\n#defi"
  },
  {
    "path": "jni/fakehd/fakehd.h",
    "chars": 241,
    "preview": "#pragma once\n\nvoid load_fakehd_config();\nvoid fakehd_disable();\nvoid fakehd_enable();\nint fakehd_is_enabled();\nvoid fake"
  },
  {
    "path": "jni/font/font.c",
    "chars": 8145,
    "preview": "#include <sys/fcntl.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <string.h>\n#include <stdlib.h>\n#include <uni"
  },
  {
    "path": "jni/font/font.h",
    "chars": 734,
    "preview": "#pragma once\n\n#include <stdint.h>\n\n#include \"../util/display_info.h\"\n\n#define FALLBACK_FONT_PATH \"/blackbox/font\"\n#defin"
  },
  {
    "path": "jni/hw/dji_display.c",
    "chars": 10734,
    "preview": "#include <stdlib.h>\n#include \"dji_display.h\"\n#include \"util/debug.h\"\n\n#define GOGGLES_V1_VOFFSET 575\n#define GOGGLES_V2_"
  },
  {
    "path": "jni/hw/dji_display.h",
    "chars": 1262,
    "preview": "#pragma once\n#include \"duml_hal.h\"\n\ntypedef struct dji_display_state_s {\n    duss_disp_plane_id_t plane_id;\n    duss_hal"
  },
  {
    "path": "jni/hw/dji_radio_shm.c",
    "chars": 942,
    "preview": "#include <assert.h>\n#include <stdio.h>\n#include <fcntl.h>\n#include <sys/mman.h>\n\n#include \"dji_radio_shm.h\"\n\nvoid open_d"
  },
  {
    "path": "jni/hw/dji_radio_shm.h",
    "chars": 3143,
    "preview": "\n#pragma once\n#include <stdint.h>\n\n#define RTOS_SHM_ADDRESS 0xfffc1000\n#define RTOS_SHM_SIZE 0x1000\n\n#define RTOS_PRODUC"
  },
  {
    "path": "jni/hw/dji_services.c",
    "chars": 840,
    "preview": "#include <string.h>\n#ifdef __ANDROID_API__\n#include <sys/system_properties.h>\n#endif\n\n#define V2_SERVICE_NAME \"dji.glass"
  },
  {
    "path": "jni/hw/dji_services.h",
    "chars": 108,
    "preview": "#pragma once\n\nvoid dji_stop_goggles(int is_v2);\nvoid dji_start_goggles(int is_v2);\nint dji_goggles_are_v2();"
  },
  {
    "path": "jni/hw/duml_hal.h",
    "chars": 8815,
    "preview": "#pragma once\n#include <stdint.h>\n\ntypedef int32_t duss_result_t;\n\ntypedef uint8_t duss_hal_state_t;\ntypedef uint8_t duss"
  },
  {
    "path": "jni/json/osd_config.c",
    "chars": 1214,
    "preview": "#include \"parson.h\"\n#define JSON_CONFIG_PATH \"/opt/etc/package-config/msp-osd/config.json\"\nstatic JSON_Object *root_obje"
  },
  {
    "path": "jni/json/osd_config.h",
    "chars": 147,
    "preview": "int get_boolean_config_value(const char* key);\nconst char *get_string_config_value(const char *key);\nint get_integer_con"
  },
  {
    "path": "jni/json/parson.c",
    "chars": 82105,
    "preview": "/*\n SPDX-License-Identifier: MIT\n\n Parson 1.4.0 (https://github.com/kgabis/parson)\n Copyright (c) 2012 - 2022 Krzysztof "
  },
  {
    "path": "jni/json/parson.h",
    "chars": 13691,
    "preview": "/*\n SPDX-License-Identifier: MIT\n\n Parson 1.4.0 (https://github.com/kgabis/parson)\n Copyright (c) 2012 - 2022 Krzysztof "
  },
  {
    "path": "jni/libspng/spng.c",
    "chars": 199624,
    "preview": "/* SPDX-License-Identifier: (BSD-2-Clause AND libpng-2.0) */\n\n#define SPNG__BUILD\n\n#include \"spng.h\"\n\n#include <limits.h"
  },
  {
    "path": "jni/libspng/spng.h",
    "chars": 13338,
    "preview": "/* SPDX-License-Identifier: BSD-2-Clause */\n#ifndef SPNG_H\n#define SPNG_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#if ("
  },
  {
    "path": "jni/lz4/lz4.c",
    "chars": 114197,
    "preview": "/*\n   LZ4 - Fast LZ compression algorithm\n   Copyright (C) 2011-2020, Yann Collet.\n\n   BSD 2-Clause License (http://www."
  },
  {
    "path": "jni/lz4/lz4.h",
    "chars": 44421,
    "preview": "/*\n *  LZ4 - Fast LZ compression algorithm\n *  Header File\n *  Copyright (C) 2011-2020, Yann Collet.\n\n   BSD 2-Clause Li"
  },
  {
    "path": "jni/msp/msp.c",
    "chars": 4077,
    "preview": "#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include \"msp.h\"\n\nuint16_t msp_data_from_msg(uint8_t message_"
  },
  {
    "path": "jni/msp/msp.h",
    "chars": 1415,
    "preview": "#pragma once\n#include <stdint.h>\n\n#define MSP_CMD_API_VERSION 1\n#define MSP_CMD_FC_VARIANT 2\n#define MSP_CMD_FC_VERSION "
  },
  {
    "path": "jni/msp/msp_displayport.c",
    "chars": 2846,
    "preview": "#include \"msp.h\"\n#include \"msp_displayport.h\"\n\nstatic void process_draw_string(displayport_vtable_t *display_driver, uin"
  },
  {
    "path": "jni/msp/msp_displayport.h",
    "chars": 961,
    "preview": "#pragma once\n#include <stdint.h>\n#include \"msp.h\"\n\ntypedef enum {\n    MSP_DISPLAYPORT_KEEPALIVE,\n    MSP_DISPLAYPORT_CLO"
  },
  {
    "path": "jni/msp_displayport_mux.c",
    "chars": 18007,
    "preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <string.h>\n#include <sys/poll.h>\n#include <time.h>\n\n"
  },
  {
    "path": "jni/net/data_protocol.h",
    "chars": 413,
    "preview": "#include <stdint.h>\n\ntypedef struct packet_data_s {\n    uint16_t tx_temperature;\n    uint16_t version_specifier; // Used"
  },
  {
    "path": "jni/net/network.c",
    "chars": 1356,
    "preview": "#include <arpa/inet.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <fcntl.h>\n#include <stdio.h>\n#include <s"
  },
  {
    "path": "jni/net/network.h",
    "chars": 88,
    "preview": "#pragma once\n\nint connect_to_server(char *address, int port);\nint bind_socket(int port);"
  },
  {
    "path": "jni/net/serial.c",
    "chars": 3575,
    "preview": "#include <stdio.h>\n#include <arpa/inet.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <unistd.h>\n#include <"
  },
  {
    "path": "jni/net/serial.h",
    "chars": 265,
    "preview": "#pragma once\n\n#include <termios.h>\n\nint open_serial_port(const char *device, speed_t baudrate);\nint open_pty(const char "
  },
  {
    "path": "jni/osd.h",
    "chars": 169,
    "preview": "#pragma once\n\n#include \"hw/dji_display.h\"\n\nvoid osd_directfb(duss_disp_instance_handle_t *disp, duss_hal_obj_handle_t io"
  },
  {
    "path": "jni/osd_dji_overlay_udp.c",
    "chars": 22825,
    "preview": "#include <stdio.h>\n#include <arpa/inet.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <unistd.h>\n#include <"
  },
  {
    "path": "jni/osd_dji_udp.c",
    "chars": 17013,
    "preview": "#include <stdio.h>\n#include <arpa/inet.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <unistd.h>\n#include <"
  },
  {
    "path": "jni/osd_sfml_udp.c",
    "chars": 6170,
    "preview": "#include <stdio.h>\n#include <arpa/inet.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <unistd.h>\n#include <"
  },
  {
    "path": "jni/rec/rec.c",
    "chars": 2868,
    "preview": "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../json/osd_config.h\"\n\n#include \"rec.h\"\n#include \""
  },
  {
    "path": "jni/rec/rec.h",
    "chars": 1227,
    "preview": "#pragma once\n\n#include <stdbool.h>\n#include <stdint.h>\n\n#define REC_MAGIC \"MSPOSD\"\n#define REC_VERSION 2\n\ntypedef struct"
  },
  {
    "path": "jni/rec/rec_pb.c",
    "chars": 6303,
    "preview": "#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n\n#include \"../json/osd_config.h\"\n\n#in"
  },
  {
    "path": "jni/rec/rec_pb.h",
    "chars": 347,
    "preview": "#pragma once\n\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdbool.h>\n\nextern uint8_t rec_pb_start_attempted;\n\nvoid"
  },
  {
    "path": "jni/rec/rec_shim.c",
    "chars": 1751,
    "preview": "#include <dlfcn.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"../hw/dji_services.h\"\n#include \"rec_shim.h\"\n\n#ifdef"
  },
  {
    "path": "jni/rec/rec_shim.h",
    "chars": 172433,
    "preview": "#pragma once\n\n#include <stdbool.h>\n\ntypedef unsigned char undefined;\n\ntypedef unsigned char byte;\ntypedef unsigned int d"
  },
  {
    "path": "jni/rec/rec_util.c",
    "chars": 537,
    "preview": "#include \"rec_util.h\"\n#include <string.h>\n\nvoid rec_util_osd_path_from_video_path(const char *video_path, char *osd_path"
  },
  {
    "path": "jni/rec/rec_util.h",
    "chars": 137,
    "preview": "#pragma once\n\n#include <stdlib.h>\n\nvoid rec_util_osd_path_from_video_path(const char *video_path, char *osd_path, size_t"
  },
  {
    "path": "jni/toast/toast.c",
    "chars": 3428,
    "preview": "#include <assert.h>\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <ctype.h>\n#in"
  },
  {
    "path": "jni/toast/toast.h",
    "chars": 167,
    "preview": "#pragma once\n\nint toast(char*, ...);\nvoid toast_load_config();\nvoid do_toast(void (*display_print_string)(uint8_t init_x"
  },
  {
    "path": "jni/util/debug.h",
    "chars": 143,
    "preview": "// #pragma once\n\n#ifdef DEBUG\n#define DEBUG_PRINT(fmt, args...)    fprintf(stderr, fmt, ## args)\n#else\n#define DEBUG_PRI"
  },
  {
    "path": "jni/util/display_info.h",
    "chars": 309,
    "preview": "#pragma once\n\n#include <stdint.h>\n\n#define NUM_CHARS 256\n#define NUM_FONT_PAGES 4\n\ntypedef struct display_info_s {\n    u"
  },
  {
    "path": "jni/util/fs_util.c",
    "chars": 1190,
    "preview": "#include <stdint.h>\n#include <stdio.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <string.h>\n#i"
  },
  {
    "path": "jni/util/fs_util.h",
    "chars": 95,
    "preview": "#pragma once\n\n#include <stdint.h>\n\nint32_t get_int_from_fs(char*);\nvoid *open_dict(int, int *);"
  },
  {
    "path": "jni/util/time_util.h",
    "chars": 595,
    "preview": "#pragma once\n\n#include <time.h>\n#include <stdbool.h>\n\n#define NSEC_PER_SEC 1000000000\n#define MSEC_PER_SEC 1000\n\nstatic "
  },
  {
    "path": "libshims/duml_hal.c",
    "chars": 3365,
    "preview": "#include \"jni/hw/duml_hal.h\"\n\nduss_result_t duss_hal_initialize(duss_hal_device_desc_t *)\n{\n    duss_result_t dummy;\n\n  "
  }
]

About this extraction

This page contains the full source code of the fpv-wtf/msp-osd GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 80 files (859.0 KB), approximately 242.7k tokens, and a symbol index with 1612 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!