protected override void initializeReports()
    {
        reports = new IntPtr[maxNumberOfReports];
        VRPNAnalogReport report = new VRPNAnalogReport();

        report.num_channel = MAX_ANALOG_CHANNELS;
        report.channel     = new double[MAX_ANALOG_CHANNELS];
        for (int i = 0; i < maxNumberOfReports; i++)
        {
            reports[i] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VRPNAnalogReport)));
            // Copy the report struct to unmanaged memory (reports array)
            Marshal.StructureToPtr(report, reports[i], true);
        }
    }
    // Update is called once per frame
    void Update()
    {
        if (!initialized && !startDevice())
        {
            return;
        }

        GameObject lb = gameObject;

        if (previousAxisInverted != axisInverted)
        {
            invertAxis();
            previousAxisInverted = axisInverted;
        }

        rot = Vector3.zero;

        if (VRPNAnalogNumReports(deviceName) > 0)
        {
            int num = maxNumberOfReports;
            VRPNAnalogReports(deviceName, reports, ref num, IntPtr.Zero, true);
            VRPNAnalogReport[] reps = new VRPNAnalogReport[num];

            int     i;
            Vector3 pos = Vector3.zero;
            for (i = 0; i < num; i++)
            {
                reps[i] = (VRPNAnalogReport)Marshal.PtrToStructure(reports[i], typeof(VRPNAnalogReport));
                if (reps[i].num_channel == 6)
                {
                    Vector3 cpos = new Vector3((float)reps[i].channel[0], (float)reps[i].channel[2], (float)reps[i].channel[1]);                     // Revert y and z axis
                    Vector3 crot = new Vector3(-(float)reps[i].channel[3], (float)reps[i].channel[5], (float)reps[i].channel[4]);

                    pos += cpos;
                    rot += crot;
                }
            }

            // Average position on the number of reports
            pos /= num;

            // Multiply by invertion vector
            // Invertion vector is set to the desired configuration by clicking a GUI checkbox
            pos.x *= invertionVector.x;
            pos.y *= invertionVector.y;
            pos.z *= invertionVector.z;

            // Average rotation on the number of reports
            rot /= num;
            rot  = -rot;            // Invert rotation

            // Dead center
            if ((pos.x > -deadCenterThreshold && pos.x < deadCenterThreshold))
            {
                pos.x = 0;
            }

            if ((pos.y > -deadCenterThreshold && pos.y < deadCenterThreshold))
            {
                pos.y = 0;
            }

            if ((pos.z > -deadCenterThreshold && pos.z < deadCenterThreshold))
            {
                pos.z = 0;
            }

            xoffset  += pos.x * xspeed;
            yoffset  += pos.y * yspeed;
            distance += pos.z * zspeed;
        }
    }