1 /* -*- c-basic-offset: 8 -*- 2 rdesktop: A Remote Desktop Protocol client. 3 Copyright (C) Matthew Chapman 1999-2005 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License along 16 with this program; if not, write to the Free Software Foundation, Inc., 17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 #define MAX_PARALLEL_DEVICES 1 20 21 #define FILE_DEVICE_PARALLEL 0x22 22 23 #define IOCTL_PAR_QUERY_RAW_DEVICE_ID 0x0c 24 25 #include "rdesktop.h" 26 #include <unistd.h> 27 #include <fcntl.h> 28 #include <sys/ioctl.h> 29 #include <errno.h> 30 31 #if defined(__linux__) 32 #include <linux/lp.h> 33 #endif 34 35 /* Enumeration of devices from rdesktop.c */ 36 /* returns numer of units found and initialized. */ 37 /* optarg looks like ':LPT1=/dev/lp0' */ 38 /* when it arrives to this function. */ 39 int 40 parallel_enum_devices(RDPCLIENT * This, uint32 * id, char *optarg) 41 { 42 PARALLEL_DEVICE *ppar_info; 43 44 char *pos = optarg; 45 char *pos2; 46 int count = 0; 47 48 /* skip the first colon */ 49 optarg++; 50 while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES) 51 { 52 ppar_info = (PARALLEL_DEVICE *) xmalloc(sizeof(PARALLEL_DEVICE)); 53 54 pos2 = next_arg(optarg, '='); 55 strcpy(This->rdpdr_device[*id].name, optarg); 56 57 toupper_str(This->rdpdr_device[*id].name); 58 59 This->rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1); 60 strcpy(This->rdpdr_device[*id].local_path, pos2); 61 printf("PARALLEL %s to %s\n", optarg, pos2); 62 63 /* set device type */ 64 This->rdpdr_device[*id].device_type = DEVICE_TYPE_PARALLEL; 65 This->rdpdr_device[*id].pdevice_data = (void *) ppar_info; 66 This->rdpdr_device[*id].handle = 0; 67 count++; 68 (*id)++; 69 70 optarg = pos; 71 } 72 return count; 73 } 74 75 static NTSTATUS 76 parallel_create(RDPCLIENT * This, uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition, 77 uint32 flags, char *filename, NTHANDLE * handle) 78 { 79 int parallel_fd; 80 81 parallel_fd = open(This->rdpdr_device[device_id].local_path, O_RDWR); 82 if (parallel_fd == -1) 83 { 84 perror("open"); 85 return STATUS_ACCESS_DENIED; 86 } 87 88 /* all read and writes should be non blocking */ 89 if (fcntl(parallel_fd, F_SETFL, O_NONBLOCK) == -1) 90 perror("fcntl"); 91 92 #if defined(LPABORT) 93 /* Retry on errors */ 94 ioctl(parallel_fd, LPABORT, (int) 1); 95 #endif 96 97 This->rdpdr_device[device_id].handle = parallel_fd; 98 99 *handle = parallel_fd; 100 101 return STATUS_SUCCESS; 102 } 103 104 static NTSTATUS 105 parallel_close(RDPCLIENT * This, NTHANDLE handle) 106 { 107 int i = get_device_index(This, handle); 108 if (i >= 0) 109 This->rdpdr_device[i].handle = 0; 110 close(handle); 111 return STATUS_SUCCESS; 112 } 113 114 static NTSTATUS 115 parallel_read(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result) 116 { 117 *result = read(handle, data, length); 118 return STATUS_SUCCESS; 119 } 120 121 static NTSTATUS 122 parallel_write(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result) 123 { 124 int rc = STATUS_SUCCESS; 125 126 int n = write(handle, data, length); 127 if (n < 0) 128 { 129 #if defined(LPGETSTATUS) 130 int status; 131 #endif 132 133 *result = 0; 134 switch (errno) 135 { 136 case EAGAIN: 137 rc = STATUS_DEVICE_OFF_LINE; 138 case ENOSPC: 139 rc = STATUS_DEVICE_PAPER_EMPTY; 140 case EIO: 141 rc = STATUS_DEVICE_OFF_LINE; 142 default: 143 rc = STATUS_DEVICE_POWERED_OFF; 144 } 145 #if defined(LPGETSTATUS) 146 if (ioctl(handle, LPGETSTATUS, &status) == 0) 147 { 148 /* coming soon: take care for the printer status */ 149 printf("parallel_write: status = %d, errno = %d\n", status, errno); 150 } 151 #endif 152 } 153 *result = n; 154 return rc; 155 } 156 157 static NTSTATUS 158 parallel_device_control(RDPCLIENT * This, NTHANDLE handle, uint32 request, STREAM in, STREAM out) 159 { 160 if ((request >> 16) != FILE_DEVICE_PARALLEL) 161 return STATUS_INVALID_PARAMETER; 162 163 /* extract operation */ 164 request >>= 2; 165 request &= 0xfff; 166 167 printf("PARALLEL IOCTL %d: ", request); 168 169 switch (request) 170 { 171 case IOCTL_PAR_QUERY_RAW_DEVICE_ID: 172 173 default: 174 175 printf("\n"); 176 unimpl("UNKNOWN IOCTL %d\n", request); 177 } 178 return STATUS_SUCCESS; 179 } 180 181 DEVICE_FNS parallel_fns = { 182 parallel_create, 183 parallel_close, 184 parallel_read, 185 parallel_write, 186 parallel_device_control 187 }; 188