Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / modules / rosapps / applications / net / tsclient / rdesktop / parallel.c
diff --git a/modules/rosapps/applications/net/tsclient/rdesktop/parallel.c b/modules/rosapps/applications/net/tsclient/rdesktop/parallel.c
new file mode 100644 (file)
index 0000000..51c7d75
--- /dev/null
@@ -0,0 +1,187 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Copyright (C) Matthew Chapman 1999-2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation, Inc.,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#define        MAX_PARALLEL_DEVICES            1
+
+#define FILE_DEVICE_PARALLEL           0x22
+
+#define IOCTL_PAR_QUERY_RAW_DEVICE_ID  0x0c
+
+#include "rdesktop.h"
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#if defined(__linux__)
+#include <linux/lp.h>
+#endif
+
+/* Enumeration of devices from rdesktop.c        */
+/* returns numer of units found and initialized. */
+/* optarg looks like ':LPT1=/dev/lp0'            */
+/* when it arrives to this function.             */
+int
+parallel_enum_devices(RDPCLIENT * This, uint32 * id, char *optarg)
+{
+       PARALLEL_DEVICE *ppar_info;
+
+       char *pos = optarg;
+       char *pos2;
+       int count = 0;
+
+       /* skip the first colon */
+       optarg++;
+       while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
+       {
+               ppar_info = (PARALLEL_DEVICE *) xmalloc(sizeof(PARALLEL_DEVICE));
+
+               pos2 = next_arg(optarg, '=');
+               strcpy(This->rdpdr_device[*id].name, optarg);
+
+               toupper_str(This->rdpdr_device[*id].name);
+
+               This->rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
+               strcpy(This->rdpdr_device[*id].local_path, pos2);
+               printf("PARALLEL %s to %s\n", optarg, pos2);
+
+               /* set device type */
+               This->rdpdr_device[*id].device_type = DEVICE_TYPE_PARALLEL;
+               This->rdpdr_device[*id].pdevice_data = (void *) ppar_info;
+               This->rdpdr_device[*id].handle = 0;
+               count++;
+               (*id)++;
+
+               optarg = pos;
+       }
+       return count;
+}
+
+static NTSTATUS
+parallel_create(RDPCLIENT * This, uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
+               uint32 flags, char *filename, NTHANDLE * handle)
+{
+       int parallel_fd;
+
+       parallel_fd = open(This->rdpdr_device[device_id].local_path, O_RDWR);
+       if (parallel_fd == -1)
+       {
+               perror("open");
+               return STATUS_ACCESS_DENIED;
+       }
+
+       /* all read and writes should be non blocking */
+       if (fcntl(parallel_fd, F_SETFL, O_NONBLOCK) == -1)
+               perror("fcntl");
+
+#if defined(LPABORT)
+       /* Retry on errors */
+       ioctl(parallel_fd, LPABORT, (int) 1);
+#endif
+
+       This->rdpdr_device[device_id].handle = parallel_fd;
+
+       *handle = parallel_fd;
+
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+parallel_close(RDPCLIENT * This, NTHANDLE handle)
+{
+       int i = get_device_index(This, handle);
+       if (i >= 0)
+               This->rdpdr_device[i].handle = 0;
+       close(handle);
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+parallel_read(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+       *result = read(handle, data, length);
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+parallel_write(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
+{
+       int rc = STATUS_SUCCESS;
+
+       int n = write(handle, data, length);
+       if (n < 0)
+       {
+#if defined(LPGETSTATUS)
+               int status;
+#endif
+
+               *result = 0;
+               switch (errno)
+               {
+                       case EAGAIN:
+                               rc = STATUS_DEVICE_OFF_LINE;
+                       case ENOSPC:
+                               rc = STATUS_DEVICE_PAPER_EMPTY;
+                       case EIO:
+                               rc = STATUS_DEVICE_OFF_LINE;
+                       default:
+                               rc = STATUS_DEVICE_POWERED_OFF;
+               }
+#if defined(LPGETSTATUS)
+               if (ioctl(handle, LPGETSTATUS, &status) == 0)
+               {
+                       /* coming soon: take care for the printer status */
+                       printf("parallel_write: status = %d, errno = %d\n", status, errno);
+               }
+#endif
+       }
+       *result = n;
+       return rc;
+}
+
+static NTSTATUS
+parallel_device_control(RDPCLIENT * This, NTHANDLE handle, uint32 request, STREAM in, STREAM out)
+{
+       if ((request >> 16) != FILE_DEVICE_PARALLEL)
+               return STATUS_INVALID_PARAMETER;
+
+       /* extract operation */
+       request >>= 2;
+       request &= 0xfff;
+
+       printf("PARALLEL IOCTL %d: ", request);
+
+       switch (request)
+       {
+               case IOCTL_PAR_QUERY_RAW_DEVICE_ID:
+
+               default:
+
+                       printf("\n");
+                       unimpl("UNKNOWN IOCTL %d\n", request);
+       }
+       return STATUS_SUCCESS;
+}
+
+DEVICE_FNS parallel_fns = {
+       parallel_create,
+       parallel_close,
+       parallel_read,
+       parallel_write,
+       parallel_device_control
+};