Thursday, August 25, 2016

Android App to HAL Code Flow

===================== GPS :: Flow from FW to HAL ===========================
App ==> FW java ==> JNI ==> HAL ==> kernel

Framework Java:-

/frameworks/base/services/core/java/com/android/server/location/GpsLocationProvider.java

Code:-
public class GpsLocationProvider implements LocationProviderInterface {
private native void native_inject_time(long time, long timeReference, int uncertainty);
}

*********************************************************************************
JNI Layer:-
/frameworks/base/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
Code:-
/* Native method registration Start */
static JNINativeMethod sMethods[] = {
{"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
......
}

Above method once registered java can call these methods,
int register_android_server_location_GpsLocationProvider(JNIEnv* env)
{
return jniRegisterNativeMethods(
env,
"com/android/server/location/GpsLocationProvider",
sMethods,
NELEM(sMethods));
}
/* Native method registration End */

/* Get the HAL module here start */
    err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);

/* Search the HAl module with the below macro name */
/hardware/libhardware/include/hardware/gps.h
#define GPS_HARDWARE_MODULE_ID "gps"

/* Call HAL module device open */
err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);

/* The below open method will get called */
loc_api/libloc_api_50001/gps.c
static struct hw_module_methods_t gps_module_methods = {
.open = open_gps
};
gps_device_t* gps_device = (gps_device_t *)device;
    sGpsInterface = gps_device->get_gps_interface(gps_device);

*********************************************************************************
HAL Layer:-

[1]
/hardware/qcom/gps/msm8084/loc_api/libloc_api_50001/loc.cpp
extern "C" const GpsInterface* get_gps_interface() {

return &sLocEngInterface; // See below the
}

// Defines the GpsInterface in gps.h
static const GpsInterface sLocEngInterface =
{
   sizeof(GpsInterface),
   loc_init,
   loc_start,
   loc_stop,
   loc_cleanup,
   loc_inject_time,
   loc_inject_location,
   loc_delete_aiding_data,
   loc_set_position_mode,
   loc_get_extension
};
The above structure is defined in hardware/libhardware/include/hardware/gps.h

Now when u call sGpsInterface->init(&sGpsCallbacks) from JNI above loc_init() fn will get called

========================================================================

Friday, August 5, 2016

I.MX socinitilization & how platform data is populated in platform device data from DT

Pre-condition:- All data are passed from DT.


Initial Flow:-
(kernel_init) from [<8000e4d8>] (ret_from_fork+0x14/0x20)
(kernel_init_freeable) from [<803ffb1c>] (kernel_init+0x18/0xf4)
(do_one_initcall) from [<8056cc04>] (kernel_init_freeable+0x104/0x1d0)
(customize_machine) from [<80008904>] (do_one_initcall+0xa4/0x118)
(imx6q_init_machine) from [<8056d938>] (customize_machine+0x24/0x48)
(of_platform_populate) from [<80577604>] (imx6q_init_machine+0x64/0x27c)
(of_platform_bus_create) from [<80361c2c>] (of_platform_populate+0x70/0xa4)
(of_platform_device_create_pdata) from [<80361b3c>] (of_platform_bus_create+0x100/0x180)
(of_device_alloc) from [<803619e0>] (of_platform_device_create_pdata+0x40/0x9c)
(of_device_make_bus_id) from [<8036198c>] (of_device_alloc+0x130/0x144)

We will see what is done in imx6 machine init (static void __init imx6q_init_machine(void)) step by step,

[1]
Check the CPU type, revision & print it,
          Code:-
                    if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_2_0)


[2]
Then comes soc device init (parent = imx_soc_device_init();) Here parent device is soc.

    [A] Allcoate memory for soc device attribute,
           Code:-
                     soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);

    [B] Read the model property from DT & store it in SOC machine type.
          Code:-
                     ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
          DT Code:-
                           model = "Freescale i.MX6 Solo/Dual Lite Rochester Orinoco Board";
                           compatible = "fsl,imx6dl-sabresd", "fsl,imx6dl";
   
    [C] Assign the SOC ID, revision in device attribute. 

    [D] Register the device with the system. Kobject (sys entry) will be created. As part of device                    register, the below device vailables are initialized.
          Code:-
                    soc_dev->attr = soc_dev_attr;
                    soc_dev->dev.bus = &soc_bus_type;
                    soc_dev->dev.groups = soc_attr_groups;
                    soc_dev->dev.release = soc_release;
                    dev_set_name(&soc_dev->dev, "soc%d", soc_dev->soc_dev_num);


[3] Then read all the platform devices from DT & populate it in platform device data.
       Code:-
                 of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);


of_platform_populate() - Populate platform_devices from device tree data
 * @root: parent of the first level to probe or NULL for the root of the tree
 * @matches: match table, NULL to use the default
 * @lookup: auxdata table for matching id and platform_data with device nodes
 * @parent: parent to hook devices from, NULL for toplevel
 *
 * Similar to of_platform_bus_probe(), this function walks the device tree
 * and creates devices from nodes.  It differs in that it follows the modern
 * convention of requiring all device nodes to have a 'compatible' property,
 * and it is suitable for creating devices which are children of the root
 * node (of_platform_bus_probe will only create children of the root which
 * are selected by the @matches argument).


During particular driver probe these platform data will be passed as a parameter.

For example touchscreen probe:-
Code:-
static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)

The client data will be populated from below DT, as part of of_platform_populate.

DT Code:-
       atmel_mxt_ts@4b {
                compatible = "atmel,atmel_mxt_ts";
                reg = <0x4b>;
                gpio_mxt449t_rst = <&gpio1 23 0>;
                interrupt-parent = <&gpio1>;
                interrupts = <24 0>;
                gpio_intr = <&gpio1 24 0>;
                status = "okay";
        };