public List<String> getPortList() { Pattern p = JTermios.getPortNamePattern(this); char[] buffer; int size = 0; for (size = 16 * 1024; size < 256 * 1024; size *= 2) { buffer = new char[size]; int res = QueryDosDeviceW(null, buffer, buffer.length); if (res > 0) { // LinkedList<String> list = new LinkedList<String>(); int offset = 0; String port; while ((port = getString(buffer, offset)).length() > 0) { if (p.matcher(port).matches()) list.add(port); offset += port.length() + 1; } return list; } else { int err = GetLastError(); if (err != ERROR_INSUFFICIENT_BUFFER) { log = log && log(1, "QueryDosDeviceW() failed with GetLastError() = %d\n", err); return null; } } } log = log && log(1, "Repeated QueryDosDeviceW() calls failed up to buffer size %d\n", size); return null; }
public int select(int n, FDSet readfds, FDSet writefds, FDSet exceptfds, TimeVal timeout) { // long T0 = System.currentTimeMillis(); int ready = 0; LinkedList<Port> locked = new LinkedList<Port>(); try { try { LinkedList<Port> waiting = new LinkedList<Port>(); for (int fd = 0; fd < n; fd++) { boolean rd = FD_ISSET(fd, readfds); boolean wr = FD_ISSET(fd, writefds); FD_CLR(fd, readfds); FD_CLR(fd, writefds); if (rd || wr) { Port port = getPort(fd); if (port == null) return -1; try { port.lock(); locked.add(port); clearCommErrors(port); // check if there is data to be read, as WaitCommEvent // does check for only *new* data that and thus // might wait indefinitely if select() is called twice // without first reading away all data if (rd && port.m_COMSTAT.cbInQue > 0) { FD_SET(fd, readfds); ready++; } if (wr && port.m_COMSTAT.cbOutQue == 0) { FD_SET(fd, writefds); ready++; } if (!ResetEvent(port.m_SelOVL.hEvent)) port.fail(); int flags = 0; if (rd) flags |= EV_RXCHAR; if (wr) flags |= EV_TXEMPTY; if (!SetCommMask(port.m_Comm, flags)) port.fail(); if (WaitCommEvent(port.m_Comm, port.m_EventFlags, port.m_SelOVL)) { if (!GetOverlappedResult(port.m_Comm, port.m_SelOVL, port.m_SelN, false)) port.fail(); // actually it seems that overlapped // WaitCommEvent never returns true so we never get here ready = maskToFDSets(port, readfds, writefds, exceptfds, ready); } else { // FIXME if the port dies on us what happens if (GetLastError() != ERROR_IO_PENDING) port.fail(); waiting.add(port); } } catch (InterruptedException ie) { m_ErrNo = EINTR; return -1; } } } if (ready == 0) { int waitn = waiting.size(); if (waitn > 0) { HANDLE[] wobj = new HANDLE[waiting.size() * 2]; int i = 0; for (Port port : waiting) { wobj[i++] = port.m_SelOVL.hEvent; wobj[i++] = port.m_CancelWaitSema4; } int tout = timeout != null ? (int) (timeout.tv_sec * 1000 + timeout.tv_usec / 1000) : INFINITE; // int res = WaitForSingleObject(wobj[0], tout); int res = WaitForMultipleObjects(waitn * 2, wobj, false, tout); if (res == WAIT_TIMEOUT) { // work around the fact that sometimes we miss // events for (Port port : waiting) { clearCommErrors(port); int[] mask = {0}; if (!GetCommMask(port.m_Comm, mask)) port.fail(); if (port.m_COMSTAT.cbInQue > 0 && ((mask[0] & EV_RXCHAR) != 0)) { FD_SET(port.m_FD, readfds); log = log && log(1, "missed EV_RXCHAR event\n"); return 1; } if (port.m_COMSTAT.cbOutQue == 0 && ((mask[0] & EV_TXEMPTY) != 0)) { FD_SET(port.m_FD, writefds); log = log && log(1, "missed EV_TXEMPTY event\n"); return 1; } } } if (res != WAIT_TIMEOUT) { i = (res - WAIT_OBJECT_0) / 2; if (i < 0 || i >= waitn) throw new Fail(); Port port = waiting.get(i); if (!GetOverlappedResult(port.m_Comm, port.m_SelOVL, port.m_SelN, false)) port.fail(); ready = maskToFDSets(port, readfds, writefds, exceptfds, ready); } } else { if (timeout != null) nanoSleep(timeout.tv_sec * 1000000000L + timeout.tv_usec * 1000); else { m_ErrNo = EINVAL; return -1; } return 0; } } } catch (Fail f) { return -1; } } finally { for (Port port : locked) port.unlock(); } // long T1 = System.currentTimeMillis(); // System.err.println("select() " + (T1 - T0)); return ready; }