windows: remove total fds (256) limitations

When queue more usb requests, and more devices working at the same time
256's limitation is easy to reach.

This patch remove such limitation of windows version.

dymatic allocate map fd_table.
each time increase 256 entry if request more fds.

Closes #592

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nathan Hjelm <hjelmn@google.com>
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
index 5c57099..5282e7d 100644
--- a/libusb/os/poll_windows.c
+++ b/libusb/os/poll_windows.c
@@ -54,7 +54,32 @@
 };
 
 static usbi_mutex_static_t fd_table_lock = USBI_MUTEX_INITIALIZER;
-static struct file_descriptor *fd_table[MAX_FDS];
+
+static struct file_descriptor **fd_table;
+static size_t fd_count;
+static size_t fd_size;
+#define INC_FDS_EACH 256
+
+static void usbi_dec_fd_table()
+{
+	fd_count--;
+	if (fd_count == 0) {
+		free(fd_table);
+		fd_table = NULL;
+	}
+}
+
+static void smart_realloc_fd_table_space(int inc)
+{
+	if (fd_count + inc > fd_size) {
+		struct file_descriptor **p = (struct file_descriptor *)realloc(fd_table, (fd_size + INC_FDS_EACH) * sizeof(struct file_descriptor *));
+		if (p != NULL) {
+			memset(p + fd_size, 0, INC_FDS_EACH * sizeof(struct file_descriptor *));
+			fd_size += INC_FDS_EACH;
+			fd_table = p;
+		}
+	}
+}
 
 static struct file_descriptor *create_fd(enum fd_type type)
 {
@@ -101,15 +126,19 @@
 		return INVALID_WINFD;
 
 	usbi_mutex_static_lock(&fd_table_lock);
-	for (wfd.fd = 0; wfd.fd < MAX_FDS; wfd.fd++) {
+
+	smart_realloc_fd_table_space(1);
+
+	for (wfd.fd = 0; wfd.fd < fd_size; wfd.fd++) {
 		if (fd_table[wfd.fd] != NULL)
 			continue;
 		fd_table[wfd.fd] = fd;
+		fd_count++;
 		break;
 	}
 	usbi_mutex_static_unlock(&fd_table_lock);
 
-	if (wfd.fd == MAX_FDS) {
+	if (wfd.fd == fd_size) {
 		free_fd(fd);
 		return INVALID_WINFD;
 	}
@@ -138,7 +167,8 @@
 	for (n = 0; n < nfds; ++n) {
 		fd = fd_table[fds[n].fd];
 		fd->refcount--;
-		if (fd->refcount == 0)
+		//FD_TYPE_PIPE map fd to two _fd
+		if (fd->refcount == 0 || (fd->refcount == 1 && fd->type == FD_TYPE_PIPE))
 		{
 			if (fd->type == FD_TYPE_PIPE) {
 				// InternalHigh is our reference count
@@ -150,6 +180,7 @@
 				free_fd(fd);
 			}
 			fd_table[fds[n].fd] = NULL;
+			usbi_dec_fd_table();
 		}
 	}
 	usbi_mutex_static_unlock(&fd_table_lock);
@@ -176,7 +207,7 @@
 			continue;
 		}
 
-		if ((fds[n].fd >= 0) && (fds[n].fd < MAX_FDS))
+		if ((fds[n].fd >= 0) && (fds[n].fd < fd_size))
 			fd = fd_table[fds[n].fd];
 		else
 			fd = NULL;
@@ -243,14 +274,16 @@
 {
 	struct file_descriptor *fd;
 
-	if (_fd < 0 || _fd >= MAX_FDS)
+	if (_fd < 0 || _fd >= fd_size)
 		goto err_badfd;
 
 	usbi_mutex_static_lock(&fd_table_lock);
 	fd = fd_table[_fd];
 	fd->refcount--;
-	if(fd->refcount==0)
+	//FD_TYPE_PIPE map fd to two _fd
+	if(fd->refcount==0 || (fd->refcount == 1 && fd->type == FD_TYPE_PIPE))
 	{	fd_table[_fd] = NULL;
+		usbi_dec_fd_table();
 
 		if (fd->type == FD_TYPE_PIPE) {
 			// InternalHigh is our reference count
@@ -298,7 +331,9 @@
 
 	usbi_mutex_static_lock(&fd_table_lock);
 	do {
-		for (i = 0; i < MAX_FDS; i++) {
+		smart_realloc_fd_table_space(2);
+
+		for (i = 0; i < fd_size; i++) {
 			if (fd_table[i] != NULL)
 				continue;
 			if (r_fd == -1) {
@@ -309,16 +344,20 @@
 			}
 		}
 
-		if (i == MAX_FDS)
+		if (i == fd_size)
 			break;
 
 		fd_table[r_fd] = fd;
 		fd_table[w_fd] = fd;
 
+		fd->refcount++; //this fd reference twice for r and w.
+
+		fd_count += 2;
+
 	} while (0);
 	usbi_mutex_static_unlock(&fd_table_lock);
 
-	if (i == MAX_FDS) {
+	if (i == fd_size) {
 		free_fd(fd);
 		errno = EMFILE;
 		return -1;
@@ -339,7 +378,7 @@
 
 	UNUSED(buf);
 
-	if (fd < 0 || fd >= MAX_FDS)
+	if (fd < 0 || fd >= fd_size)
 		goto err_out;
 
 	if (count != sizeof(unsigned char)) {
@@ -377,7 +416,7 @@
 
 	UNUSED(buf);
 
-	if (fd < 0 || fd >= MAX_FDS)
+	if (fd < 0 || fd >= fd_size)
 		goto err_out;
 
 	if (count != sizeof(unsigned char)) {
diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h
index a9a3909..314853e 100644
--- a/libusb/os/poll_windows.h
+++ b/libusb/os/poll_windows.h
@@ -41,8 +41,6 @@
 
 #define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
 
-#define MAX_FDS     256
-
 #define POLLIN      0x0001    /* There is data to read */
 #define POLLPRI     0x0002    /* There is urgent data to read */
 #define POLLOUT     0x0004    /* Writing now will not block */
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 78b74e0..80acfb4 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11384
+#define LIBUSB_NANO 11385