//		[DllImport(hid)]
//		internal static extern long AllocateHIDObjectFromIOHIDDeviceRef(IOHIDDeviceRef inIOHIDDeviceRef);

        internal static long AllocateHIDObjectFromIOHIDDeviceRef(IOHIDDeviceRef inIOHIDDeviceRef)
        {
            long result = 0;

            if (inIOHIDDeviceRef != IntPtr.Zero)
            {
                // Set up the matching criteria for the devices we're interested in.
                // We are interested in instances of class IOHIDDevice.
                // matchingDict is consumed below( in IOServiceGetMatchingService )
                // so we have no leak here.
                //CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOHIDDeviceKey);
                byte[] utf8Bytes = Encoding.UTF8.GetBytes(Native.kIOHIDDeviceKey);
                //char[] charArr=Native.IOHIDDeviceKey.ToCharArray(
                IntPtr bufferIntPtr = Marshal.AllocHGlobal(utf8Bytes.Length);
                Marshal.Copy(utf8Bytes, 0, bufferIntPtr, utf8Bytes.Length);



                IntPtr matchingDictRef = Native.IOServiceMatching(bufferIntPtr);
                matchingDictRef = Native.IOServiceMatching(Native.CFSTR(Native.kIOHIDDeviceKey));
                Marshal.FreeHGlobal(bufferIntPtr);



                if (matchingDictRef != IntPtr.Zero)
                {
                    Native.CFDictionary dict = new Native.CFDictionary(matchingDictRef);

                    // Add a key for locationID to our matching dictionary.  This works for matching to
                    // IOHIDDevices, so we will only look for a device attached to that particular port
                    // on the machine.

                    IntPtr tCFTypeRef = Native.IOHIDDeviceGetProperty(inIOHIDDeviceRef, Native.CFSTR(Native.kIOHIDLocationIDKey));

                    if (tCFTypeRef != IntPtr.Zero)
                    {
                        dict[Native.kIOHIDLocationIDKey] = tCFTypeRef;



                        //CFDictionaryAddValue (matchingDictRef, CFSTR (Native.IOHIDLocationIDKey), tCFTypeRef);
                        // CFRelease( tCFTypeRef ); // don't release objects that we "Get".

                        // IOServiceGetMatchingService assumes that we already know that there is only one device
                        // that matches.  This way we don't have to do the whole iteration dance to look at each
                        // device that matches.  This is a new API in 10.2
                        //result = Native.IOServiceGetMatchingService (kIOMasterPortDefault, matchingDictRef);
                        result = Native.IOServiceGetMatchingService(IntPtr.Zero, matchingDictRef);
                    }

                    // Note: We're not leaking the matchingDict.
                    // One reference is consumed by IOServiceGetMatchingServices
                }
            }
            return(result);
        }
        void RemoveDevice(IOHIDDeviceRef deviceRef)
        {
            if (deviceRef == IntPtr.Zero)
            {
                Debug.LogWarning("IOHIDeviceRef equal to IntPtr.Zero");
                return;
            }


            int product_id = (int)(new Native.CFNumber(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDProductIDKey)))).ToInteger();



            int vendor_id = (int)(new Native.CFNumber(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDVendorIDKey)))).ToInteger();


            int    location  = (int)(new Native.CFNumber(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDLocationIDKey)))).ToInteger();
            string transport = (new Native.CFString(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDTransportKey)))).ToString();

            string path = String.Format("{0:s}_{1,4:X}_{2,4:X}_{3:X}",
                                        transport, vendor_id, product_id, location);          //"%s_%04hx_%04hx_%x"


            lock (syncRoot) {
                if (!__Generics.ContainsKey(path))
                {
                    return;
                }

                HIDDevice hidDevice = __Generics [path];


                Generics.Remove(path);

                Debug.Log("Device " + hidDevice.index + " PID:" + hidDevice.PID + " VID:" + hidDevice.VID + " Disconnected");
            }


            Debug.Log("Try to unshedule,unregister and close device");
            Native.IOHIDDeviceUnscheduleFromRunLoop(deviceRef, RunLoop, InputLoopMode);
            Native.IOHIDDeviceRegisterInputValueCallback(deviceRef, IntPtr.Zero, IntPtr.Zero);
            Native.IOHIDDeviceRegisterRemovalCallback(deviceRef, null, IntPtr.Zero);

            Native.IOHIDDeviceClose(deviceRef, (int)Native.IOHIDOptionsType.kIOHIDOptionsTypeNone);



            this.DeviceDisconnectEvent(this, new DeviceEventArgs <string>(path));
        }
        /// <summary>
        /// Devices the added.
        /// </summary>
        /// <param name="context">Context.</param>
        /// <param name="res">Res.</param>
        /// <param name="sender">Sender.</param>
        /// <param name="device">Device.</param>
        void HidDeviceAdded(IntPtr context, IOReturn res, IntPtr sender, IOHIDDeviceRef deviceRef)
        {
            //IOReturn success = Native.IOHIDDeviceOpen (device, (int)Native.IOHIDOptionsType.kIOHIDOptionsTypeNone);

            if (deviceRef == IntPtr.Zero)
            {
                Debug.LogWarning("IOHIDeviceRef of Added Device equal to IntPtr.Zero");
                return;
            }



            int product_id = (int)(new Native.CFNumber(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDProductIDKey)))).ToInteger();



            int vendor_id = (int)(new Native.CFNumber(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDVendorIDKey)))).ToInteger();

            string manufacturer = (new Native.CFString(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDManufacturerKey)))).ToString();
            string description  = manufacturer + " " + (new Native.CFString(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDProductKey)))).ToString();

            int    location  = (int)(new Native.CFNumber(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDLocationIDKey)))).ToInteger();
            string transport = (new Native.CFString(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDTransportKey)))).ToString();

            string path = String.Format("{0:s}_{1,4:X}_{2,4:X}_{3:X}",
                                        transport, vendor_id, product_id, location);                  //"%s_%04hx_%04hx_%x"

            //string serial=(new Native.CFString(Native.IOHIDDeviceGetProperty(deviceRef, Native.CFSTR(Native.kIOHIDSerialNumberKey)))).ToString();

            if (Generics.ContainsKey(path))
            {
                return;
            }

            GenericHIDDevice hidDevice;
            IDevice          joyDevice = null;

            // IDevice<IAxisDetails, IButtonDetails, IDeviceExtension> joyDevice = null;


            ///loop thru specific drivers and attach the driver to device if compatible
            if (__drivers != null)
            {
                foreach (var driver in __drivers)
                {
                    hidDevice = new GenericHIDDevice(GetIndexForDeviceWithID(path), vendor_id, product_id, path, deviceRef, this, path, description);

                    if ((joyDevice = driver.ResolveDevice(hidDevice)) != null)
                    {
                        lock (syncRoot){
                            __Generics[path] = hidDevice;
                        }

                        //if (context != IntPtr.Zero) {
                        Native.IOHIDDeviceRegisterRemovalCallback(deviceRef, HandleDeviceRemoved, context);
                        //}else{
                        //	Debug.LogWarning("IOHIDDeviceRegisterRemovalCallback not registerd cos of Context IntPtr.Zero");
                        //}

                        Debug.Log("Device PID:" + joyDevice.PID + " VID:" + joyDevice.VID + "[" + joyDevice.Name + "] attached to " + driver.GetType().ToString());

                        break;
                    }
                }
            }

            if (joyDevice == null)
            {    //set default driver as resolver if no custom driver match device
                hidDevice = new GenericHIDDevice(GetIndexForDeviceWithID(path), vendor_id, product_id, path, deviceRef, this, path, description);


                if ((joyDevice = defaultDriver.ResolveDevice(hidDevice)) != null)
                {
                    lock (syncRoot){
                        __Generics[path] = hidDevice;
                    }

                    //if (context != IntPtr.Zero) {
                    Native.IOHIDDeviceRegisterRemovalCallback(deviceRef, HandleDeviceRemoved, context);
                    //}else{
                    //	Debug.LogWarning("IOHIDDeviceRegisterRemovalCallback not registerd cos of Context IntPtr.Zero");
                    //}

                    Debug.Log("Device PID:" + joyDevice.PID + " VID:" + joyDevice.VID + "[" + joyDevice.Name + "] attached to " + defaultDriver.GetType().ToString());
                }
                else
                {
                    Debug.LogWarning("Device PID:" + product_id.ToString() + " VID:" + vendor_id.ToString() + " not found compatible driver on the system.Removed!");
                }
            }

            if (joyDevice != null)
            {
                this.DeviceConnectEvent(this, new DeviceEventArgs <IDevice>(joyDevice));
            }
        }