Rewrite GetCommState16 using GetCommState.
[wine/wine-kai.git] / msdos / ppdev.c
blob6be95ec9fe6c8f1b82a444d62d3aeda2ca1f1e8f
1 /*
2 * Parallel-port device support
3 */
5 #include "config.h"
7 #include "debugtools.h"
9 DEFAULT_DEBUG_CHANNEL(int);
11 #ifdef HAVE_PPDEV
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18 #include <errno.h>
19 #include <linux/ppdev.h>
21 #include "winerror.h"
22 #include "winreg.h"
25 typedef struct _PPDEVICESTRUCT{
26 int fd; /* NULL if device not available */
27 char *devicename;
28 int userbase; /* where wine thinks the ports are*/
29 DWORD lastaccess; /* or NULL if release */
30 int timeout; /* time in second of inactivity to release the port*/
31 } PPDeviceStruct;
33 static PPDeviceStruct PPDeviceList[5];
34 static int PPDeviceNum=0;
36 static int IO_pp_sort(const void *p1,const void *p2)
38 return ((PPDeviceStruct*)p1)->userbase - ((PPDeviceStruct*)p2)->userbase;
41 /* IO_pp_init
43 * Read the ppdev entries from wine.conf, open the device and check
44 * for nescessary IOCTRL
45 * Report verbose about possible errors
47 char IO_pp_init(void)
49 char name[80];
50 char buffer[1024];
51 HKEY hkey;
52 char temp[256];
53 int i,idx=0,fd,res,userbase,nports=0;
54 char * timeout;
55 char ret=1;
56 int lasterror;
58 TRACE("\n");
59 if (RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\ppdev", &hkey ) != ERROR_SUCCESS)
60 return 1;
62 for (;;)
64 DWORD type, count = sizeof(buffer), name_len = sizeof(name);
66 if (RegEnumValueA( hkey, idx, name, &name_len, NULL, &type, buffer, &count )!= ERROR_SUCCESS)
67 break;
69 idx++;
70 if(nports >4)
72 FIXME("Make the PPDeviceList larger then 5 elements\n");
73 break;
75 TRACE("Device '%s' at virtual userbase '%s'\n", buffer,name);
76 timeout = strchr(buffer,',');
77 if (timeout)
78 *timeout++=0;
79 fd=open(buffer,O_RDWR);
80 lasterror=errno;
81 if (fd == -1)
83 WARN("Configuration: No access to %s Cause: %s\n",buffer,strerror(lasterror));
84 WARN("Rejecting configuration item\n");
85 if (lasterror == ENODEV)
86 FIXME("Is the ppdev module loaded?\n");
87 continue;
89 userbase = strtol(name,(char **)NULL, 16);
90 if ( errno == ERANGE)
92 WARN("Configuration: Invalid base %s for %s\n",name,buffer);
93 WARN("Rejecting configuration item\n");
94 continue;
96 if (ioctl (fd,PPEXCL,0))
98 ERR("PPEXCL IOCTL rejected for device %s\n",buffer);
99 ERR("Check that PPDEV module is loaded!\n");
100 ERR("Perhaps the device is already in use or non-existant\n");
101 continue;
103 if (ioctl (fd,PPCLAIM,0))
105 ERR("PPCLAIM rejected %s\n",buffer);
106 ERR("Perhaps the device is already in use or non-existant\n");
107 continue;
109 if (nports > 0)
111 for (i=0; i<= nports; i++)
113 if (PPDeviceList[i].userbase == userbase)
115 WARN("Configuration: %s uses the same virtual ports as %s\n",
116 buffer,PPDeviceList[0].devicename);
117 WARN("Configuration: Rejecting configuration item");
118 userbase = 0;
119 break;
122 if (!userbase) continue;
124 /* Check for the minimum required IOCTLS */
125 if ((ioctl(fd,PPRDATA,&res))||
126 (ioctl(fd,PPRCONTROL,&res))||
127 (ioctl(fd,PPRCONTROL,&res)))
129 ERR("PPUSER IOCTL not available for parport device %s\n",temp);
130 continue;
132 PPDeviceList[nports].devicename = malloc(sizeof(buffer)+1);
133 if (!PPDeviceList[nports].devicename)
135 ERR("No (more)space for devicename\n");
136 break;
138 strcpy(PPDeviceList[nports].devicename,buffer);
139 PPDeviceList[nports].fd = fd;
140 PPDeviceList[nports].userbase = userbase;
141 PPDeviceList[nports].lastaccess=GetTickCount();
142 if (timeout)
144 PPDeviceList[nports].timeout = strtol(timeout,(char **)NULL, 10);
145 if (errno == ERANGE)
147 WARN("Configuration:Invalid timeout %s in configuration for %s, Setting to 0\n",
148 timeout,buffer);
149 PPDeviceList[nports].timeout = 0;
152 else
153 PPDeviceList[nports].timeout = 0;
154 nports++;
156 TRACE("found %d ports\n",nports);
157 RegCloseKey( hkey );
159 PPDeviceNum= nports;
160 if (nports > 1)
161 /* sort in accending order for userbase for faster access*/
162 qsort (PPDeviceList,PPDeviceNum,sizeof(PPDeviceStruct),IO_pp_sort);
164 if (nports)
165 ret=0;
166 for (idx= 0;idx<PPDeviceNum; idx++)
167 TRACE("found device %s userbase %x fd %x timeout %d\n",
168 PPDeviceList[idx].devicename, PPDeviceList[idx].userbase,
169 PPDeviceList[idx].fd,PPDeviceList[idx].timeout);
170 /* FIXME:
171 register a timer callback perhaps every 30 second to release unused ports
172 Set lastaccess = 0 as indicator when port was released
174 return ret;
177 /* IO_pp_do_access
179 * Do the actual IOCTL
180 * Return NULL on success
182 static int IO_pp_do_access(int idx,int ppctl, DWORD* res)
184 if (!PPDeviceList[idx].lastaccess)
185 /* TIMER callback has released the device after some time of inactivity
186 Reclaim the device
187 !!!!!!THIS MAY UNINTERRUPTIPLE BLOCK IF SOME OTHER DEVICE
188 !!!!!! HAS CLAIMED THE SAME PORT
190 if (ioctl(PPDeviceList[idx].fd,PPCLAIM,0))
192 ERR("Can't reclaim device %s, PPUSER/PPDEV handling confused\n",
193 PPDeviceList[idx].devicename);
194 return 1;
196 PPDeviceList[idx].lastaccess=GetTickCount();
197 return ioctl(PPDeviceList[idx].fd,ppctl,res);
200 /* IO_pp_inp
202 * Check if we can satisfy the INP command with some of the configured PPDEV deviced
203 * Return NULL on success
205 int IO_pp_inp(int port, DWORD* res)
207 int idx,j=0;
209 for (idx=0;idx<PPDeviceNum ;idx++)
211 j = port - PPDeviceList[idx].userbase;
212 if (j <0) return 1;
213 switch (j)
215 case 0:
216 return IO_pp_do_access(idx,PPRDATA,res);
217 case 1:
218 return IO_pp_do_access(idx,PPRSTATUS,res);
219 case 2:
220 return IO_pp_do_access(idx,PPRCONTROL,res);
221 case 0x400:
222 case 0x402:
223 case 3:
224 case 4:
225 case 0x401:
226 FIXME("Port 0x%x not accessible for reading with ppdev\n",port);
227 FIXME("If this is causing problems, try direct port access\n");
228 return 1;
229 default:
230 break;
233 return 1;
236 /* IO_pp_outp
238 * Check if we can satisfy the INP command with some of the configured PPDEV deviced
239 * Return NULL on success
241 BOOL IO_pp_outp(int port, DWORD* res)
243 int idx,j=0;
245 for (idx=0;idx<PPDeviceNum ;idx++)
247 j = port - PPDeviceList[idx].userbase;
248 if (j <0) return 1;
249 switch (j)
251 case 0:
252 return IO_pp_do_access(idx,PPWDATA,res);
253 case 2:
254 return IO_pp_do_access(idx,PPWCONTROL,res);
255 case 1:
256 case 0x400:
257 case 0x402:
258 case 3:
259 case 4:
260 case 0x401:
261 FIXME("Port %d not accessible for writing with ppdev\n",port);
262 FIXME("If this is causing problems, try direct port access\n");
263 return 1;
264 default:
265 break;
268 return TRUE;
272 #else /* HAVE_PPDEV */
274 char IO_pp_init(void)
276 return 1;
279 int IO_pp_inp(int port, DWORD* res)
281 return 1;
284 BOOL IO_pp_outp(int port, DWORD* res)
286 return TRUE;
288 #endif /* HAVE_PPDEV */