fix for mutex deadlock when closing and reopening the cable connection
[usb-driver] / usb-driver.c
CommitLineData
54357994 1/* libusb/ppdev connector for XILINX impact
f1405f13 2 *
3 * Copyright (c) 2007 Michael Gernoth <michael@gernoth.net>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
cdc711dc 23
24#define _GNU_SOURCE 1
25
cdc711dc 26#include <dlfcn.h>
27#include <stdarg.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <sys/time.h>
35#include <stdio.h>
2a7af812 36#include <signal.h>
9ba1e383 37#include <errno.h>
11d01742 38#include <inttypes.h>
54357994 39#include <sys/ioctl.h>
c42237a3
MG
40#include <sys/utsname.h>
41#include <bits/wordsize.h>
2c0c1255 42#include "usb-driver.h"
3e670223 43#include "config.h"
cbfa0ac6 44#include "xpcu.h"
cdc711dc 45
9c9fd67c 46static int (*ioctl_func) (int, int, void *) = NULL;
332ced7a 47static int windrvrfd = -1;
54357994 48static unsigned long ppbase = 0;
49static unsigned long ecpbase = 0;
25ba7a49 50static struct parport_config *pport = NULL;
be59993b
MG
51static FILE *modulesfp = NULL;
52static FILE *baseaddrfp = NULL;
53static int baseaddrnum = 0;
723d9aa0 54static int modules_read = 0;
292160ed 55
795992ad 56#define NO_WINDRVR 1
723d9aa0 57
58void hexdump(unsigned char *buf, int len) {
59 int i;
60
61 for(i=0; i<len; i++) {
62 fprintf(stderr,"%02x ", buf[i]);
63 if ((i % 16) == 15)
64 fprintf(stderr,"\n");
65 }
f1405f13 66 fprintf(stderr,"\n");
723d9aa0 67}
cdc711dc 68
cf55ed64 69
be59993b 70static int do_wdioctl(int fd, unsigned int request, unsigned char *wdioctl) {
cdc711dc 71 struct header_struct* wdheader = (struct header_struct*)wdioctl;
9c9fd67c 72 struct version_struct *version;
73 int ret = 0;
cdc711dc 74
da3ba95a 75 if (wdheader->magic != MAGIC) {
2c2119eb 76 fprintf(stderr,"!!!ERROR: magic header does not match!!!\n");
77 return (*ioctl_func) (fd, request, wdioctl);
cdc711dc 78 }
79
bdc65937 80 switch(request & ~(0xc0000000)) {
da3ba95a 81 case VERSION:
9c9fd67c 82 version = (struct version_struct*)(wdheader->data);
81cf3658 83 strcpy(version->version, "libusb-driver.so version: " USB_DRIVER_VERSION);
90831fba 84 version->versionul = 802;
f1405f13 85 DPRINTF("VERSION\n");
cdc711dc 86 break;
2c2119eb 87
88 case LICENSE:
f1405f13 89 DPRINTF("LICENSE\n");
2c2119eb 90 break;
91
f152c048 92 case CARD_REGISTER_OLD:
9c9fd67c 93 case CARD_REGISTER:
54357994 94 DPRINTF("CARD_REGISTER\n");
9c9fd67c 95 {
533f4b68 96 struct card_register* cr = (struct card_register*)(wdheader->data);
54357994 97
501f1c21 98 DPRINTF("-> Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
54357994 99 cr->Card.dwItems,
100 (unsigned long)cr->Card.Item[0].I.IO.dwAddr,
101 cr->Card.Item[0].I.IO.dwBytes,
102 cr->Card.Item[0].I.IO.dwBar);
103
501f1c21 104 DPRINTF("-> Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
54357994 105 cr->Card.dwItems,
106 (unsigned long)cr->Card.Item[1].I.IO.dwAddr,
107 cr->Card.Item[1].I.IO.dwBytes,
108 cr->Card.Item[1].I.IO.dwBar);
576995a8 109#ifndef NO_WINDRVR
110 ret = (*ioctl_func) (fd, request, wdioctl);
ac9e3f59 111#else
bccac33b 112
25ba7a49 113 pport = config_get((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
61e0de7a 114 if (!pport)
115 break;
116
25ba7a49 117 ret = pport->open((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
3e670223 118
5e3d963b 119 ppbase = (unsigned long)cr->Card.Item[0].I.IO.dwAddr;
bccac33b 120
5e3d963b 121 if (cr->Card.dwItems > 1 && cr->Card.Item[1].I.IO.dwAddr)
122 ecpbase = (unsigned long)cr->Card.Item[1].I.IO.dwAddr;
19b2e286 123
5e3d963b 124 if (ret >= 0) {
125 cr->hCard = ret;
126 } else {
19b2e286 127 cr->hCard = 0;
5e3d963b 128 }
576995a8 129#endif
501f1c21 130 DPRINTF("<-hCard: %lu\n", cr->hCard);
9c9fd67c 131 }
da3ba95a 132 break;
2c2119eb 133
da3ba95a 134 case USB_TRANSFER:
501f1c21 135 DPRINTF("USB_TRANSFER\n");
da3ba95a 136 {
137 struct usb_transfer *ut = (struct usb_transfer*)(wdheader->data);
138
723d9aa0 139#ifdef DEBUG
501f1c21 140 DPRINTF("-> unique: 0x%lx, pipe: %lu, read: %lu, options: %lx, size: %lu, timeout: %lx\n",
f1405f13 141 ut->dwUniqueID, ut->dwPipeNum, ut->fRead,
142 ut->dwOptions, ut->dwBufferSize, ut->dwTimeout);
cf55ed64 143 if (ut->dwPipeNum == 0) {
501f1c21 144 DPRINTF("-> setup packet: ");
cf55ed64
MG
145 hexdump(ut->SetupPacket, 8);
146 }
723d9aa0 147
9c9fd67c 148 if (!ut->fRead && ut->dwBufferSize)
149 {
150 hexdump(ut->pBuffer, ut->dwBufferSize);
9c9fd67c 151 }
723d9aa0 152#endif
9c9fd67c 153
795992ad 154#ifndef NO_WINDRVR
9c9fd67c 155 ret = (*ioctl_func) (fd, request, wdioctl);
411af373 156#else
19acdb82 157 ret = xpcu_transfer(ut);
292160ed 158#endif
9c9fd67c 159
723d9aa0 160#ifdef DEBUG
f1405f13 161 DPRINTF("Transferred: %lu (%s)\n",ut->dwBytesTransferred, (ut->fRead?"read":"write"));
9c9fd67c 162 if (ut->fRead && ut->dwBytesTransferred)
163 {
501f1c21 164 DPRINTF("<- Read: ");
9c9fd67c 165 hexdump(ut->pBuffer, ut->dwBytesTransferred);
166 }
723d9aa0 167#endif
da3ba95a 168 }
cdc711dc 169 break;
2c2119eb 170
f152c048 171 case INT_ENABLE_OLD:
da3ba95a 172 case INT_ENABLE:
f1405f13 173 DPRINTF("INT_ENABLE\n");
da3ba95a 174 {
9c9fd67c 175 struct interrupt *it = (struct interrupt*)(wdheader->data);
cdc711dc 176
501f1c21 177 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 178 it->hInterrupt, it->dwOptions,
179 it->dwCmds, it->fEnableOk, it->dwCounter,
180 it->dwLost, it->fStopped);
cdc711dc 181
501f1c21
MG
182#ifndef NO_WINDRVR
183 ret = (*ioctl_func) (fd, request, wdioctl);
184#else
19acdb82 185 ret = xpcu_int_state(it, ENABLE_INTERRUPT);
501f1c21
MG
186#endif
187
188 DPRINTF("<- Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
189 it->hInterrupt, it->dwOptions,
190 it->dwCmds, it->fEnableOk, it->dwCounter,
191 it->dwLost, it->fStopped);
9c9fd67c 192 }
cdc711dc 193
cdc711dc 194 break;
9c9fd67c 195
da3ba95a 196 case INT_DISABLE:
f1405f13 197 DPRINTF("INT_DISABLE\n");
da3ba95a 198 {
9c9fd67c 199 struct interrupt *it = (struct interrupt*)(wdheader->data);
da3ba95a 200
501f1c21 201 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 202 it->hInterrupt, it->dwOptions,
203 it->dwCmds, it->fEnableOk, it->dwCounter,
204 it->dwLost, it->fStopped);
795992ad 205#ifndef NO_WINDRVR
9c9fd67c 206 ret = (*ioctl_func) (fd, request, wdioctl);
e71b6bf3 207#else
19acdb82 208 ret = xpcu_int_state(it, DISABLE_INTERRUPT);
292160ed 209#endif
501f1c21 210 DPRINTF("<- Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 211 it->hInterrupt, it->dwOptions,
212 it->dwCmds, it->fEnableOk, it->dwCounter,
213 it->dwLost, it->fStopped);
da3ba95a 214 }
da3ba95a 215 break;
da3ba95a 216
9c9fd67c 217 case USB_SET_INTERFACE:
f1405f13 218 DPRINTF("USB_SET_INTERFACE\n");
da3ba95a 219 {
9c9fd67c 220 struct usb_set_interface *usi = (struct usb_set_interface*)(wdheader->data);
221
501f1c21 222 DPRINTF("-> unique: 0x%lx, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
f1405f13 223 usi->dwUniqueID, usi->dwInterfaceNum,
224 usi->dwAlternateSetting, usi->dwOptions);
795992ad 225#ifndef NO_WINDRVR
9c9fd67c 226 ret = (*ioctl_func) (fd, request, wdioctl);
2a7af812 227#else
19acdb82 228 ret = xpcu_set_interface(usi);
292160ed 229#endif
501f1c21 230 DPRINTF("<- unique: 0x%lx, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
f1405f13 231 usi->dwUniqueID, usi->dwInterfaceNum,
232 usi->dwAlternateSetting, usi->dwOptions);
da3ba95a 233 }
cdc711dc 234 break;
da3ba95a 235
f152c048 236 case USB_GET_DEVICE_DATA_OLD:
9c9fd67c 237 case USB_GET_DEVICE_DATA:
f1405f13 238 DPRINTF("USB_GET_DEVICE_DATA\n");
9c9fd67c 239 {
240 struct usb_get_device_data *ugdd = (struct usb_get_device_data*)(wdheader->data);
9c9fd67c 241
501f1c21 242 DPRINTF("-> unique: 0x%lx, bytes: %lu, options: %lx\n",
f1405f13 243 ugdd->dwUniqueID, ugdd->dwBytes,
244 ugdd->dwOptions);
245
19acdb82 246 ret = xpcu_deviceinfo(ugdd);
f92c0fbc 247
da3ba95a 248 }
9c9fd67c 249 break;
250
f152c048 251 case EVENT_REGISTER_OLD:
b0f621dd 252 case EVENT_REGISTER:
f1405f13 253 DPRINTF("EVENT_REGISTER\n");
b0f621dd 254 {
255 struct event *e = (struct event*)(wdheader->data);
f92c0fbc 256#ifdef DEBUG
b0f621dd 257 int i;
f92c0fbc 258#endif
b0f621dd 259
501f1c21 260 DPRINTF("-> handle: 0x%lx, action: %lu, status: %lu, eventid: %lu, cardtype: %lu, kplug: %lu, options: %lu, dev: %lx:%lx, unique: 0x%lx, ver: %lu, nummatch: %lu\n",
f1405f13 261 e->handle, e->dwAction,
262 e->dwStatus, e->dwEventId, e->dwCardType,
263 e->hKernelPlugIn, e->dwOptions,
264 e->u.Usb.deviceId.dwVendorId,
265 e->u.Usb.deviceId.dwProductId,
266 e->u.Usb.dwUniqueID, e->dwEventVer,
267 e->dwNumMatchTables);
268
795992ad 269#ifndef NO_WINDRVR
b0f621dd 270 ret = (*ioctl_func) (fd, request, wdioctl);
2a7af812 271#else
19acdb82 272 ret = xpcu_find(e);
292160ed 273#endif
b0f621dd 274
723d9aa0 275#ifdef DEBUG
501f1c21 276 DPRINTF("<- handle: 0x%lx, action: %lu, status: %lu, eventid: %lu, cardtype: %lu, kplug: %lu, options: %lu, dev: %lx:%lx, unique: 0x%lx, ver: %lu, nummatch: %lu\n",
f1405f13 277 e->handle, e->dwAction,
278 e->dwStatus, e->dwEventId, e->dwCardType,
279 e->hKernelPlugIn, e->dwOptions,
280 e->u.Usb.deviceId.dwVendorId,
281 e->u.Usb.deviceId.dwProductId,
282 e->u.Usb.dwUniqueID, e->dwEventVer,
283 e->dwNumMatchTables);
284
b0f621dd 285 for (i = 0; i < e->dwNumMatchTables; i++)
f1405f13 286 DPRINTF("match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
287 e->matchTables[i].VendorId,
288 e->matchTables[i].ProductId,
289 e->matchTables[i].bDeviceClass,
290 e->matchTables[i].bDeviceSubClass,
291 e->matchTables[i].bInterfaceClass,
292 e->matchTables[i].bInterfaceSubClass,
293 e->matchTables[i].bInterfaceProtocol);
723d9aa0 294#endif
b0f621dd 295 }
296 break;
297
f152c048 298 case TRANSFER_OLD:
da3ba95a 299 case TRANSFER:
f1405f13 300 DPRINTF("TRANSFER\n");
ac9e3f59 301 {
302 WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
303
1dac5195 304#ifndef NO_WINDRVR
305 ret = (*ioctl_func) (fd, request, wdioctl);
306#else
25ba7a49 307 ret = pport->transfer(tr, fd, request, ppbase, ecpbase, 1);
1dac5195 308#endif
ac9e3f59 309 }
9c9fd67c 310 break;
311
54357994 312 case MULTI_TRANSFER_OLD:
576995a8 313 case MULTI_TRANSFER:
314 DPRINTF("MULTI_TRANSFER\n");
ac9e3f59 315 {
316 WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
317 unsigned long num = wdheader->size/sizeof(WD_TRANSFER);
1dac5195 318#ifndef NO_WINDRVR
319 ret = (*ioctl_func) (fd, request, wdioctl);
320#else
25ba7a49 321 ret = pport->transfer(tr, fd, request, ppbase, ecpbase, num);
ac9e3f59 322#endif
ac9e3f59 323 }
576995a8 324 break;
325
da3ba95a 326 case EVENT_UNREGISTER:
f92c0fbc
MG
327 {
328 struct event *e = (struct event*)(wdheader->data);
329
330 DPRINTF("EVENT_UNREGISTER\n");
795992ad 331#ifndef NO_WINDRVR
f92c0fbc
MG
332 ret = (*ioctl_func) (fd, request, wdioctl);
333#else
19acdb82 334 ret = xpcu_close(e);
292160ed 335#endif
f92c0fbc 336 }
9c9fd67c 337 break;
338
da3ba95a 339 case INT_WAIT:
f1405f13 340 DPRINTF("INT_WAIT\n");
b0f621dd 341 {
342 struct interrupt *it = (struct interrupt*)(wdheader->data);
343
501f1c21 344 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 345 it->hInterrupt, it->dwOptions,
346 it->dwCmds, it->fEnableOk, it->dwCounter,
347 it->dwLost, it->fStopped);
b0f621dd 348
795992ad 349#ifndef NO_WINDRVR
b0f621dd 350 ret = (*ioctl_func) (fd, request, wdioctl);
292160ed 351#else
19acdb82 352 ret = xpcu_int_wait(it);
292160ed 353#endif
354
501f1c21 355 DPRINTF("<- INT_WAIT_RETURN: Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 356 it->hInterrupt, it->dwOptions, it->dwCmds,
357 it->fEnableOk, it->dwCounter, it->dwLost,
358 it->fStopped);
b0f621dd 359 }
9c9fd67c 360 break;
361
da3ba95a 362 case CARD_UNREGISTER:
f1405f13 363 DPRINTF("CARD_UNREGISTER\n");
54357994 364 {
365 struct card_register* cr = (struct card_register*)(wdheader->data);
366
501f1c21 367 DPRINTF("-> Addr: 0x%lx, bytes: %lu, bar: %lu\n",
54357994 368 (unsigned long)cr->Card.Item[0].I.IO.dwAddr,
369 cr->Card.Item[0].I.IO.dwBytes,
370 cr->Card.Item[0].I.IO.dwBar);
371
501f1c21 372 DPRINTF("-> hCard: %lu\n", cr->hCard);
54357994 373
795992ad 374#ifndef NO_WINDRVR
54357994 375 ret = (*ioctl_func) (fd, request, wdioctl);
376#else
72ce448b
MG
377 if (pport)
378 pport->close(cr->hCard);
379
380 pport = NULL;
292160ed 381#endif
54357994 382 }
9c9fd67c 383 break;
384
da3ba95a 385 case EVENT_PULL:
f1405f13 386 DPRINTF("EVENT_PULL\n");
b1831983 387 {
388 struct event *e = (struct event*)(wdheader->data);
723d9aa0 389#ifdef DEBUG
b1831983 390 int i;
391
501f1c21 392 DPRINTF("-> handle: 0x%lx, action: %lu, status: %lu, eventid: %lu, cardtype: %lx, kplug: %lu, options: %lu, dev: %lx:%lx, unique: 0x%lx, ver: %lu, nummatch: %lu\n",
f1405f13 393 e->handle, e->dwAction, e->dwStatus,
394 e->dwEventId, e->dwCardType, e->hKernelPlugIn,
395 e->dwOptions, e->u.Usb.deviceId.dwVendorId,
396 e->u.Usb.deviceId.dwProductId,
397 e->u.Usb.dwUniqueID, e->dwEventVer,
398 e->dwNumMatchTables);
399
b1831983 400 for (i = 0; i < e->dwNumMatchTables; i++)
501f1c21 401 DPRINTF("-> match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
f1405f13 402 e->matchTables[i].VendorId,
403 e->matchTables[i].ProductId,
404 e->matchTables[i].bDeviceClass,
405 e->matchTables[i].bDeviceSubClass,
406 e->matchTables[i].bInterfaceClass,
407 e->matchTables[i].bInterfaceSubClass,
408 e->matchTables[i].bInterfaceProtocol);
723d9aa0 409#endif
b1831983 410
795992ad 411#ifndef NO_WINDRVR
b1831983 412 ret = (*ioctl_func) (fd, request, wdioctl);
292160ed 413#else
19acdb82 414 ret = xpcu_found(e);
292160ed 415#endif
b1831983 416
723d9aa0 417#ifdef DEBUG
501f1c21 418 DPRINTF("<- handle: 0x%lx, action: %lu, status: %lu, eventid: %lu, cardtype: %lx, kplug: %lu, options: %lu, dev: %lx:%lx, unique: 0x%lx, ver: %lu, nummatch: %lu\n",
f1405f13 419 e->handle, e->dwAction, e->dwStatus,
420 e->dwEventId, e->dwCardType, e->hKernelPlugIn,
421 e->dwOptions, e->u.Usb.deviceId.dwVendorId,
422 e->u.Usb.deviceId.dwProductId,
423 e->u.Usb.dwUniqueID, e->dwEventVer,
424 e->dwNumMatchTables);
425
b1831983 426 for (i = 0; i < e->dwNumMatchTables; i++)
501f1c21 427 DPRINTF("<- match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
f1405f13 428 e->matchTables[i].VendorId,
429 e->matchTables[i].ProductId,
430 e->matchTables[i].bDeviceClass,
431 e->matchTables[i].bDeviceSubClass,
432 e->matchTables[i].bInterfaceClass,
433 e->matchTables[i].bInterfaceSubClass,
434 e->matchTables[i].bInterfaceProtocol);
723d9aa0 435#endif
ca18111b 436
b1831983 437 }
9c9fd67c 438 break;
439
da3ba95a 440 default:
292160ed 441 fprintf(stderr,"!!!Unsupported IOCTL: %x!!!\n", request);
795992ad 442#ifndef NO_WINDRVR
9c9fd67c 443 ret = (*ioctl_func) (fd, request, wdioctl);
292160ed 444#endif
445 break;
cdc711dc 446 }
da3ba95a 447
9c9fd67c 448 return ret;
cdc711dc 449}
450
54357994 451int ioctl(int fd, unsigned long int request, ...) {
dbda1264 452 va_list args;
453 void *argp;
454 int ret;
455
456 if (!ioctl_func)
f1405f13 457 ioctl_func = (int (*) (int, int, void *)) dlsym (RTLD_NEXT, "ioctl");
dbda1264 458
459 va_start (args, request);
460 argp = va_arg (args, void *);
461 va_end (args);
462
332ced7a 463 if (fd == windrvrfd)
dbda1264 464 ret = do_wdioctl(fd, request, argp);
465 else
466 ret = (*ioctl_func) (fd, request, argp);
467
468 return ret;
469}
cdc711dc 470
be452175 471int open (const char *pathname, int flags, ...) {
472 static int (*func) (const char *, int, mode_t) = NULL;
cdc711dc 473 mode_t mode = 0;
474 va_list args;
475 int fd;
476
477 if (!func)
f1405f13 478 func = (int (*) (const char *, int, mode_t)) dlsym (RTLD_NEXT, "open");
cdc711dc 479
480 if (flags & O_CREAT) {
481 va_start(args, flags);
482 mode = va_arg(args, mode_t);
483 va_end(args);
484 }
485
cdc711dc 486 if (!strcmp (pathname, "/dev/windrvr6")) {
f1405f13 487 DPRINTF("opening windrvr6\n");
795992ad 488#ifdef NO_WINDRVR
01b99d52 489 windrvrfd = fd = (*func) ("/dev/null", flags, mode);
490#else
491 windrvrfd = fd = (*func) (pathname, flags, mode);
492#endif
723d9aa0 493
494 return fd;
cdc711dc 495 }
496
723d9aa0 497 return (*func) (pathname, flags, mode);
cdc711dc 498}
499
723d9aa0 500int close(int fd) {
501 static int (*func) (int) = NULL;
cdc711dc 502
723d9aa0 503 if (!func)
f1405f13 504 func = (int (*) (int)) dlsym(RTLD_NEXT, "close");
723d9aa0 505
11d01742 506 if (fd == windrvrfd && windrvrfd >= 0) {
f1405f13 507 DPRINTF("close windrvrfd\n");
332ced7a 508 windrvrfd = -1;
cdc711dc 509 }
cdc711dc 510
723d9aa0 511 return (*func) (fd);
cdc711dc 512}
513
723d9aa0 514FILE *fopen(const char *path, const char *mode) {
515 FILE *ret;
516 static FILE* (*func) (const char*, const char*) = NULL;
0dca330e 517 char buf[256];
518 int i;
ca18111b 519
520 if (!func)
f1405f13 521 func = (FILE* (*) (const char*, const char*)) dlsym(RTLD_NEXT, "fopen");
ca18111b 522
3e670223 523 for (i = 0; i < 4; i++) {
524 snprintf(buf, sizeof(buf), "/proc/sys/dev/parport/parport%d/base-addr", i);
525 if (!strcmp(path, buf)) {
526 DPRINTF("open base-addr of parport%d\n", i);
527 if (config_is_real_pport(i)) {
528 ret = (*func) (path, mode);
529 } else {
530 ret = (*func) ("/dev/null", mode);
531 }
532
533 if (ret) {
534 baseaddrfp = ret;
535 baseaddrnum = i;
536 }
537
538 return ret;
539 }
540 }
541
542 ret = (*func) (path, mode);
ca18111b 543
0dca330e 544 if (!strcmp(path, "/proc/modules")) {
f1405f13 545 DPRINTF("opening /proc/modules\n");
723d9aa0 546#ifdef NO_WINDRVR
dbda1264 547 modulesfp = ret;
723d9aa0 548 modules_read = 0;
549#endif
550 }
cdc711dc 551
552 return ret;
553}
554
dbda1264 555char *fgets(char *s, int size, FILE *stream) {
556 static char* (*func) (char*, int, FILE*) = NULL;
16f6b164 557 const char modules[][256] = {"windrvr6 1 0 - Live 0xdeadbeef\n", "parport_pc 1 0 - Live 0xdeadbeef\n"};
0dca330e 558 char buf[256];
dbda1264 559 char *ret = NULL;
560
cdc711dc 561
562 if (!func)
f1405f13 563 func = (char* (*) (char*, int, FILE*)) dlsym(RTLD_NEXT, "fgets");
723d9aa0 564
dbda1264 565 if (modulesfp == stream) {
54357994 566 if (modules_read < sizeof(modules) / sizeof(modules[0])) {
16f6b164 567 strcpy(s, modules[modules_read]);
dbda1264 568 ret = s;
16f6b164 569 modules_read++;
dbda1264 570 }
0dca330e 571 } else if (baseaddrfp == stream) {
572 snprintf(s, sizeof(buf), "%d\t%d\n",
573 (baseaddrnum) * 0x10,
574 ((baseaddrnum) * 0x10) + 0x400);
575 ret = s;
723d9aa0 576 } else {
dbda1264 577 ret = (*func)(s,size,stream);
723d9aa0 578 }
cdc711dc 579
580 return ret;
581}
582
dbda1264 583int fclose(FILE *fp) {
584 static int (*func) (FILE*) = NULL;
cdc711dc 585
dbda1264 586 if (!func)
f1405f13 587 func = (int (*) (FILE*)) dlsym(RTLD_NEXT, "fclose");
cdc711dc 588
dbda1264 589 if (fp == modulesfp) {
590 modulesfp = NULL;
591 }
0dca330e 592
593 if (fp == baseaddrfp) {
594 baseaddrfp = NULL;
595 }
dbda1264 596
597 return (*func)(fp);
cdc711dc 598}
419f2c98 599
600int access(const char *pathname, int mode) {
601 static int (*func) (const char*, int);
602
603 if (!func)
f1405f13 604 func = (int (*) (const char*, int)) dlsym(RTLD_NEXT, "access");
3eee002c 605
b8b756f5 606 if (pathname && !strcmp(pathname, "/dev/windrvr6")) {
419f2c98 607 return 0;
608 } else {
609 return (*func)(pathname, mode);
610 }
611}
c42237a3
MG
612
613#if __WORDSIZE == 32
614int uname (struct utsname *__name) {
615 static int (*func) (struct utsname*);
616 int ret;
617
618 if (!func)
619 func = (int (*) (struct utsname*)) dlsym(RTLD_NEXT, "uname");
620
621 ret = (*func)(__name);
622
623 if (ret == 0 && (!strcmp(__name->machine, "x86_64"))) {
624 strcpy(__name->machine, "i686");
625 }
626
627 return ret;
628}
629#endif
Impressum, Datenschutz