private void runReadOnBackground() { m_SyncStart.waitAndSync(); while (!m_StopThread) { // In Linux read() from a HID device we always try to read at least as many bytes as there can // be in a report // the kernel will return with the actual number of bytes in the report (plus one if numbered // reports are used) // and the data will be preceded with the report number if and only if numbered reports are // used, which is // kind of stupid because then we need to know this and to know that it is necessary to (be // able to!) read // the HID descriptor AND parse it. I like the Mac OS and Windows ways better, what a mess the // world is! int bytes_read = read(m_DeviceHandle, m_InputReportBytes, m_InputReportBytes.length); if (m_InputReportListener != null) { byte reportID = 0; if (m_UsesNumberedReports) { reportID = m_InputReportBytes[0]; bytes_read--; System.arraycopy(m_InputReportBytes, 1, m_InputReportBytes, 0, bytes_read); } m_InputReportListener.onInputReport(this, reportID, m_InputReportBytes, bytes_read); } } m_SyncShutdown.waitAndSync(); }
/* package */ HidDevice(String path, Frontend frontend) throws IOException { m_Frontend = frontend; udev udev = udev_new(); udev_device raw_dev = udev_device_new_from_syspath(udev, path); String dev_path = udev_device_get_devnode(raw_dev); udev_unref(udev); m_HidDeviceInfo = new HidDeviceInfo(path); // OPEN HERE // m_DeviceHandle = open(dev_path, O_RDWR); // If we have a good handle, return it. if (m_DeviceHandle <= 0) throw new IOException("open() failed, errno " + Native.getLastError()); // Get the report descriptor int[] desc_size = {0}; int res; hidraw_report_descriptor rpt_desc = new hidraw_report_descriptor(); // Get Report Descriptor Size res = ioctl(m_DeviceHandle, HIDIOCGRDESCSIZE, desc_size); if (res < 0) // FIXME ERROR HANDLING throw new IOException("ioctl(...HIDIOCGRDESCSIZE..) failed"); // perror("HIDIOCGRDESCSIZE"); // Get Report Descriptor rpt_desc.size = desc_size[0]; res = ioctl(m_DeviceHandle, HIDIOCGRDESC, rpt_desc); if (res < 0) throw new IOException("ioctl(...HIDIOCGRDESC..) failed"); // Determine if this device uses numbered reports. m_UsesNumberedReports = uses_numbered_reports(rpt_desc.value, rpt_desc.size); // --------------- // Magic here, assume that no HID device ever uses reports longer than 4kB m_InputReportBytes = new byte[4096 + 1]; m_OutputReportBytes = new byte[4096 + 1]; m_SyncStart = new SyncPoint(2); m_SyncShutdown = new SyncPoint(2); m_Thread = new Thread( new Runnable() { @Override public void run() { try { runReadOnBackground(); } catch (Exception e) { e.printStackTrace(); } } }, m_HidDeviceInfo.getPath()); m_Thread.start(); m_SyncStart.waitAndSync(); }
@Override public synchronized void close() { if (!m_Open) throw new IllegalStateException("device not open"); m_StopThread = true; UdevLibrary.close(m_DeviceHandle); m_Thread.interrupt(); m_SyncShutdown.waitAndSync(); m_Frontend.closeDevice(this); m_Open = false; }