2013-03-12 3 views
1

저는 C와 함께 HIDAPI로 작업 중이며 interop을 사용하여 HIDAPI와 통신하도록 Mono를 얻으려고합니다. 나는 많은 검색을했고 HIDAPI를 OS X에서 Mono와 함께 작업 한 사람을 찾을 수 없었습니다.OS X의 HIDAPI 옵션

HIDAPI를 사용하는 출력을 로컬 가상으로 리디렉션 할 수 있는지 아는 사람은 누구입니까? 직렬 포트를 누른 다음 Mono가 직렬 포트에서 읽었습니까?

다른 옵션으로 Arduino leonardo 나 Circuits @ Home USB Host Shield와 같은 것을 사용할 수 있는지 알고 싶습니까?

적어도 모노에서 PInvoke를 분류 할 수있을 때까지.

감사합니다.

답변

0

Arduino Leonardo는 USB 호스트로 작동 할 수 없습니다.

그러나 원칙적으로 장치가 장치 측에서 CDC 직렬 포트로 작동하도록하고 HID 장치에 대한 호스트 USB로 작동하도록 할 수 있습니다.

또는 HIDAPI 단계를 건너 뛰고 HidSharp을 사용할 수 있습니다. :) MacOS X 네이티브 API에 직접 P/Invoke 할 것입니다.

희망이 내가 내 인생의 소스를 찾을 수 있지만,

제임스

2

내가 발견하고 다른 곳에서이 코드를 적용 할 수 있습니다. 누군가가 알고있는 경우 알려 주시면 적절한 속성을 부여하고 링크 할 수 있습니다. Windows와 OS X 모두 나를 위해 잘 작동했습니다. 분명히 각 플랫폼에 대해 hidapi를 제작해야합니다.

using System; 
using System.Globalization; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Text; 
using System.Threading; 

namespace HidApiCommunicationLayer 
{ 
    internal class HidApiInteropCommLayer 
    { 
     #region Interop 

#if WINDOWS 
     private const string HIDAPI_DLL = "hidapi.dll"; 
#else 
     private const string HIDAPI_DLL = "hidapi.dylib"; 
#endif 

     protected IntPtr _device; 

     private Object _locker = new object(); 

     public bool IsOpen() 
     { 
      return _device != IntPtr.Zero; 
     } 

     public void Open(ushort vid, ushort hid, string serial) 
     { 
      if (_device != IntPtr.Zero) throw new Exception("a device is already opened; close it first."); 
      IntPtr ret = hid_open(vid, hid, serial); 
      _device = ret; 
      //if (_device != IntPtr.Zero) 
      // hid_set_nonblocking(_device, true); 
     } 

     public int Read(byte[] buffer, int length) 
     { 
      lock (_locker) 
      { 
       AssertValidDev(); 
       int ret = hid_read_timeout(_device, buffer, (uint)length, 1); 
       if (ret < 0) 
        throw new Exception("Failed to Read."); 

       return ret; 
      } 
     } 

     public void Close() 
     { 
      AssertValidDev(); 
      hid_close(_device); 
      _device = IntPtr.Zero; 
     } 

     public int ExitHidAPI() 
     { 
      return hid_exit(); 
     } 

     public String GetProductString() 
     { 
      AssertValidDev(); 
      byte[] buf = new byte[1000]; 
      int ret = HidApiInteropCommLayer.hid_get_product_string(_device, buf, (uint)(buf.Length/4) - 1); 
      if (ret < 0) 
       throw new Exception("failed to receive product string"); 
      return EncodeBuffer(buf); 
     } 

     public String GetManufacturerString() 
     { 
      AssertValidDev(); 
      byte[] buf = new byte[1000]; 
      int ret = HidApiInteropCommLayer.hid_get_manufacturer_string(_device, buf, (uint)(buf.Length/4) - 1); 
      if (ret < 0) 
       throw new Exception("failed to receive manufacturer string"); 
      return EncodeBuffer(buf); 
     } 

     public int GetFeatureReport(byte[] buffer, int length) 
     { 
      AssertValidDev(); 
      int ret = hid_get_feature_report(_device, buffer, (uint)length); 
      if (ret < 0) 
       throw new Exception("failed to get feature report"); 
      return ret; 
     } 

     public int SendFeatureReport(byte[] buffer) 
     { 
      int ret = hid_send_feature_report(_device, buffer, (uint)buffer.Length); 
      //if (ret < 0) 
      // throw new Exception ("failed to send feature report"); 
      return ret; 
     } 

     public int Write(byte[] buffer) 
     { 
      lock (_locker) 
      { 
       AssertValidDev(); 
       int ret = hid_write(_device, buffer, HID_MAX_PACKET_SIZE + 1); 
       //if (ret < 0) 
       // Custom logging 
       return ret; 
      } 
     } 

     public String Error() 
     { 
      AssertValidDev(); 
      IntPtr ret = hid_error(_device); 
      return Marshal.PtrToStringAuto(ret); 
     } 

     public string GetIndexedString(int index) 
     { 
      AssertValidDev(); 
      byte[] buf = new byte[1000]; 
      int ret = HidApiInteropCommLayer.hid_get_indexed_string(_device, index, buf, (uint)(buf.Length/4) - 1); 
      if (ret < 0) 
       throw new Exception("failed to receive indexed string"); 
      return EncodeBuffer(buf); 
     } 

     public string GetSerialNumberString() 
     { 
      AssertValidDev(); 
      byte[] buf = new byte[1000]; 
      int ret = HidApiInteropCommLayer.hid_get_serial_number_string(_device, buf, (uint)(buf.Length/4) - 1); 
      if (ret < 0) 
       throw new Exception("failed to receive serial number string"); 
      return EncodeBuffer(buf); 
     } 

     private string EncodeBuffer(byte[] buffer) 
     { 
      return Encoding.Unicode.GetString(buffer).Trim('\0'); 
     } 

     private void AssertValidDev() 
     { 
      if (_device == IntPtr.Zero) throw new Exception("No device opened"); 
     } 

     #region DllImports 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_read(IntPtr device, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] data, uint length); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_read_timeout(IntPtr device, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] data, uint length, int timeout); 

     [DllImport(HIDAPI_DLL)] 
     private static extern IntPtr hid_open(ushort vid, ushort pid, [MarshalAs(UnmanagedType.LPWStr)] string serial); 

     [DllImport(HIDAPI_DLL)] 
     private static extern void hid_close(IntPtr device); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_init(); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_exit(); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_get_product_string(IntPtr device, [Out] byte[] _string, uint length); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_get_manufacturer_string(IntPtr device, [Out] byte[] _string, uint length); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_get_feature_report(IntPtr device, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] data, uint length); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_get_serial_number_string(IntPtr device, [Out] byte[] serial, uint maxlen); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_get_indexed_string(IntPtr device, int string_index, [Out] byte[] _string, uint maxlen); 

     [DllImport(HIDAPI_DLL)] 
     private static extern IntPtr hid_error(IntPtr device); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_send_feature_report(IntPtr device, [In, MarshalAs(UnmanagedType.LPArray)] byte[] data, uint length); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_set_nonblocking(IntPtr device, [In, MarshalAs(UnmanagedType.SysInt)] bool nonblock); 

     [DllImport(HIDAPI_DLL)] 
     private static extern int hid_write(IntPtr device, [In, MarshalAs(UnmanagedType.LPArray)] byte[] data, uint length); 

     [DllImport(HIDAPI_DLL)] 
     private static extern IntPtr hid_open_path([In, MarshalAs(UnmanagedType.LPStr)] string path); 

     #endregion DllImports 

     #endregion Interop 

     #region Constructors 

     public static HidApiInteropCommLayer GetDevice(ushort vid, ushort pid) 
     { 
      try 
      { 
       HidApiInteropCommLayer layer = new HidApiInteropCommLayer(); 
       layer.Open(vid, pid, null); 
       return layer._device == IntPtr.Zero ? null : layer; 
      } 
      catch (System.BadImageFormatException fx) 
      { 
       //Custom logging 
       return null; 
      } 
      catch (Exception ex) 
      { 
       //Custom logging 
       return null; 
      } 
     } 

     #endregion Constructors 

     private const int HID_MAX_PACKET_SIZE = 1024; 

     #region ICommunicationLayer 

     public void Init() 
     { 
      try 
      { 
       if (IsOpen()) 
       { 
        ContinueReadProcessing = true; 
        ReadThread = new Thread(new ThreadStart(ReadLoop)); 
        ReadThread.Name = "HidApiReadThread"; 
        ReadThread.Start(); 
       } 
       else 
       { 
        Disconnect(); 
       } 
      } 
      catch (Exception ex) 
      { 
       //Custom logging 
       throw; 
      } 
     } 

     public bool SendData(byte[] data) 
     { 
      try 
      { 
       MemoryStream stream = new MemoryStream(HID_MAX_PACKET_SIZE + 1); 
       stream.WriteByte(0); 
       stream.Write(data, 0, HID_MAX_PACKET_SIZE); 
       int ret = Write(stream.ToArray()); 
       if (ret >= 0) 
        return true; 
       else 
       { 
        return false; 
       } 
      } 
      catch (Exception ex) 
      { 
       //Custom logging 
       return false; 
      } 
     } 

     public event EventHandler<DataEventArgs> DataReceived; 

     public event EventHandler Disconnected; 

     public void Start() 
     { 
      ContinueReadProcessing = true; 
     } 

     public void Stop() 
     { 
      Disconnect(); 
     } 

     #endregion ICommunicationLayer 

     private Thread ReadThread = null; 

     protected volatile bool ContinueReadProcessing = true; 

     private void ReadLoop() 
     { 
      var culture = CultureInfo.InvariantCulture; 
      Thread.CurrentThread.CurrentCulture = culture; 
      Thread.CurrentThread.CurrentUICulture = culture; 
      Thread.CurrentThread.Priority = ThreadPriority.AboveNormal; 

      while (ContinueReadProcessing) 
      { 
       try 
       { 
        byte[] report = new byte[HID_MAX_PACKET_SIZE]; 

        var result = Read(report, HID_MAX_PACKET_SIZE); 

        if (result > 0) 
        { 
         DataReceived(this, new DataEventArgs(report)); 
        } 
        else if (result < 0) 
        { 
         Disconnect(); 
        } 
       } 
       catch (Exception ex) 
       { 
        Disconnect(); 
       } 

       Thread.Sleep(1); 
      } 
     } 

     private void Disconnect() 
     { 
      ContinueReadProcessing = false; 
      Disconnected(this, EventArgs.Empty); 
     } 

     #region IDisposable Members 

     public void Dispose() 
     { 
      ContinueReadProcessing = false; 
      ReadThread.Join(500); 
      if (ReadThread.IsAlive) 
      { 
       ReadThread.Abort(); 
      } 

      if (IsOpen()) 
       Close(); 
      int res = ExitHidAPI(); 
     } 

     #endregion IDisposable Members 
    } 

    internal class Utf32Marshaler : ICustomMarshaler 
    { 
     private static Utf32Marshaler instance = new Utf32Marshaler(); 

     public static ICustomMarshaler GetInstance(string s) 
     { 
      return instance; 
     } 

     public void CleanUpManagedData(object o) 
     { 
     } 

     public void CleanUpNativeData(IntPtr pNativeData) 
     { 
      Marshal.FreeHGlobal(pNativeData); 
      //UnixMarshal.FreeHeap(pNativeData); 
     } 

     public int GetNativeDataSize() 
     { 
      return IntPtr.Size; 
     } 

     public IntPtr MarshalManagedToNative(object obj) 
     { 
      string s = obj as string; 
      if (s == null) 
       return IntPtr.Zero; 
      return Marshal.StringToHGlobalAuto(s); 
     } 

     public object MarshalNativeToManaged(IntPtr pNativeData) 
     { 
      return Marshal.PtrToStringAuto(pNativeData); 
     } 
    } 

    public class DataEventArgs : EventArgs 
    { 
     public DataEventArgs(byte[] data) 
     { 
      Data = data; 
     } 

     public byte[] Data { get; private set; } 
    } 
}