CVS: rdesktop constants.h,1.36,1.37 disk.c,1.39,1.40 proto.h,1.68,1.69 rdpdr.c,1.37,1.38 serial.c,1.20,1.21 types.h,1.21,1.22 xwin.c,1.178,1.179

Michael Gernoth <[email protected]>
Newsgroups gmane.network.rdesktop.cvs
Message-ID <[email protected]>
Update of /cvsroot/rdesktop/rdesktop
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12687

Modified Files:
	constants.h disk.c proto.h rdpdr.c serial.c types.h xwin.c 
Log Message:
Big serial- and disk-redirection update from
Andreas Flick <[email protected]>


Index: constants.h
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/constants.h,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** constants.h	27 Jun 2004 18:53:08 -0000	1.36
--- constants.h	3 Nov 2004 13:56:44 -0000	1.37
***************
*** 341,344 ****
--- 341,345 ----
  /* NT status codes for RDPDR */
  #define STATUS_SUCCESS			0x00000000
+ #define STATUS_NOT_IMPLEMENTED          0x00000001
  #define STATUS_PENDING                  0x00000103
  
***************
*** 359,362 ****
--- 360,364 ----
  #define STATUS_NOT_SUPPORTED            0xc00000bb
  #define STATUS_TIMEOUT                  0xc0000102
+ #define STATUS_NOTIFY_ENUM_DIR          0xc000010c
  #define STATUS_CANCELLED                0xc0000120
  
***************
*** 372,375 ****
--- 374,379 ----
  #define FILE_DIRECTORY_FILE             0x00000001
  #define FILE_NON_DIRECTORY_FILE         0x00000040
+ #define FILE_COMPLETE_IF_OPLOCKED       0x00000100
+ #define FILE_DELETE_ON_CLOSE            0x00001000
  #define FILE_OPEN_FOR_FREE_SPACE_QUERY  0x00800000
  

Index: disk.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/disk.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -C2 -d -r1.39 -r1.40
*** disk.c	28 Oct 2004 07:46:39 -0000	1.39
--- disk.c	3 Nov 2004 13:56:44 -0000	1.40
***************
*** 82,85 ****
--- 82,86 ----
  
  FILEINFO g_fileinfo[MAX_OPEN_FILES];
+ BOOL g_notify_stamp = False;
  
  typedef struct
***************
*** 91,94 ****
--- 92,96 ----
  } FsInfoType;
  
+ static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
  
  static time_t
***************
*** 329,333 ****
  	}
  
! 	//printf("Open: \"%s\"  flags: %u, accessmask: %u sharemode: %u create disp: %u\n", path, flags_and_attributes, accessmask, sharemode, create_disposition);
  
  	// Get information about file and set that flag ourselfs
--- 331,335 ----
  	}
  
! 	//printf("Open: \"%s\"  flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition);
  
  	// Get information about file and set that flag ourselfs
***************
*** 425,431 ****
--- 427,439 ----
  	if (dirp)
  		g_fileinfo[handle].pdir = dirp;
+ 	else
+ 		g_fileinfo[handle].pdir = NULL;
+ 
  	g_fileinfo[handle].device_id = device_id;
  	g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
+ 	g_fileinfo[handle].accessmask = accessmask;
  	strncpy(g_fileinfo[handle].path, path, 255);
+ 	g_fileinfo[handle].delete_on_close = False;
+ 	g_notify_stamp = True;
  
  	*phandle = handle;
***************
*** 440,451 ****
  	pfinfo = &(g_fileinfo[handle]);
  
! 	if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)
  	{
! 		closedir(pfinfo->pdir);
! 		//FIXME: Should check exit code
  	}
  	else
  	{
! 		close(handle);
  	}
  
--- 448,486 ----
  	pfinfo = &(g_fileinfo[handle]);
  
! 	g_notify_stamp = True;
! 
! 	rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
! 
! 	if (pfinfo->pdir)
  	{
! 		if (closedir(pfinfo->pdir) < 0)
! 		{
! 			perror("closedir");
! 			return STATUS_INVALID_HANDLE;
! 		}
! 
! 		if (pfinfo->delete_on_close)
! 			if (rmdir(pfinfo->path) < 0)
! 			{
! 				perror(pfinfo->path);
! 				return STATUS_ACCESS_DENIED;
! 			}
! 		pfinfo->delete_on_close = False;
  	}
  	else
  	{
! 		if (close(handle) < 0)
! 		{
! 			perror("close");
! 			return STATUS_INVALID_HANDLE;
! 		}
! 		if (pfinfo->delete_on_close)
! 			if (unlink(pfinfo->path) < 0)
! 			{
! 				perror(pfinfo->path);
! 				return STATUS_ACCESS_DENIED;
! 			}
! 
! 		pfinfo->delete_on_close = False;
  	}
  
***************
*** 478,482 ****
  		{
  			case EISDIR:
! 				return STATUS_FILE_IS_A_DIRECTORY;
  			default:
  				perror("read");
--- 513,520 ----
  		{
  			case EISDIR:
! 				/* Implement 24 Byte directory read ??
! 				   with STATUS_NOT_IMPLEMENTED server doesn't read again */
! 				/* return STATUS_FILE_IS_A_DIRECTORY; */
! 				return STATUS_NOT_IMPLEMENTED;
  			default:
  				perror("read");
***************
*** 601,608 ****
  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
  {
! 	uint32 length, file_attributes, ft_high, ft_low;
  	char newname[256], fullpath[256];
  	struct fileinfo *pfinfo;
- 
  	int mode;
  	struct stat filestat;
--- 639,645 ----
  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
  {
! 	uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
  	char newname[256], fullpath[256];
  	struct fileinfo *pfinfo;
  	int mode;
  	struct stat filestat;
***************
*** 612,615 ****
--- 649,653 ----
  
  	pfinfo = &(g_fileinfo[handle]);
+ 	g_notify_stamp = True;
  
  	switch (info_class)
***************
*** 671,675 ****
  				       ctime(&tvs.modtime));
  #endif
! 				if (utime(pfinfo->path, &tvs))
  					return STATUS_ACCESS_DENIED;
  			}
--- 709,713 ----
  				       ctime(&tvs.modtime));
  #endif
! 				if (utime(pfinfo->path, &tvs) && errno != EPERM)
  					return STATUS_ACCESS_DENIED;
  			}
***************
*** 729,751 ****
  			   DeleteFile set to FALSE should unschedule
  			   the delete. See
! 			   http://www.osronline.com/article.cfm?article=245. Currently,
! 			   we are deleting the file immediately. I
! 			   guess this is a FIXME. */
! 
! 			//in_uint32_le(in, delete_on_close);
  
! 			/* Make sure we close the file before
! 			   unlinking it. Not doing so would trigger
! 			   silly-delete if using NFS, which might fail
! 			   on FAT floppies, for example. */
! 			disk_close(handle);
  
! 			if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE))	// remove a directory
  			{
! 				if (rmdir(pfinfo->path) < 0)
! 					return STATUS_ACCESS_DENIED;
  			}
- 			else if (unlink(pfinfo->path) < 0)	// unlink a file
- 				return STATUS_ACCESS_DENIED;
  
  			break;
--- 767,780 ----
  			   DeleteFile set to FALSE should unschedule
  			   the delete. See
! 			   http://www.osronline.com/article.cfm?article=245. */
  
! 			in_uint32_le(in, delete_on_close);
  
! 			if (delete_on_close ||
! 			    (pfinfo->
! 			     accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
  			{
! 				pfinfo->delete_on_close = True;
  			}
  
  			break;
***************
*** 764,768 ****
  			/* prevents start of writing if not enough space left on device */
  			if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)
! 				if (stat_fs.f_bsize * stat_fs.f_bfree < length)
  					return STATUS_DISK_FULL;
  
--- 793,797 ----
  			/* prevents start of writing if not enough space left on device */
  			if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)
! 				if (stat_fs.f_bfree * stat_fs.f_bsize < length)
  					return STATUS_DISK_FULL;
  
***************
*** 781,792 ****
  }
  
  static FsInfoType *
  FsVolumeInfo(char *fpath)
  {
  
- #ifdef HAVE_MNTENT_H
  	FILE *fdfs;
- 	struct mntent *e;
  	static FsInfoType info;
  
  	/* initialize */
--- 810,929 ----
  }
  
+ NTSTATUS
+ disk_check_notify(NTHANDLE handle)
+ {
+ 	struct fileinfo *pfinfo;
+ 	NTSTATUS status = STATUS_PENDING;
+ 
+ 	NOTIFY notify;
+ 
+ 	pfinfo = &(g_fileinfo[handle]);
+ 	if (!pfinfo->pdir)
+ 		return STATUS_INVALID_DEVICE_REQUEST;
+ 
+ 
+ 
+ 	status = NotifyInfo(handle, pfinfo->info_class, &notify);
+ 
+ 	if (status != STATUS_PENDING)
+ 		return status;
+ 
+ 	if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
+ 	{
+ 		//printf("disk_check_notify found changed event\n");
+ 		memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
+ 		status = STATUS_NOTIFY_ENUM_DIR;
+ 	}
+ 
+ 	return status;
+ 
+ 
+ }
+ 
+ NTSTATUS
+ disk_create_notify(NTHANDLE handle, uint32 info_class)
+ {
+ 
+ 	struct fileinfo *pfinfo;
+ 	NTSTATUS ret = STATUS_PENDING;
+ 
+ 	/* printf("start disk_create_notify info_class %X\n", info_class); */
+ 
+ 	pfinfo = &(g_fileinfo[handle]);
+ 	pfinfo->info_class = info_class;
+ 
+ 	ret = NotifyInfo(handle, info_class, &pfinfo->notify);
+ 
+ 	if (info_class & 0x1000)
+ 	{			/* ???? */
+ 		if (ret == STATUS_PENDING)
+ 			return STATUS_SUCCESS;
+ 	}
+ 
+ 	/* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
+ 
+ 
+ 	return ret;
+ 
+ }
+ 
+ static NTSTATUS
+ NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p)
+ {
+ 	struct fileinfo *pfinfo;
+ 	struct stat buf;
+ 	struct dirent *dp;
+ 	char *fullname;
+ 	DIR *dpr;
+ 
+ 	pfinfo = &(g_fileinfo[handle]);
+ 	if (fstat(handle, &buf) < 0)
+ 	{
+ 		perror("NotifyInfo");
+ 		return STATUS_ACCESS_DENIED;
+ 	}
+ 	p->modify_time = buf.st_mtime;
+ 	p->status_time = buf.st_ctime;
+ 	p->num_entries = 0;
+ 	p->total_time = 0;
+ 
+ 
+ 	dpr = opendir(pfinfo->path);
+ 	if (!dpr)
+ 	{
+ 		perror("NotifyInfo");
+ 		return STATUS_ACCESS_DENIED;
+ 	}
+ 
+ 
+ 	while ((dp = readdir(dpr)))
+ 	{
+ 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+ 			continue;
+ 		p->num_entries++;
+ 		fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
+ 		sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
+ 
+ 		if (!stat(fullname, &buf))
+ 		{
+ 			p->total_time += (buf.st_mtime + buf.st_ctime);
+ 		}
+ 
+ 		xfree(fullname);
+ 	}
+ 	closedir(dpr);
+ 
+ 	return STATUS_PENDING;
+ }
+ 
  static FsInfoType *
  FsVolumeInfo(char *fpath)
  {
  
  	FILE *fdfs;
  	static FsInfoType info;
+ #ifdef HAVE_MNTENT_H
+ 	struct mntent *e;
+ #endif
  
  	/* initialize */
***************
*** 795,798 ****
--- 932,936 ----
  	strcpy(info.type, "RDPFS");
  
+ #ifdef HAVE_MNTENT_H
  	fdfs = setmntent(MNTENT_PATH, "r");
  	if (!fdfs)
***************
*** 837,842 ****
  	endmntent(fdfs);
  #else
- 	static FsInfoType info;
- 
  	/* initialize */
  	memset(&info, 0, sizeof(info));
--- 975,978 ----

Index: proto.h
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/proto.h,v
retrieving revision 1.68
retrieving revision 1.69
diff -C2 -d -r1.68 -r1.69
*** proto.h	2 Oct 2004 01:30:32 -0000	1.68
--- proto.h	3 Nov 2004 13:56:44 -0000	1.69
***************
*** 33,36 ****
--- 33,38 ----
  NTSTATUS disk_query_volume_information(NTHANDLE handle, uint32 info_class, STREAM out);
  NTSTATUS disk_query_directory(NTHANDLE handle, uint32 info_class, char *pattern, STREAM out);
+ NTSTATUS disk_create_notify(NTHANDLE handle, uint32 info_class);
+ NTSTATUS disk_check_notify(NTHANDLE handle);
  /* mppc.c */
  int mppc_expand(uint8 * data, uint32 clen, uint8 ctype, uint32 * roff, uint32 * rlen);
***************
*** 145,148 ****
--- 147,151 ----
  int serial_enum_devices(uint32 * id, char *optarg);
  BOOL serial_get_timeout(NTHANDLE handle, uint32 length, uint32 * timeout, uint32 * itv_timeout);
+ BOOL serial_get_event(NTHANDLE handle, uint32 * result);
  /* tcp.c */
  STREAM tcp_init(uint32 maxlen);

Index: rdpdr.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/rdpdr.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -C2 -d -r1.37 -r1.38
*** rdpdr.c	2 Oct 2004 01:30:32 -0000	1.37
--- rdpdr.c	3 Nov 2004 13:56:51 -0000	1.38
***************
*** 62,65 ****
--- 62,66 ----
  extern DEVICE_FNS disk_fns;
  extern FILEINFO g_fileinfo[];
+ extern BOOL g_notify_stamp;
  
  static VCHANNEL *rdpdr_channel;
***************
*** 324,329 ****
  	out_uint8p(s, buffer, length);
  	s_mark_end(s);
! 	/* JIF
! 	   hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
  	channel_send(s, rdpdr_channel);
  }
--- 325,333 ----
  	out_uint8p(s, buffer, length);
  	s_mark_end(s);
! 	/* JIF */
! #ifdef WITH_DEBUG_RDP5
! 	printf("--> rdpdr_send_completion\n");
! 	//hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
! #endif
  	channel_send(s, rdpdr_channel);
  }
***************
*** 624,629 ****
  
  					/* JIF
! 					   unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor); */
! 					status = STATUS_PENDING;	// Don't send completion packet
  					break;
  
--- 628,643 ----
  
  					/* JIF
! 					   unimpl("IRP major=0x%x minor=0x%x: IRP_MN_NOTIFY_CHANGE_DIRECTORY\n", major, minor);  */
! 
! 					in_uint32_le(s, info_level);	// notify mask
! 
! 					g_notify_stamp = True;
! 
! 					status = disk_create_notify(file, info_level);
! 					result = 0;
! 
! 					if (status == STATUS_PENDING)
! 						add_async_iorequest(device, file, id, major, length,
! 								    fns, 0, 0, NULL, 0);
  					break;
  
***************
*** 631,636 ****
  
  					status = STATUS_INVALID_PARAMETER;
! 					/* JIF
! 					   unimpl("IRP major=0x%x minor=0x%x\n", major, minor); */
  			}
  			break;
--- 645,650 ----
  
  					status = STATUS_INVALID_PARAMETER;
! 					/* JIF */
! 					unimpl("IRP major=0x%x minor=0x%x\n", major, minor);
  			}
  			break;
***************
*** 660,663 ****
--- 674,688 ----
  			status = fns->device_control(file, request, s, &out);
  			result = buffer_len = out.p - out.data;
+ 
+ 			/* Serial SERIAL_WAIT_ON_MASK */
+ 			if (status == STATUS_PENDING)
+ 			{
+ 				if (add_async_iorequest
+ 				    (device, file, id, major, length, fns, 0, 0, NULL, 0))
+ 				{
+ 					status = STATUS_PENDING;
+ 					break;
+ 				}
+ 			}
  			break;
  
***************
*** 828,843 ****
  					   support for reconnects. */
  
- 					if ((read(iorq->fd, &c, 0) != 0) && (errno == EBADF))
- 						break;
- 
  					FD_SET(iorq->fd, rfds);
  					*n = MAX(*n, iorq->fd);
  
! 					// Check if io request timeout is smaller than current (but not 0).
  					if (iorq->timeout
  					    && (select_timeout == 0
  						|| iorq->timeout < select_timeout))
  					{
! 						// Set new timeout
  						select_timeout = iorq->timeout;
  						g_min_timeout_fd = iorq->fd;	/* Remember fd */
--- 853,865 ----
  					   support for reconnects. */
  
  					FD_SET(iorq->fd, rfds);
  					*n = MAX(*n, iorq->fd);
  
! 					/* Check if io request timeout is smaller than current (but not 0). */
  					if (iorq->timeout
  					    && (select_timeout == 0
  						|| iorq->timeout < select_timeout))
  					{
! 						/* Set new timeout */
  						select_timeout = iorq->timeout;
  						g_min_timeout_fd = iorq->fd;	/* Remember fd */
***************
*** 845,850 ****
  						tv->tv_usec = (select_timeout % 1000) * 1000;
  						*timeout = True;
  					}
- 
  					break;
  
--- 867,884 ----
  						tv->tv_usec = (select_timeout % 1000) * 1000;
  						*timeout = True;
+ 						break;
+ 					}
+ 					if (iorq->itv_timeout && iorq->partial_len > 0
+ 					    && (select_timeout == 0
+ 						|| iorq->itv_timeout < select_timeout))
+ 					{
+ 						/* Set new timeout */
+ 						select_timeout = iorq->itv_timeout;
+ 						g_min_timeout_fd = iorq->fd;	/* Remember fd */
+ 						tv->tv_sec = select_timeout / 1000;
+ 						tv->tv_usec = (select_timeout % 1000) * 1000;
+ 						*timeout = True;
+ 						break;
  					}
  					break;
  
***************
*** 858,861 ****
--- 892,900 ----
  					break;
  
+ 				case IRP_MJ_DEVICE_CONTROL:
+ 					if (select_timeout > 5)
+ 						select_timeout = 5;	/* serial event queue */
+ 					break;
+ 
  			}
  
***************
*** 892,896 ****
  /* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
  void
! rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
  {
  	NTSTATUS status;
--- 931,935 ----
  /* Check if select() returned with one of the rdpdr file descriptors, and complete io if it did */
  void
! _rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
  {
  	NTSTATUS status;
***************
*** 900,906 ****
--- 939,989 ----
  	struct async_iorequest *prev;
  	uint32 req_size = 0;
+ 	uint32 buffer_len;
+ 	struct stream out;
+ 	uint8 *buffer = NULL;
+ 
  
  	if (timed_out)
  	{
+ 		/* check serial iv_timeout */
+ 
+ 		iorq = g_iorequest;
+ 		prev = NULL;
+ 		while (iorq != NULL)
+ 		{
+ 			if (iorq->fd == g_min_timeout_fd)
+ 			{
+ 				if ((iorq->partial_len > 0) &&
+ 				    (g_rdpdr_device[iorq->device].device_type ==
+ 				     DEVICE_TYPE_SERIAL))
+ 				{
+ 
+ 					/* iv_timeout between 2 chars, send partial_len */
+ 					//printf("RDPDR: IVT total %u bytes read of %u\n", iorq->partial_len, iorq->length);
+ 					rdpdr_send_completion(iorq->device,
+ 							      iorq->id, STATUS_SUCCESS,
+ 							      iorq->partial_len,
+ 							      iorq->buffer, iorq->partial_len);
+ 					iorq = rdpdr_remove_iorequest(prev, iorq);
+ 					return;
+ 				}
+ 				else
+ 				{
+ 					break;
+ 				}
+ 
+ 			}
+ 			else
+ 			{
+ 				break;
+ 			}
+ 
+ 
+ 			prev = iorq;
+ 			if (iorq)
+ 				iorq = iorq->next;
+ 
+ 		}
+ 
  		rdpdr_abort_io(g_min_timeout_fd, 0, STATUS_TIMEOUT);
  		return;
***************
*** 930,934 ****
  								   req_size, iorq->offset, &result);
  
! 						if (result > 0)
  						{
  							iorq->partial_len += result;
--- 1013,1017 ----
  								   req_size, iorq->offset, &result);
  
! 						if ((long) result > 0)
  						{
  							iorq->partial_len += result;
***************
*** 941,946 ****
  						/* or if result was 0 and status success - EOF      */
  						if ((iorq->partial_len == iorq->length) ||
! 						    (g_rdpdr_device[iorq->device].device_type ==
! 						     DEVICE_TYPE_SERIAL) || (result == 0))
  						{
  #if WITH_DEBUG_RDP5
--- 1024,1028 ----
  						/* or if result was 0 and status success - EOF      */
  						if ((iorq->partial_len == iorq->length) ||
! 						    (result == 0))
  						{
  #if WITH_DEBUG_RDP5
***************
*** 973,977 ****
  								    iorq->offset, &result);
  
! 						if (result > 0)
  						{
  							iorq->partial_len += result;
--- 1055,1059 ----
  								    iorq->offset, &result);
  
! 						if ((long) result > 0)
  						{
  							iorq->partial_len += result;
***************
*** 1000,1003 ****
--- 1082,1102 ----
  					}
  					break;
+ 				case IRP_MJ_DEVICE_CONTROL:
+ 					if (serial_get_event(iorq->fd, &result))
+ 					{
+ 						buffer = (uint8 *) xrealloc((void *) buffer, 0x14);
+ 						out.data = out.p = buffer;
+ 						out.size = sizeof(buffer);
+ 						out_uint32_le(&out, result);
+ 						result = buffer_len = out.p - out.data;
+ 						status = STATUS_SUCCESS;
+ 						rdpdr_send_completion(iorq->device, iorq->id,
+ 								      status, result, buffer,
+ 								      buffer_len);
+ 						xfree(buffer);
+ 						iorq = rdpdr_remove_iorequest(prev, iorq);
+ 					}
+ 
+ 					break;
  			}
  
***************
*** 1008,1013 ****
--- 1107,1172 ----
  	}
  
+ 	/* Check notify */
+ 	iorq = g_iorequest;
+ 	prev = NULL;
+ 	while (iorq != NULL)
+ 	{
+ 		if (iorq->fd != 0)
+ 		{
+ 			switch (iorq->major)
+ 			{
+ 
+ 				case IRP_MJ_DIRECTORY_CONTROL:
+ 					if (g_rdpdr_device[iorq->device].device_type ==
+ 					    DEVICE_TYPE_DISK)
+ 					{
+ 
+ 						if (g_notify_stamp)
+ 						{
+ 							g_notify_stamp = False;
+ 							status = disk_check_notify(iorq->fd);
+ 							if (status != STATUS_PENDING)
+ 							{
+ 								rdpdr_send_completion(iorq->device,
+ 										      iorq->id,
+ 										      status, 0,
+ 										      NULL, 0);
+ 								iorq = rdpdr_remove_iorequest(prev,
+ 											      iorq);
+ 							}
+ 						}
+ 					}
+ 					break;
+ 
+ 
+ 
+ 			}
+ 		}
+ 
+ 		prev = iorq;
+ 		if (iorq)
+ 			iorq = iorq->next;
+ 	}
+ 
+ }
+ 
+ void
+ rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
+ {
+ 	fd_set dummy;
+ 
+ 
+ 	FD_ZERO(&dummy);
+ 
+ 
+ 	/* fist check event queue only,
+ 	   any serial wait event must be done before read block will be sent
+ 	 */
+ 
+ 	_rdpdr_check_fds(&dummy, &dummy, False);
+ 	_rdpdr_check_fds(rfds, wfds, timed_out);
  }
  
+ 
  /* Abort a pending io request for a given handle and major */
  BOOL

Index: serial.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/serial.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** serial.c	7 Oct 2004 13:00:28 -0000	1.20
--- serial.c	3 Nov 2004 13:56:51 -0000	1.21
***************
*** 6,9 ****
--- 6,15 ----
  #include "rdesktop.h"
  
+ #ifdef WITH_DEBUG_SERIAL
+ #define DEBUG_SERIAL(args) printf args;
+ #else
+ #define DEBUG_SERIAL(args)
+ #endif
+ 
  #define FILE_DEVICE_SERIAL_PORT		0x1b
  
***************
*** 76,79 ****
--- 82,87 ----
  
  /* Modem Status */
+ #define SERIAL_MS_DTR 0x01
+ #define SERIAL_MS_RTS 0x02
  #define SERIAL_MS_CTS 0x10
  #define SERIAL_MS_DSR 0x20
***************
*** 81,88 ****
--- 89,118 ----
  #define SERIAL_MS_CAR 0x80
  
+ /* Handflow */
+ #define SERIAL_DTR_CONTROL	0x01
+ #define SERIAL_CTS_HANDSHAKE	0x08
+ #define SERIAL_ERROR_ABORT	0x80000000
+ 
+ #define SERIAL_XON_HANDSHAKE	0x01
+ #define SERIAL_XOFF_HANDSHAKE	0x02
+ #define SERIAL_DSR_SENSITIVITY	0x40
+ 
+ #define SERIAL_CHAR_EOF		0
+ #define SERIAL_CHAR_ERROR	1
+ #define SERIAL_CHAR_BREAK	2
+ #define SERIAL_CHAR_EVENT	3
+ #define SERIAL_CHAR_XON		4
+ #define SERIAL_CHAR_XOFF	5
+ 
  #ifndef CRTSCTS
  #define CRTSCTS 0
  #endif
  
+ /* FIONREAD should really do the same thing as TIOCINQ, where it is
+  * not available */
+ #ifndef TIOCINQ
+ #include <sys/filio.h>
+ #define TIOCINQ FIONREAD
+ #endif
  
  extern RDPDR_DEVICE g_rdpdr_device[];
***************
*** 190,195 ****
  			break;
  #endif
  		default:
! 			pser_inf->baud_rate = 0;
  			break;
  	}
--- 220,235 ----
  			break;
  #endif
+ #ifdef B230400
+ 		case B230400:
+ 			pser_inf->baud_rate = 230400;
+ 			break;
+ #endif
+ #ifdef B460800
+ 		case B460800:
+ 			pser_inf->baud_rate = 460800;
+ 			break;
+ #endif
  		default:
! 			pser_inf->baud_rate = 9600;
  			break;
  	}
***************
*** 219,223 ****
  	}
  
! 	pser_inf->rts = (ptermios->c_cflag & CRTSCTS) ? 1 : 0;
  
  	return True;
--- 259,283 ----
  	}
  
! 	if (ptermios->c_cflag & CRTSCTS)
! 	{
! 		pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_CTS_HANDSHAKE | SERIAL_ERROR_ABORT;
! 	}
! 	else
! 	{
! 		pser_inf->control = SERIAL_DTR_CONTROL | SERIAL_ERROR_ABORT;
! 	}
! 
! 	pser_inf->xonoff = SERIAL_DSR_SENSITIVITY;
! 	if (ptermios->c_iflag & IXON)
! 		pser_inf->xonoff |= SERIAL_XON_HANDSHAKE;
! 
! 	if (ptermios->c_iflag & IXOFF)
! 		pser_inf->xonoff |= SERIAL_XOFF_HANDSHAKE;
! 
! 	pser_inf->chars[SERIAL_CHAR_XON] = ptermios->c_cc[VSTART];
! 	pser_inf->chars[SERIAL_CHAR_XOFF] = ptermios->c_cc[VSTOP];
! 	pser_inf->chars[SERIAL_CHAR_EOF] = ptermios->c_cc[VEOF];
! 	pser_inf->chars[SERIAL_CHAR_BREAK] = ptermios->c_cc[VINTR];
! 	pser_inf->chars[SERIAL_CHAR_ERROR] = ptermios->c_cc[VKILL];
  
  	return True;
***************
*** 311,323 ****
  			break;
  #endif
  		default:
! 			speed = B0;
  			break;
  	}
  
  	/* on systems with separate ispeed and ospeed, we can remember the speed
  	   in ispeed while changing DTR with ospeed */
  	cfsetispeed(pser_inf->ptermios, speed);
  	cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0);
  
  	ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS);
--- 371,398 ----
  			break;
  #endif
+ #ifdef B230400
+ 		case 230400:
+ 			speed = B115200;
+ 			break;
+ #endif
+ #ifdef B460800
+ 		case 460800:
+ 			speed = B115200;
+ 			break;
+ #endif
  		default:
! 			speed = B9600;
  			break;
  	}
  
+ #if 0
  	/* on systems with separate ispeed and ospeed, we can remember the speed
  	   in ispeed while changing DTR with ospeed */
  	cfsetispeed(pser_inf->ptermios, speed);
  	cfsetospeed(pser_inf->ptermios, pser_inf->dtr ? speed : 0);
+ #endif
+ 
+ 	ptermios->c_cflag &= ~CBAUD;
+ 	ptermios->c_cflag |= speed;
  
  	ptermios->c_cflag &= ~(CSTOPB | PARENB | PARODD | CSIZE | CRTSCTS);
***************
*** 327,330 ****
--- 402,408 ----
  			ptermios->c_cflag |= CSTOPB;
  			break;
+ 		default:
+ 			ptermios->c_cflag &= ~CSTOPB;
+ 			break;
  	}
  
***************
*** 337,340 ****
--- 415,421 ----
  			ptermios->c_cflag |= PARENB | PARODD;
  			break;
+ 		case NO_PARITY:
+ 			ptermios->c_cflag &= ~(PARENB | PARODD);
+ 			break;
  	}
  
***************
*** 355,360 ****
--- 436,476 ----
  	}
  
+ #if 0
  	if (pser_inf->rts)
  		ptermios->c_cflag |= CRTSCTS;
+ 	else
+ 		ptermios->c_cflag &= ~CRTSCTS;
+ #endif
+ 
+ 	if (pser_inf->control & SERIAL_CTS_HANDSHAKE)
+ 	{
+ 		ptermios->c_cflag |= CRTSCTS;
+ 	}
+ 	else
+ 	{
+ 		ptermios->c_cflag &= ~CRTSCTS;
+ 	}
+ 
+ 
+ 	if (pser_inf->xonoff & SERIAL_XON_HANDSHAKE)
+ 	{
+ 		ptermios->c_iflag |= IXON | IMAXBEL;
+ 	}
+ 	if (pser_inf->xonoff & SERIAL_XOFF_HANDSHAKE)
+ 	{
+ 		ptermios->c_iflag |= IXOFF | IMAXBEL;
+ 	}
+ 
+ 	if ((pser_inf->xonoff & (SERIAL_XOFF_HANDSHAKE | SERIAL_XON_HANDSHAKE)) == 0)
+ 	{
+ 		ptermios->c_iflag &= ~IXON;
+ 		ptermios->c_iflag &= ~IXOFF;
+ 	}
+ 
+ 	ptermios->c_cc[VSTART] = pser_inf->chars[SERIAL_CHAR_XON];
+ 	ptermios->c_cc[VSTOP] = pser_inf->chars[SERIAL_CHAR_XOFF];
+ 	ptermios->c_cc[VEOF] = pser_inf->chars[SERIAL_CHAR_EOF];
+ 	ptermios->c_cc[VINTR] = pser_inf->chars[SERIAL_CHAR_BREAK];
+ 	ptermios->c_cc[VKILL] = pser_inf->chars[SERIAL_CHAR_ERROR];
  
  	tcsetattr(serial_fd, TCSANOW, ptermios);
***************
*** 435,457 ****
  
  	/* some sane information */
! 	printf("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u, rts %u\n", g_rdpdr_device[device_id].name, g_rdpdr_device[device_id].local_path, pser_inf->baud_rate, pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length, pser_inf->dtr, pser_inf->rts);
! 
! 	printf("INFO: use stty to change settings\n");
! 
! /*	ptermios->c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD;
! 	ptermios->c_cflag |= CREAD;
! 	ptermios->c_lflag |= ICANON;
! 	ptermios->c_iflag = IGNPAR | ICRNL;
  
- 	tcsetattr(serial_fd, TCSANOW, ptermios);
- */
  	pser_inf->ptermios->c_iflag &=
  		~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
  	pser_inf->ptermios->c_oflag &= ~OPOST;
! 	pser_inf->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  	pser_inf->ptermios->c_cflag &= ~(CSIZE | PARENB);
  	pser_inf->ptermios->c_cflag |= CS8;
  	tcsetattr(serial_fd, TCSANOW, pser_inf->ptermios);
  
  	*handle = serial_fd;
  
--- 551,571 ----
  
  	/* some sane information */
! 	DEBUG_SERIAL(("INFO: SERIAL %s to %s\nINFO: speed %u baud, stop bits %u, parity %u, word length %u bits, dtr %u, rts %u\n", g_rdpdr_device[device_id].name, g_rdpdr_device[device_id].local_path, pser_inf->baud_rate, pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length, pser_inf->dtr, pser_inf->rts));
  
  	pser_inf->ptermios->c_iflag &=
  		~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
  	pser_inf->ptermios->c_oflag &= ~OPOST;
! 	pser_inf->ptermios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN | XCASE);
  	pser_inf->ptermios->c_cflag &= ~(CSIZE | PARENB);
  	pser_inf->ptermios->c_cflag |= CS8;
+ 
  	tcsetattr(serial_fd, TCSANOW, pser_inf->ptermios);
  
+ 	pser_inf->event_txempty = 0;
+ 	pser_inf->event_cts = 0;
+ 	pser_inf->event_dsr = 0;
+ 	pser_inf->event_rlsd = 0;
+ 	pser_inf->event_pending = 0;
+ 
  	*handle = serial_fd;
  
***************
*** 460,463 ****
--- 574,579 ----
  		perror("fcntl");
  
+ 	pser_inf->read_total_timeout_constant = 5;
+ 
  	return STATUS_SUCCESS;
  }
***************
*** 469,472 ****
--- 585,590 ----
  	if (i >= 0)
  		g_rdpdr_device[i].handle = 0;
+ 
+ 	rdpdr_abort_io(handle, 0, STATUS_TIMEOUT);
  	close(handle);
  	return STATUS_SUCCESS;
***************
*** 479,482 ****
--- 597,604 ----
  	SERIAL_DEVICE *pser_inf;
  	struct termios *ptermios;
+ #ifdef WITH_DEBUG_SERIAL
+ 	int bytes_inqueue;
+ #endif
+ 
  
  	timeout = 90;
***************
*** 512,519 ****
  	tcsetattr(handle, TCSANOW, ptermios);
  
  
  	*result = read(handle, data, length);
  
! 	//hexdump(data, *read);
  
  	return STATUS_SUCCESS;
--- 634,649 ----
  	tcsetattr(handle, TCSANOW, ptermios);
  
+ #ifdef WITH_DEBUG_SERIAL
+ 	ioctl(handle, TIOCINQ, &bytes_inqueue);
+ 	DEBUG_SERIAL(("serial_read inqueue: %d expected %d\n", bytes_inqueue, length));
+ #endif
  
  	*result = read(handle, data, length);
  
! #ifdef WITH_DEBUG_SERIAL
! 	DEBUG_SERIAL(("serial_read Bytes %d\n", *result));
! 	if (*result > 0)
! 		hexdump(data, *result);
! #endif
  
  	return STATUS_SUCCESS;
***************
*** 523,527 ****
--- 653,667 ----
  serial_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
  {
+ 	SERIAL_DEVICE *pser_inf;
+ 
+ 	pser_inf = get_serial_info(handle);
+ 
  	*result = write(handle, data, length);
+ 
+ 	if (*result > 0)
+ 		pser_inf->event_txempty = *result;
+ 
+ 	DEBUG_SERIAL(("serial_write length %d, offset %d result %d\n", length, offset, *result));
+ 
  	return STATUS_SUCCESS;
  }
***************
*** 530,536 ****
  serial_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
  {
- #if 0
  	int flush_mask, purge_mask;
- #endif
  	uint32 result, modemstate;
  	uint8 immediate;
--- 670,674 ----
***************
*** 548,553 ****
  	request &= 0xfff;
  
- 	printf("SERIAL IOCTL %d\n", request);
- 
  	switch (request)
  	{
--- 686,689 ----
***************
*** 555,565 ****
--- 691,705 ----
  			in_uint32_le(in, pser_inf->baud_rate);
  			set_termios(pser_inf, handle);
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BAUD_RATE %d\n", pser_inf->baud_rate));
  			break;
  		case SERIAL_GET_BAUD_RATE:
  			out_uint32_le(out, pser_inf->baud_rate);
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_BAUD_RATE %d\n", pser_inf->baud_rate));
  			break;
  		case SERIAL_SET_QUEUE_SIZE:
  			in_uint32_le(in, pser_inf->queue_in_size);
  			in_uint32_le(in, pser_inf->queue_out_size);
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_QUEUE_SIZE in %d out %d\n",
+ 			    pser_inf->queue_in_size, pser_inf->queue_out_size));
  			break;
  		case SERIAL_SET_LINE_CONTROL:
***************
*** 568,573 ****
--- 708,716 ----
  			in_uint8(in, pser_inf->word_length);
  			set_termios(pser_inf, handle);
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_LINE_CONTROL stop %d parity %d word %d\n",
+ 			    pser_inf->stop_bits, pser_inf->parity, pser_inf->word_length));
  			break;
  		case SERIAL_GET_LINE_CONTROL:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_LINE_CONTROL\n"));
  			out_uint8(out, pser_inf->stop_bits);
  			out_uint8(out, pser_inf->parity);
***************
*** 575,626 ****
  			break;
  		case SERIAL_IMMEDIATE_CHAR:
  			in_uint8(in, immediate);
  			serial_write(handle, &immediate, 1, 0, &result);
  			break;
  		case SERIAL_CONFIG_SIZE:
  			out_uint32_le(out, 0);
  			break;
  		case SERIAL_GET_CHARS:
! 			out_uint8s(out, 6);
  			break;
  		case SERIAL_SET_CHARS:
! 			in_uint8s(in, 6);
  			break;
  		case SERIAL_GET_HANDFLOW:
! 			out_uint32_le(out, 0);
! 			out_uint32_le(out, 3);	/* Xon/Xoff */
! 			out_uint32_le(out, 0);
! 			out_uint32_le(out, 0);
  			break;
  		case SERIAL_SET_HANDFLOW:
! 			in_uint8s(in, 16);
  			break;
  		case SERIAL_SET_TIMEOUTS:
! 			in_uint8s(in, 20);
  			break;
  		case SERIAL_GET_TIMEOUTS:
! 			out_uint8s(out, 20);
  			break;
  		case SERIAL_GET_WAIT_MASK:
! 			out_uint32(out, pser_inf->wait_mask);
  			break;
  		case SERIAL_SET_WAIT_MASK:
  			in_uint32(in, pser_inf->wait_mask);
  			break;
  		case SERIAL_SET_DTR:
  			pser_inf->dtr = 1;
- 			set_termios(pser_inf, handle);
  			break;
  		case SERIAL_CLR_DTR:
  			pser_inf->dtr = 0;
- 			set_termios(pser_inf, handle);
  			break;
  		case SERIAL_SET_RTS:
  			pser_inf->rts = 1;
- 			set_termios(pser_inf, handle);
  			break;
  		case SERIAL_CLR_RTS:
  			pser_inf->rts = 0;
- 			set_termios(pser_inf, handle);
  			break;
  		case SERIAL_GET_MODEMSTATUS:
--- 718,817 ----
  			break;
  		case SERIAL_IMMEDIATE_CHAR:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_IMMEDIATE_CHAR\n"));
  			in_uint8(in, immediate);
  			serial_write(handle, &immediate, 1, 0, &result);
  			break;
  		case SERIAL_CONFIG_SIZE:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_CONFIG_SIZE\n"));
  			out_uint32_le(out, 0);
  			break;
  		case SERIAL_GET_CHARS:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_CHARS\n"));
! 			out_uint8a(out, pser_inf->chars, 6);
  			break;
  		case SERIAL_SET_CHARS:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_CHARS\n"));
! 			in_uint8a(in, pser_inf->chars, 6);
! #ifdef WITH_DEBUG_SERIAL
! 			hexdump(pser_inf->chars, 6);
! #endif
! 			set_termios(pser_inf, handle);
  			break;
  		case SERIAL_GET_HANDFLOW:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_HANDFLOW\n"));
! 			get_termios(pser_inf, handle);
! 			out_uint32_le(out, pser_inf->control);
! 			out_uint32_le(out, pser_inf->xonoff);	/* Xon/Xoff */
! 			out_uint32_le(out, pser_inf->onlimit);
! 			out_uint32_le(out, pser_inf->offlimit);
  			break;
  		case SERIAL_SET_HANDFLOW:
! 			in_uint32_le(in, pser_inf->control);
! 			in_uint32_le(in, pser_inf->xonoff);
! 			in_uint32_le(in, pser_inf->onlimit);
! 			in_uint32_le(in, pser_inf->offlimit);
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_HANDFLOW %x %x %x %x\n",
! 			    pser_inf->control, pser_inf->xonoff, pser_inf->onlimit,
! 			    pser_inf->onlimit));
! 			set_termios(pser_inf, handle);
  			break;
  		case SERIAL_SET_TIMEOUTS:
! 			in_uint32(in, pser_inf->read_interval_timeout);
! 			in_uint32(in, pser_inf->read_total_timeout_multiplier);
! 			in_uint32(in, pser_inf->read_total_timeout_constant);
! 			in_uint32(in, pser_inf->write_total_timeout_multiplier);
! 			in_uint32(in, pser_inf->write_total_timeout_constant);
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_TIMEOUTS read timeout %d %d %d\n",
! 			    pser_inf->read_interval_timeout,
! 			    pser_inf->read_total_timeout_multiplier,
! 			    pser_inf->read_total_timeout_constant));
  			break;
  		case SERIAL_GET_TIMEOUTS:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_TIMEOUTS read timeout %d %d %d\n",
! 			    pser_inf->read_interval_timeout,
! 			    pser_inf->read_total_timeout_multiplier,
! 			    pser_inf->read_total_timeout_constant));
! 
! 			out_uint32(out, pser_inf->read_interval_timeout);
! 			out_uint32(out, pser_inf->read_total_timeout_multiplier);
! 			out_uint32(out, pser_inf->read_total_timeout_constant);
! 			out_uint32(out, pser_inf->write_total_timeout_multiplier);
! 			out_uint32(out, pser_inf->write_total_timeout_constant);
  			break;
  		case SERIAL_GET_WAIT_MASK:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_WAIT_MASK %X\n", pser_inf->wait_mask);
! 			out_uint32(out, pser_inf->wait_mask));
  			break;
  		case SERIAL_SET_WAIT_MASK:
  			in_uint32(in, pser_inf->wait_mask);
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_WAIT_MASK %X\n", pser_inf->wait_mask));
  			break;
  		case SERIAL_SET_DTR:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_DTR\n"));
+ 			ioctl(handle, TIOCMGET, &result);
+ 			result |= TIOCM_DTR;
+ 			ioctl(handle, TIOCMSET, &result);
  			pser_inf->dtr = 1;
  			break;
  		case SERIAL_CLR_DTR:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_DTR\n"));
+ 			ioctl(handle, TIOCMGET, &result);
+ 			result &= ~TIOCM_DTR;
+ 			ioctl(handle, TIOCMSET, &result);
  			pser_inf->dtr = 0;
  			break;
  		case SERIAL_SET_RTS:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_RTS\n"));
+ 			ioctl(handle, TIOCMGET, &result);
+ 			result |= TIOCM_RTS;
+ 			ioctl(handle, TIOCMSET, &result);
  			pser_inf->rts = 1;
  			break;
  		case SERIAL_CLR_RTS:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_CLR_RTS\n"));
+ 			ioctl(handle, TIOCMGET, &result);
+ 			result &= ~TIOCM_RTS;
+ 			ioctl(handle, TIOCMSET, &result);
  			pser_inf->rts = 0;
  			break;
  		case SERIAL_GET_MODEMSTATUS:
***************
*** 636,640 ****
--- 827,836 ----
  			if (result & TIOCM_CAR)
  				modemstate |= SERIAL_MS_CAR;
+ 			if (result & TIOCM_DTR)
+ 				modemstate |= SERIAL_MS_DTR;
+ 			if (result & TIOCM_RTS)
+ 				modemstate |= SERIAL_MS_RTS;
  #endif
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_MODEMSTATUS %X\n", modemstate));
  			out_uint32_le(out, modemstate);
  			break;
***************
*** 642,679 ****
  			out_uint32_le(out, 0);	/* Errors */
  			out_uint32_le(out, 0);	/* Hold reasons */
! 			out_uint32_le(out, 0);	/* Amount in in queue */
! 			out_uint32_le(out, 0);	/* Amount in out queue */
  			out_uint8(out, 0);	/* EofReceived */
  			out_uint8(out, 0);	/* WaitForImmediate */
  			break;
- #if 0
  		case SERIAL_PURGE:
- 			printf("SERIAL_PURGE\n");
  			in_uint32(in, purge_mask);
! 			if (purge_mask & 0x04)
  				flush_mask |= TCOFLUSH;
! 			if (purge_mask & 0x08)
  				flush_mask |= TCIFLUSH;
  			if (flush_mask != 0)
  				tcflush(handle, flush_mask);
! 			if (purge_mask & 0x01)
  				rdpdr_abort_io(handle, 4, STATUS_CANCELLED);
! 			if (purge_mask & 0x02)
  				rdpdr_abort_io(handle, 3, STATUS_CANCELLED);
  			break;
  		case SERIAL_WAIT_ON_MASK:
! 			/* XXX implement me */
! 			out_uint32_le(out, pser_inf->wait_mask);
  			break;
  		case SERIAL_SET_BREAK_ON:
! 			tcsendbreak(serial_fd, 0);
  			break;
  		case SERIAL_RESET_DEVICE:
  		case SERIAL_SET_BREAK_OFF:
  		case SERIAL_SET_XOFF:
  		case SERIAL_SET_XON:
! 			/* ignore */
  			break;
- #endif
  		default:
  			unimpl("SERIAL IOCTL %d\n", request);
--- 838,900 ----
  			out_uint32_le(out, 0);	/* Errors */
  			out_uint32_le(out, 0);	/* Hold reasons */
! 
! 			result = 0;
! 			ioctl(handle, TIOCINQ, &result);
! 			out_uint32_le(out, result);	/* Amount in in queue */
! 			if (result)
! 				DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS in queue %d\n", result));
! 
! 			result = 0;
! 			ioctl(handle, TIOCOUTQ, &result);
! 			out_uint32_le(out, result);	/* Amount in out queue */
! 			if (result)
! 				DEBUG_SERIAL(("serial_ioctl -> SERIAL_GET_COMMSTATUS out queue %d\n", result));
! 
  			out_uint8(out, 0);	/* EofReceived */
  			out_uint8(out, 0);	/* WaitForImmediate */
  			break;
  		case SERIAL_PURGE:
  			in_uint32(in, purge_mask);
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_PURGE purge_mask %X\n", purge_mask));
! 			flush_mask = 0;
! 			if (purge_mask & SERIAL_PURGE_TXCLEAR)
  				flush_mask |= TCOFLUSH;
! 			if (purge_mask & SERIAL_PURGE_RXCLEAR)
  				flush_mask |= TCIFLUSH;
  			if (flush_mask != 0)
  				tcflush(handle, flush_mask);
! 			if (purge_mask & SERIAL_PURGE_TXABORT)
  				rdpdr_abort_io(handle, 4, STATUS_CANCELLED);
! 			if (purge_mask & SERIAL_PURGE_RXABORT)
  				rdpdr_abort_io(handle, 3, STATUS_CANCELLED);
  			break;
  		case SERIAL_WAIT_ON_MASK:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_WAIT_ON_MASK %X\n", pser_inf->wait_mask));
! 			pser_inf->event_pending = 1;
! 			if (serial_get_event(handle, &result))
! 			{
! 				DEBUG_SERIAL(("WAIT end  event = %x\n", result));
! 				out_uint32_le(out, result);
! 				break;
! 			}
! 			return STATUS_PENDING;
  			break;
  		case SERIAL_SET_BREAK_ON:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_ON\n"));
! 			tcsendbreak(handle, 0);
  			break;
  		case SERIAL_RESET_DEVICE:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_RESET_DEVICE\n"));
+ 			break;
  		case SERIAL_SET_BREAK_OFF:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_BREAK_OFF\n"));
+ 			break;
  		case SERIAL_SET_XOFF:
+ 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XOFF\n"));
+ 			break;
  		case SERIAL_SET_XON:
! 			DEBUG_SERIAL(("serial_ioctl -> SERIAL_SET_XON\n"));
! 			tcflow(handle, TCION);
  			break;
  		default:
  			unimpl("SERIAL IOCTL %d\n", request);
***************
*** 684,687 ****
--- 905,1002 ----
  }
  
+ BOOL
+ serial_get_event(NTHANDLE handle, uint32 * result)
+ {
+ 	int index;
+ 	SERIAL_DEVICE *pser_inf;
+ 	int bytes;
+ 	BOOL ret = False;
+ 
+ 	*result = 0;
+ 	index = get_device_index(handle);
+ 	if (index < 0)
+ 		return False;
+ 
+ 	pser_inf = (SERIAL_DEVICE *) g_rdpdr_device[index].pdevice_data;
+ 
+ 
+ 	ioctl(handle, TIOCINQ, &bytes);
+ 
+ 	if (bytes > 0)
+ 	{
+ 		DEBUG_SERIAL(("serial_get_event Bytes %d\n", bytes));
+ 		if (bytes > pser_inf->event_rlsd)
+ 		{
+ 			pser_inf->event_rlsd = bytes;
+ 			if (pser_inf->wait_mask & SERIAL_EV_RLSD)
+ 			{
+ 				DEBUG_SERIAL(("Event -> SERIAL_EV_RLSD \n"));
+ 				*result |= SERIAL_EV_RLSD;
+ 				ret = True;
+ 			}
+ 
+ 		}
+ 
+ 		if ((bytes > 1) && (pser_inf->wait_mask & SERIAL_EV_RXFLAG))
+ 		{
+ 			DEBUG_SERIAL(("Event -> SERIAL_EV_RXFLAG Bytes %d\n", bytes));
+ 			*result |= SERIAL_EV_RXFLAG;
+ 			ret = True;
+ 		}
+ 		if ((pser_inf->wait_mask & SERIAL_EV_RXCHAR))
+ 		{
+ 			DEBUG_SERIAL(("Event -> SERIAL_EV_RXCHAR Bytes %d\n", bytes));
+ 			*result |= SERIAL_EV_RXCHAR;
+ 			ret = True;
+ 		}
+ 
+ 	}
+ 	else
+ 	{
+ 		pser_inf->event_rlsd = 0;
+ 	}
+ 
+ 
+ 	ioctl(handle, TIOCOUTQ, &bytes);
+ 	if ((bytes == 0)
+ 	    && (pser_inf->event_txempty > 0) && (pser_inf->wait_mask & SERIAL_EV_TXEMPTY))
+ 	{
+ 
+ 		DEBUG_SERIAL(("Event -> SERIAL_EV_TXEMPTY\n"));
+ 		*result |= SERIAL_EV_TXEMPTY;
+ 		ret = True;
+ 	}
+ 	pser_inf->event_txempty = bytes;
+ 
+ 
+ 	ioctl(handle, TIOCMGET, &bytes);
+ 	if ((bytes & TIOCM_DSR) != pser_inf->event_dsr)
+ 	{
+ 		pser_inf->event_dsr = bytes & TIOCM_DSR;
+ 		if (pser_inf->wait_mask & SERIAL_EV_DSR)
+ 		{
+ 			DEBUG_SERIAL(("event -> SERIAL_EV_DSR %s\n", (bytes & TIOCM_DSR) ? "ON" : "OFF"));
+ 			*result |= SERIAL_EV_DSR;
+ 			ret = True;
+ 		}
+ 	}
+ 
+ 	if ((bytes & TIOCM_CTS) != pser_inf->event_cts)
+ 	{
+ 		pser_inf->event_cts = bytes & TIOCM_CTS;
+ 		if (pser_inf->wait_mask & SERIAL_EV_CTS)
+ 		{
+ 			DEBUG_SERIAL((" EVENT-> SERIAL_EV_CTS %s\n", (bytes & TIOCM_CTS) ? "ON" : "OFF"));
+ 			*result |= SERIAL_EV_CTS;
+ 			ret = True;
+ 		}
+ 	}
+ 
+ 	if (ret)
+ 		pser_inf->event_pending = 0;
+ 
+ 	return ret;
+ }
+ 
  /* Read timeout for a given file descripter (device) when adding fd's to select() */
  BOOL

Index: types.h
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/types.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -d -r1.21 -r1.22
*** types.h	2 Oct 2004 01:30:32 -0000	1.21
--- types.h	3 Nov 2004 13:56:52 -0000	1.22
***************
*** 198,201 ****
--- 198,202 ----
  	int dtr;
  	int rts;
+ 	uint32 control, xonoff, onlimit, offlimit;
  	uint32 baud_rate,
  		queue_in_size,
***************
*** 207,211 ****
--- 208,214 ----
  		write_total_timeout_multiplier, write_total_timeout_constant, posix_wait_mask;
  	uint8 stop_bits, parity, word_length;
+ 	uint8 chars[6];
  	struct termios *ptermios, *pold_termios;
+ 	int event_txempty, event_cts, event_dsr, event_rlsd, event_pending;
  }
  SERIAL_DEVICE;
***************
*** 236,242 ****
  PRINTER;
  
  typedef struct fileinfo
  {
! 	uint32 device_id, flags_and_attributes;
  	char path[256];
  	DIR *pdir;
--- 239,254 ----
  PRINTER;
  
+ typedef struct notify_data
+ {
+ 	time_t modify_time;
+ 	time_t status_time;
+ 	time_t total_time;
+ 	unsigned int num_entries;
+ }
+ NOTIFY;
+ 
  typedef struct fileinfo
  {
! 	uint32 device_id, flags_and_attributes, accessmask;
  	char path[256];
  	DIR *pdir;
***************
*** 244,247 ****
--- 256,261 ----
  	char pattern[64];
  	BOOL delete_on_close;
+ 	NOTIFY notify;
+ 	uint32 info_class;
  }
  FILEINFO;

Index: xwin.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/xwin.c,v
retrieving revision 1.178
retrieving revision 1.179
diff -C2 -d -r1.178 -r1.179
*** xwin.c	21 Oct 2004 08:43:22 -0000	1.178
--- xwin.c	3 Nov 2004 13:56:52 -0000	1.179
***************
*** 1436,1445 ****
  
  			case 0:
! 				/* TODO: if tv.tv_sec just times out
! 				 * we will segfault.
! 				 * FIXME:
! 				 */
! 				//s_timeout = True;
! 				//rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
  				continue;
  		}
--- 1436,1442 ----
  
  			case 0:
! 				/* Abort serial read calls */
! 				if (s_timeout)
! 					rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
  				continue;
  		}



-------------------------------------------------------
This SF.Net email is sponsored by:
Sybase ASE Linux Express Edition - download now for FREE
LinuxWorld Reader's Choice Award Winner for best database on Linux.
http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.