update links for xc3sprog
[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>
1fc8f7a4
MG
42#include <sys/ipc.h>
43#include <sys/sem.h>
a90dd207 44#include <sys/mman.h>
daa4fc04
MG
45#include <syscall.h>
46#include <linux/personality.h>
2c0c1255 47#include "usb-driver.h"
3e670223 48#include "config.h"
cbfa0ac6 49#include "xpcu.h"
cdc711dc 50
9c9fd67c 51static int (*ioctl_func) (int, int, void *) = NULL;
9bfaca62
MG
52static int *windrvrfds = NULL;
53static int windrvrfds_count = 0;
54357994 54static unsigned long ppbase = 0;
55static unsigned long ecpbase = 0;
25ba7a49 56static struct parport_config *pport = NULL;
be59993b
MG
57static FILE *modulesfp = NULL;
58static FILE *baseaddrfp = NULL;
59static int baseaddrnum = 0;
723d9aa0 60static int modules_read = 0;
292160ed 61
795992ad 62#define NO_WINDRVR 1
723d9aa0 63
325556c9 64void hexdump(unsigned char *buf, int len, char *prefix) {
765c485a 65 int i = 0;
723d9aa0 66
765c485a
MG
67 fprintf(stderr, "%s %03x: ", prefix, i);
68 for(i = 0; i<len; i++) {
723d9aa0 69 fprintf(stderr,"%02x ", buf[i]);
765c485a
MG
70 if ((i % 16) == 7)
71 fprintf(stderr," ");
72 if (((i % 16) == 15) && ((i+1) < len))
73 fprintf(stderr,"\n%s %03x: ", prefix, i+1);
723d9aa0 74 }
f1405f13 75 fprintf(stderr,"\n");
723d9aa0 76}
cdc711dc 77
cf55ed64 78
be59993b 79static int do_wdioctl(int fd, unsigned int request, unsigned char *wdioctl) {
cdc711dc 80 struct header_struct* wdheader = (struct header_struct*)wdioctl;
9c9fd67c 81 struct version_struct *version;
82 int ret = 0;
cdc711dc 83
da3ba95a 84 if (wdheader->magic != MAGIC) {
2c2119eb 85 fprintf(stderr,"!!!ERROR: magic header does not match!!!\n");
86 return (*ioctl_func) (fd, request, wdioctl);
cdc711dc 87 }
88
bdc65937 89 switch(request & ~(0xc0000000)) {
da3ba95a 90 case VERSION:
9c9fd67c 91 version = (struct version_struct*)(wdheader->data);
81cf3658 92 strcpy(version->version, "libusb-driver.so version: " USB_DRIVER_VERSION);
90831fba 93 version->versionul = 802;
f1405f13 94 DPRINTF("VERSION\n");
cdc711dc 95 break;
2c2119eb 96
97 case LICENSE:
f1405f13 98 DPRINTF("LICENSE\n");
2c2119eb 99 break;
100
f152c048 101 case CARD_REGISTER_OLD:
9c9fd67c 102 case CARD_REGISTER:
54357994 103 DPRINTF("CARD_REGISTER\n");
9c9fd67c 104 {
533f4b68 105 struct card_register* cr = (struct card_register*)(wdheader->data);
54357994 106
501f1c21 107 DPRINTF("-> Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
54357994 108 cr->Card.dwItems,
109 (unsigned long)cr->Card.Item[0].I.IO.dwAddr,
110 cr->Card.Item[0].I.IO.dwBytes,
111 cr->Card.Item[0].I.IO.dwBar);
112
501f1c21 113 DPRINTF("-> Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
54357994 114 cr->Card.dwItems,
115 (unsigned long)cr->Card.Item[1].I.IO.dwAddr,
116 cr->Card.Item[1].I.IO.dwBytes,
117 cr->Card.Item[1].I.IO.dwBar);
576995a8 118#ifndef NO_WINDRVR
119 ret = (*ioctl_func) (fd, request, wdioctl);
ac9e3f59 120#else
4c90fa39 121 cr->hCard = 0;
bccac33b 122
25ba7a49 123 pport = config_get((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
61e0de7a 124 if (!pport)
125 break;
126
25ba7a49 127 ret = pport->open((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
3e670223 128
5e3d963b 129 ppbase = (unsigned long)cr->Card.Item[0].I.IO.dwAddr;
bccac33b 130
5e3d963b 131 if (cr->Card.dwItems > 1 && cr->Card.Item[1].I.IO.dwAddr)
132 ecpbase = (unsigned long)cr->Card.Item[1].I.IO.dwAddr;
19b2e286 133
5e3d963b 134 if (ret >= 0) {
135 cr->hCard = ret;
136 } else {
19b2e286 137 cr->hCard = 0;
5e3d963b 138 }
576995a8 139#endif
501f1c21 140 DPRINTF("<-hCard: %lu\n", cr->hCard);
9c9fd67c 141 }
da3ba95a 142 break;
2c2119eb 143
da3ba95a 144 case USB_TRANSFER:
501f1c21 145 DPRINTF("USB_TRANSFER\n");
da3ba95a 146 {
147 struct usb_transfer *ut = (struct usb_transfer*)(wdheader->data);
148
723d9aa0 149#ifdef DEBUG
501f1c21 150 DPRINTF("-> unique: 0x%lx, pipe: %lu, read: %lu, options: %lx, size: %lu, timeout: %lx\n",
f1405f13 151 ut->dwUniqueID, ut->dwPipeNum, ut->fRead,
152 ut->dwOptions, ut->dwBufferSize, ut->dwTimeout);
cf55ed64 153 if (ut->dwPipeNum == 0) {
325556c9
MG
154 DPRINTF("-> setup packet:");
155 hexdump(ut->SetupPacket, 8, "");
cf55ed64 156 }
723d9aa0 157
9c9fd67c 158 if (!ut->fRead && ut->dwBufferSize)
159 {
325556c9 160 hexdump(ut->pBuffer, ut->dwBufferSize, "->");
9c9fd67c 161 }
723d9aa0 162#endif
9c9fd67c 163
795992ad 164#ifndef NO_WINDRVR
9c9fd67c 165 ret = (*ioctl_func) (fd, request, wdioctl);
411af373 166#else
19acdb82 167 ret = xpcu_transfer(ut);
292160ed 168#endif
9c9fd67c 169
723d9aa0 170#ifdef DEBUG
f1405f13 171 DPRINTF("Transferred: %lu (%s)\n",ut->dwBytesTransferred, (ut->fRead?"read":"write"));
9c9fd67c 172 if (ut->fRead && ut->dwBytesTransferred)
173 {
325556c9 174 hexdump(ut->pBuffer, ut->dwBytesTransferred, "<-");
9c9fd67c 175 }
723d9aa0 176#endif
da3ba95a 177 }
cdc711dc 178 break;
2c2119eb 179
f152c048 180 case INT_ENABLE_OLD:
da3ba95a 181 case INT_ENABLE:
f1405f13 182 DPRINTF("INT_ENABLE\n");
da3ba95a 183 {
9c9fd67c 184 struct interrupt *it = (struct interrupt*)(wdheader->data);
cdc711dc 185
501f1c21 186 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 187 it->hInterrupt, it->dwOptions,
188 it->dwCmds, it->fEnableOk, it->dwCounter,
189 it->dwLost, it->fStopped);
cdc711dc 190
501f1c21
MG
191#ifndef NO_WINDRVR
192 ret = (*ioctl_func) (fd, request, wdioctl);
193#else
19acdb82 194 ret = xpcu_int_state(it, ENABLE_INTERRUPT);
501f1c21
MG
195#endif
196
197 DPRINTF("<- Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
198 it->hInterrupt, it->dwOptions,
199 it->dwCmds, it->fEnableOk, it->dwCounter,
200 it->dwLost, it->fStopped);
9c9fd67c 201 }
cdc711dc 202
cdc711dc 203 break;
9c9fd67c 204
da3ba95a 205 case INT_DISABLE:
f1405f13 206 DPRINTF("INT_DISABLE\n");
da3ba95a 207 {
9c9fd67c 208 struct interrupt *it = (struct interrupt*)(wdheader->data);
da3ba95a 209
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);
795992ad 214#ifndef NO_WINDRVR
9c9fd67c 215 ret = (*ioctl_func) (fd, request, wdioctl);
e71b6bf3 216#else
19acdb82 217 ret = xpcu_int_state(it, DISABLE_INTERRUPT);
292160ed 218#endif
501f1c21 219 DPRINTF("<- Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 220 it->hInterrupt, it->dwOptions,
221 it->dwCmds, it->fEnableOk, it->dwCounter,
222 it->dwLost, it->fStopped);
da3ba95a 223 }
da3ba95a 224 break;
da3ba95a 225
9c9fd67c 226 case USB_SET_INTERFACE:
f1405f13 227 DPRINTF("USB_SET_INTERFACE\n");
da3ba95a 228 {
9c9fd67c 229 struct usb_set_interface *usi = (struct usb_set_interface*)(wdheader->data);
230
501f1c21 231 DPRINTF("-> unique: 0x%lx, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
f1405f13 232 usi->dwUniqueID, usi->dwInterfaceNum,
233 usi->dwAlternateSetting, usi->dwOptions);
795992ad 234#ifndef NO_WINDRVR
9c9fd67c 235 ret = (*ioctl_func) (fd, request, wdioctl);
2a7af812 236#else
19acdb82 237 ret = xpcu_set_interface(usi);
292160ed 238#endif
501f1c21 239 DPRINTF("<- unique: 0x%lx, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
f1405f13 240 usi->dwUniqueID, usi->dwInterfaceNum,
241 usi->dwAlternateSetting, usi->dwOptions);
da3ba95a 242 }
cdc711dc 243 break;
da3ba95a 244
f152c048 245 case USB_GET_DEVICE_DATA_OLD:
9c9fd67c 246 case USB_GET_DEVICE_DATA:
f1405f13 247 DPRINTF("USB_GET_DEVICE_DATA\n");
9c9fd67c 248 {
249 struct usb_get_device_data *ugdd = (struct usb_get_device_data*)(wdheader->data);
9c9fd67c 250
501f1c21 251 DPRINTF("-> unique: 0x%lx, bytes: %lu, options: %lx\n",
f1405f13 252 ugdd->dwUniqueID, ugdd->dwBytes,
253 ugdd->dwOptions);
254
19acdb82 255 ret = xpcu_deviceinfo(ugdd);
f92c0fbc 256
da3ba95a 257 }
9c9fd67c 258 break;
259
f152c048 260 case EVENT_REGISTER_OLD:
b0f621dd 261 case EVENT_REGISTER:
f1405f13 262 DPRINTF("EVENT_REGISTER\n");
b0f621dd 263 {
264 struct event *e = (struct event*)(wdheader->data);
f92c0fbc 265#ifdef DEBUG
b0f621dd 266 int i;
f92c0fbc 267#endif
b0f621dd 268
501f1c21 269 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 270 e->handle, e->dwAction,
271 e->dwStatus, e->dwEventId, e->dwCardType,
272 e->hKernelPlugIn, e->dwOptions,
273 e->u.Usb.deviceId.dwVendorId,
274 e->u.Usb.deviceId.dwProductId,
275 e->u.Usb.dwUniqueID, e->dwEventVer,
276 e->dwNumMatchTables);
277
795992ad 278#ifndef NO_WINDRVR
b0f621dd 279 ret = (*ioctl_func) (fd, request, wdioctl);
2a7af812 280#else
19acdb82 281 ret = xpcu_find(e);
292160ed 282#endif
b0f621dd 283
723d9aa0 284#ifdef DEBUG
501f1c21 285 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 286 e->handle, e->dwAction,
287 e->dwStatus, e->dwEventId, e->dwCardType,
288 e->hKernelPlugIn, e->dwOptions,
289 e->u.Usb.deviceId.dwVendorId,
290 e->u.Usb.deviceId.dwProductId,
291 e->u.Usb.dwUniqueID, e->dwEventVer,
292 e->dwNumMatchTables);
293
b0f621dd 294 for (i = 0; i < e->dwNumMatchTables; i++)
f1405f13 295 DPRINTF("match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
296 e->matchTables[i].VendorId,
297 e->matchTables[i].ProductId,
298 e->matchTables[i].bDeviceClass,
299 e->matchTables[i].bDeviceSubClass,
300 e->matchTables[i].bInterfaceClass,
301 e->matchTables[i].bInterfaceSubClass,
302 e->matchTables[i].bInterfaceProtocol);
723d9aa0 303#endif
b0f621dd 304 }
305 break;
306
f152c048 307 case TRANSFER_OLD:
da3ba95a 308 case TRANSFER:
f1405f13 309 DPRINTF("TRANSFER\n");
ac9e3f59 310 {
311 WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
312
1dac5195 313#ifndef NO_WINDRVR
314 ret = (*ioctl_func) (fd, request, wdioctl);
315#else
25ba7a49 316 ret = pport->transfer(tr, fd, request, ppbase, ecpbase, 1);
1dac5195 317#endif
ac9e3f59 318 }
9c9fd67c 319 break;
320
54357994 321 case MULTI_TRANSFER_OLD:
576995a8 322 case MULTI_TRANSFER:
323 DPRINTF("MULTI_TRANSFER\n");
ac9e3f59 324 {
325 WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
326 unsigned long num = wdheader->size/sizeof(WD_TRANSFER);
1dac5195 327#ifndef NO_WINDRVR
328 ret = (*ioctl_func) (fd, request, wdioctl);
329#else
25ba7a49 330 ret = pport->transfer(tr, fd, request, ppbase, ecpbase, num);
ac9e3f59 331#endif
ac9e3f59 332 }
576995a8 333 break;
334
da3ba95a 335 case EVENT_UNREGISTER:
f92c0fbc
MG
336 {
337 struct event *e = (struct event*)(wdheader->data);
338
339 DPRINTF("EVENT_UNREGISTER\n");
795992ad 340#ifndef NO_WINDRVR
f92c0fbc
MG
341 ret = (*ioctl_func) (fd, request, wdioctl);
342#else
19acdb82 343 ret = xpcu_close(e);
292160ed 344#endif
f92c0fbc 345 }
9c9fd67c 346 break;
347
da3ba95a 348 case INT_WAIT:
f1405f13 349 DPRINTF("INT_WAIT\n");
b0f621dd 350 {
351 struct interrupt *it = (struct interrupt*)(wdheader->data);
352
501f1c21 353 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 354 it->hInterrupt, it->dwOptions,
355 it->dwCmds, it->fEnableOk, it->dwCounter,
356 it->dwLost, it->fStopped);
b0f621dd 357
795992ad 358#ifndef NO_WINDRVR
b0f621dd 359 ret = (*ioctl_func) (fd, request, wdioctl);
292160ed 360#else
19acdb82 361 ret = xpcu_int_wait(it);
292160ed 362#endif
363
501f1c21 364 DPRINTF("<- INT_WAIT_RETURN: Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
f1405f13 365 it->hInterrupt, it->dwOptions, it->dwCmds,
366 it->fEnableOk, it->dwCounter, it->dwLost,
367 it->fStopped);
b0f621dd 368 }
9c9fd67c 369 break;
370
da3ba95a 371 case CARD_UNREGISTER:
f1405f13 372 DPRINTF("CARD_UNREGISTER\n");
54357994 373 {
374 struct card_register* cr = (struct card_register*)(wdheader->data);
375
501f1c21 376 DPRINTF("-> Addr: 0x%lx, bytes: %lu, bar: %lu\n",
54357994 377 (unsigned long)cr->Card.Item[0].I.IO.dwAddr,
378 cr->Card.Item[0].I.IO.dwBytes,
379 cr->Card.Item[0].I.IO.dwBar);
380
501f1c21 381 DPRINTF("-> hCard: %lu\n", cr->hCard);
54357994 382
795992ad 383#ifndef NO_WINDRVR
54357994 384 ret = (*ioctl_func) (fd, request, wdioctl);
385#else
72ce448b
MG
386 if (pport)
387 pport->close(cr->hCard);
388
389 pport = NULL;
292160ed 390#endif
54357994 391 }
9c9fd67c 392 break;
393
da3ba95a 394 case EVENT_PULL:
f1405f13 395 DPRINTF("EVENT_PULL\n");
b1831983 396 {
397 struct event *e = (struct event*)(wdheader->data);
723d9aa0 398#ifdef DEBUG
b1831983 399 int i;
400
501f1c21 401 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 402 e->handle, e->dwAction, e->dwStatus,
403 e->dwEventId, e->dwCardType, e->hKernelPlugIn,
404 e->dwOptions, e->u.Usb.deviceId.dwVendorId,
405 e->u.Usb.deviceId.dwProductId,
406 e->u.Usb.dwUniqueID, e->dwEventVer,
407 e->dwNumMatchTables);
408
b1831983 409 for (i = 0; i < e->dwNumMatchTables; i++)
501f1c21 410 DPRINTF("-> match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
f1405f13 411 e->matchTables[i].VendorId,
412 e->matchTables[i].ProductId,
413 e->matchTables[i].bDeviceClass,
414 e->matchTables[i].bDeviceSubClass,
415 e->matchTables[i].bInterfaceClass,
416 e->matchTables[i].bInterfaceSubClass,
417 e->matchTables[i].bInterfaceProtocol);
723d9aa0 418#endif
b1831983 419
795992ad 420#ifndef NO_WINDRVR
b1831983 421 ret = (*ioctl_func) (fd, request, wdioctl);
292160ed 422#else
19acdb82 423 ret = xpcu_found(e);
292160ed 424#endif
b1831983 425
723d9aa0 426#ifdef DEBUG
501f1c21 427 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 428 e->handle, e->dwAction, e->dwStatus,
429 e->dwEventId, e->dwCardType, e->hKernelPlugIn,
430 e->dwOptions, e->u.Usb.deviceId.dwVendorId,
431 e->u.Usb.deviceId.dwProductId,
432 e->u.Usb.dwUniqueID, e->dwEventVer,
433 e->dwNumMatchTables);
434
b1831983 435 for (i = 0; i < e->dwNumMatchTables; i++)
501f1c21 436 DPRINTF("<- match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
f1405f13 437 e->matchTables[i].VendorId,
438 e->matchTables[i].ProductId,
439 e->matchTables[i].bDeviceClass,
440 e->matchTables[i].bDeviceSubClass,
441 e->matchTables[i].bInterfaceClass,
442 e->matchTables[i].bInterfaceSubClass,
443 e->matchTables[i].bInterfaceProtocol);
723d9aa0 444#endif
ca18111b 445
b1831983 446 }
9c9fd67c 447 break;
448
da3ba95a 449 default:
292160ed 450 fprintf(stderr,"!!!Unsupported IOCTL: %x!!!\n", request);
795992ad 451#ifndef NO_WINDRVR
9c9fd67c 452 ret = (*ioctl_func) (fd, request, wdioctl);
292160ed 453#endif
454 break;
cdc711dc 455 }
da3ba95a 456
9c9fd67c 457 return ret;
cdc711dc 458}
459
54357994 460int ioctl(int fd, unsigned long int request, ...) {
dbda1264 461 va_list args;
462 void *argp;
9bfaca62 463 int i;
dbda1264 464
465 if (!ioctl_func)
f1405f13 466 ioctl_func = (int (*) (int, int, void *)) dlsym (RTLD_NEXT, "ioctl");
dbda1264 467
468 va_start (args, request);
469 argp = va_arg (args, void *);
470 va_end (args);
471
9bfaca62
MG
472 for (i = 0; i < windrvrfds_count; i++) {
473 if (fd == windrvrfds[i])
474 return do_wdioctl(fd, request, argp);
475 }
dbda1264 476
9bfaca62 477 return (*ioctl_func) (fd, request, argp);
dbda1264 478}
cdc711dc 479
be452175 480int open (const char *pathname, int flags, ...) {
481 static int (*func) (const char *, int, mode_t) = NULL;
cdc711dc 482 mode_t mode = 0;
483 va_list args;
484 int fd;
485
486 if (!func)
f1405f13 487 func = (int (*) (const char *, int, mode_t)) dlsym (RTLD_NEXT, "open");
cdc711dc 488
489 if (flags & O_CREAT) {
490 va_start(args, flags);
491 mode = va_arg(args, mode_t);
492 va_end(args);
493 }
494
cdc711dc 495 if (!strcmp (pathname, "/dev/windrvr6")) {
9bfaca62
MG
496 DPRINTF("opening windrvr6 (%d)\n", windrvrfds_count);
497 windrvrfds = realloc(windrvrfds, sizeof(int) * (++windrvrfds_count));
498 if (!windrvrfds)
499 return -ENOMEM;
500
795992ad 501#ifdef NO_WINDRVR
9bfaca62 502 windrvrfds[windrvrfds_count-1] = fd = (*func) ("/dev/null", flags, mode);
01b99d52 503#else
9bfaca62 504 windrvrfds[windrvrfds_count-1] = fd = (*func) (pathname, flags, mode);
01b99d52 505#endif
723d9aa0 506
507 return fd;
cdc711dc 508 }
509
723d9aa0 510 return (*func) (pathname, flags, mode);
cdc711dc 511}
512
723d9aa0 513int close(int fd) {
514 static int (*func) (int) = NULL;
9bfaca62 515 int i;
cdc711dc 516
723d9aa0 517 if (!func)
f1405f13 518 func = (int (*) (int)) dlsym(RTLD_NEXT, "close");
723d9aa0 519
9bfaca62
MG
520 for (i = 0; i < windrvrfds_count; i++) {
521 if (fd == windrvrfds[i] && windrvrfds[i] >= 0) {
522 int remaining = windrvrfds_count - (i + 1);
523 DPRINTF("close windrvr6 (%d)\n", i);
524 if (remaining)
525 memmove(&(windrvrfds[i]), &(windrvrfds[i+1]), remaining * sizeof(int));
526 windrvrfds = realloc(windrvrfds, sizeof(int) * --windrvrfds_count);
527 if (!windrvrfds_count)
528 windrvrfds = NULL;
529 break;
530 }
cdc711dc 531 }
cdc711dc 532
723d9aa0 533 return (*func) (fd);
cdc711dc 534}
535
723d9aa0 536FILE *fopen(const char *path, const char *mode) {
537 FILE *ret;
538 static FILE* (*func) (const char*, const char*) = NULL;
0dca330e 539 char buf[256];
540 int i;
ca18111b 541
542 if (!func)
f1405f13 543 func = (FILE* (*) (const char*, const char*)) dlsym(RTLD_NEXT, "fopen");
ca18111b 544
3e670223 545 for (i = 0; i < 4; i++) {
546 snprintf(buf, sizeof(buf), "/proc/sys/dev/parport/parport%d/base-addr", i);
547 if (!strcmp(path, buf)) {
548 DPRINTF("open base-addr of parport%d\n", i);
549 if (config_is_real_pport(i)) {
550 ret = (*func) (path, mode);
551 } else {
552 ret = (*func) ("/dev/null", mode);
553 }
554
555 if (ret) {
556 baseaddrfp = ret;
557 baseaddrnum = i;
558 }
559
560 return ret;
561 }
562 }
563
564 ret = (*func) (path, mode);
ca18111b 565
0dca330e 566 if (!strcmp(path, "/proc/modules")) {
f1405f13 567 DPRINTF("opening /proc/modules\n");
aed36bb3
MG
568 if (!ret && errno == ENOENT) {
569 /* Hmm.. there appears to be no /proc/modules file
570 * fake it then */
571 ret = (*func)("/dev/null", mode);
572 DPRINTF("No /proc/modules -- faking\n");
573 }
723d9aa0 574#ifdef NO_WINDRVR
dbda1264 575 modulesfp = ret;
723d9aa0 576 modules_read = 0;
577#endif
578 }
cdc711dc 579
580 return ret;
581}
582
dbda1264 583char *fgets(char *s, int size, FILE *stream) {
584 static char* (*func) (char*, int, FILE*) = NULL;
16f6b164 585 const char modules[][256] = {"windrvr6 1 0 - Live 0xdeadbeef\n", "parport_pc 1 0 - Live 0xdeadbeef\n"};
0dca330e 586 char buf[256];
dbda1264 587 char *ret = NULL;
588
cdc711dc 589
590 if (!func)
f1405f13 591 func = (char* (*) (char*, int, FILE*)) dlsym(RTLD_NEXT, "fgets");
723d9aa0 592
dbda1264 593 if (modulesfp == stream) {
54357994 594 if (modules_read < sizeof(modules) / sizeof(modules[0])) {
16f6b164 595 strcpy(s, modules[modules_read]);
dbda1264 596 ret = s;
16f6b164 597 modules_read++;
dbda1264 598 }
0dca330e 599 } else if (baseaddrfp == stream) {
600 snprintf(s, sizeof(buf), "%d\t%d\n",
601 (baseaddrnum) * 0x10,
602 ((baseaddrnum) * 0x10) + 0x400);
603 ret = s;
723d9aa0 604 } else {
dbda1264 605 ret = (*func)(s,size,stream);
723d9aa0 606 }
cdc711dc 607
608 return ret;
609}
610
dbda1264 611int fclose(FILE *fp) {
612 static int (*func) (FILE*) = NULL;
cdc711dc 613
dbda1264 614 if (!func)
f1405f13 615 func = (int (*) (FILE*)) dlsym(RTLD_NEXT, "fclose");
cdc711dc 616
dbda1264 617 if (fp == modulesfp) {
618 modulesfp = NULL;
619 }
0dca330e 620
621 if (fp == baseaddrfp) {
622 baseaddrfp = NULL;
623 }
dbda1264 624
625 return (*func)(fp);
cdc711dc 626}
419f2c98 627
628int access(const char *pathname, int mode) {
629 static int (*func) (const char*, int);
630
631 if (!func)
f1405f13 632 func = (int (*) (const char*, int)) dlsym(RTLD_NEXT, "access");
3eee002c 633
b8b756f5 634 if (pathname && !strcmp(pathname, "/dev/windrvr6")) {
419f2c98 635 return 0;
636 } else {
637 return (*func)(pathname, mode);
638 }
639}
c42237a3 640
1fc8f7a4
MG
641#if 0
642/* USB cable sharing needs to overload semop, TODO! */
643int semop (int __semid, struct sembuf *__sops, size_t __nsops) {
644 static int (*func) (int, struct sembuf*, size_t) = NULL;
645 int i;
646
647 if (!func)
648 func = (int (*) (int, struct sembuf*, size_t)) dlsym(RTLD_NEXT, "semop");
649
650 fprintf(stderr,"semop: semid: 0x%X, elements: %d\n", __semid, __nsops);
651 for (i = 0; i < __nsops; i++) {
652 fprintf(stderr, " num: %u, op: %d, flg: %d\n", __sops[i].sem_num, __sops[i].sem_op, __sops[i].sem_flg);
653 if (__sops[i].sem_op < 0) {
654 fprintf(stderr, "SEMAPHORE LOCK\n");
655 } else {
656 fprintf(stderr, "SEMAPHORE UNLOCK\n");
657 }
658 }
659
660 return (*func)(__semid, __sops, __nsops);
661}
662#endif
663
9f78065e 664/*
b05f6dfe
MG
665 * Ugly hack for ISE 12. Preload doesn't seem to work correctly for
666 * libImpactComm.so. Even though the file is still read with fopen(),
667 * the version from libc is used and not the one from this file.
668 * Replace the function calling fopen() instead...
9f78065e
MG
669 * echo '_Z14isModuleLoadedPci' | c++filt
670 */
80a14787 671long int _Z14isModuleLoadedPci(char *module_name, int i) {
9f78065e 672 DPRINTF("_Z14isModuleLoadedPci: Checking for module %s (%d)\n", module_name, i);
4ba5d6d9
MG
673
674 return 1;
675}
daa4fc04 676
47661cec
MG
677void cpr_segv_handler(int sig, siginfo_t *info, void *context) {
678 void *newmem;
679
680 DPRINTF("SEGV at %p, mapping memory\n", info->si_addr);
681 errno = 0;
682 newmem = mmap(info->si_addr, 1, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
683 if (newmem != info->si_addr) {
684 perror("libusb-driver.so: Can't map memory, crashing now");
685 exit(EXIT_FAILURE);
686 }
687}
688
765c485a
MG
689/* XilCommNS::CPortResources::Instance() */
690void* _ZN9XilCommNS14CPortResources8InstanceEv() {
691 static void* (*func) (void) = NULL;
a90dd207 692 char *filename = NULL;
765c485a 693 void *ret;
6b3a1715 694 int i;
765c485a 695
6b3a1715 696 if (!func) {
47661cec
MG
697 struct sigaction act, oldact;
698 int sighand_installed = 0;
699
765c485a
MG
700 func = (void* (*) (void)) dlsym(RTLD_NEXT, "_ZN9XilCommNS14CPortResources8InstanceEv");
701
47661cec
MG
702 DPRINTF("Installing signal-handler for SIGSEGV\n");
703 bzero(&act, sizeof(struct sigaction));
704 act.sa_sigaction = cpr_segv_handler;
705 act.sa_flags = SA_SIGINFO;
706 if (sigaction(SIGSEGV, &act, &oldact) == 0) {
707 sighand_installed = 1;
708 }
709
6b3a1715 710 DPRINTF("Searching for filename starting at %p\n", func);
47661cec 711 for(i = 0; i < 32768; i++) {
6b3a1715
MG
712 if (!strcmp(((char*)func)+i, "/proc/sys/dev/parport/%s/base-addr")) {
713 filename = ((char*)func)+i;
714 DPRINTF("Filename found at offset %p\n", (void*)(filename - ((char*)func)));
715 break;
716 }
717 }
47661cec
MG
718 if (sighand_installed) {
719 DPRINTF("Restoring signal-handler for SIGSEGV\n");
720 sigaction(SIGSEGV, &oldact, NULL);
721 }
722 if (!filename)
723 fprintf(stderr, "libusb-driver.so: Can't find memory to patch, parallel cables will probably not work!\n");
6b3a1715 724 }
a90dd207
MG
725
726 if (filename) {
727 long pagesize;
728 size_t protectlen;
729 void *start;
730 int len = strlen(filename) + 1;
731 int ret;
732
733 pagesize = sysconf(_SC_PAGE_SIZE);
734 DPRINTF("You have %lu bytes sized pages!\n", pagesize);
735
736 start = (void*)((long)filename & (~(pagesize-1)));
737
738 protectlen = pagesize;
739 if ((long)(filename + len) > (long)(start + protectlen))
740 protectlen += pagesize;
741
742 DPRINTF("Unprotecting %zd bytes starting at %p\n", protectlen, start);
743 ret = mprotect(start, protectlen, PROT_READ|PROT_WRITE);
744 if (ret == -1)
745 perror("mprotect");
746
747 DPRINTF("Replacing %s with /dev/zero\n", filename);
748 strcpy(filename, "/dev/zero");
749
750 DPRINTF("Reprotecting %zd bytes starting at %p\n", protectlen, start);
751 ret = mprotect(start, protectlen, PROT_READ|PROT_EXEC);
752 if (ret == -1)
753 perror("mprotect");
765c485a 754 }
a90dd207
MG
755
756 DPRINTF("-> XilCommNS::CPortResources::Instance()\n");
757
758 ret = func();
765c485a
MG
759
760 DPRINTF("<- XilCommNS::CPortResources::Instance()\n");
761
762 return ret;
763}
764
daa4fc04 765static void __attribute__ ((constructor)) libusbdriver_init(void) {
b05f6dfe
MG
766 int i;
767 char buf[256];
768 char buf2[256];
769
770 for (i = 0; i < 4; i++) {
771 snprintf(buf, sizeof(buf), "XIL_IMPACT_ENV_LPT%d_BASE_ADDRESS", i+1);
772 snprintf(buf2, sizeof(buf2), "%x", 0x10*i);
773 setenv(buf, buf2, 1);
774 snprintf(buf, sizeof(buf), "XIL_IMPACT_ENV_LPT%d_ECP_ADDRESS", i+1);
775 snprintf(buf2, sizeof(buf2), "%x", (0x10*i)+0x400);
776 setenv(buf, buf2, 1);
777 }
778
779 setenv("XIL_IMPACT_USE_LIBUSB", "0", 1);
780 setenv("XIL_IMPACT_USE_WINDRIVER", "1", 1);
781
daa4fc04 782 #if __WORDSIZE == 32
ad0f0d12
MG
783 {
784 struct utsname un;
785 int ret;
daa4fc04 786
ad0f0d12 787 ret = uname(&un);
daa4fc04 788
ad0f0d12
MG
789 if (ret == 0 && (!strcmp(un.machine, "x86_64"))) {
790 DPRINTF("setting 32bit personality\n");
791 (long)syscall(SYS_personality, PER_LINUX32);
792 }
daa4fc04
MG
793 }
794 #endif
795}
Impressum, Datenschutz