update links for xc3sprog
[usb-driver] / usb-driver.c
1 /* libusb/ppdev connector for XILINX impact
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 */
23
24 #define _GNU_SOURCE 1
25
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>
36 #include <signal.h>
37 #include <errno.h>
38 #include <inttypes.h>
39 #include <sys/ioctl.h>
40 #include <sys/utsname.h>
41 #include <bits/wordsize.h>
42 #include <sys/ipc.h>
43 #include <sys/sem.h>
44 #include <sys/mman.h>
45 #include <syscall.h>
46 #include <linux/personality.h>
47 #include "usb-driver.h"
48 #include "config.h"
49 #include "xpcu.h"
50
51 static int (*ioctl_func) (int, int, void *) = NULL;
52 static int *windrvrfds = NULL;
53 static int windrvrfds_count = 0;
54 static unsigned long ppbase = 0;
55 static unsigned long ecpbase = 0;
56 static struct parport_config *pport = NULL;
57 static FILE *modulesfp = NULL;
58 static FILE *baseaddrfp = NULL;
59 static int baseaddrnum = 0;
60 static int modules_read = 0;
61
62 #define NO_WINDRVR 1
63
64 void hexdump(unsigned char *buf, int len, char *prefix) {
65 int i = 0;
66
67 fprintf(stderr, "%s %03x: ", prefix, i);
68 for(i = 0; i<len; i++) {
69 fprintf(stderr,"%02x ", buf[i]);
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);
74 }
75 fprintf(stderr,"\n");
76 }
77
78
79 static int do_wdioctl(int fd, unsigned int request, unsigned char *wdioctl) {
80 struct header_struct* wdheader = (struct header_struct*)wdioctl;
81 struct version_struct *version;
82 int ret = 0;
83
84 if (wdheader->magic != MAGIC) {
85 fprintf(stderr,"!!!ERROR: magic header does not match!!!\n");
86 return (*ioctl_func) (fd, request, wdioctl);
87 }
88
89 switch(request & ~(0xc0000000)) {
90 case VERSION:
91 version = (struct version_struct*)(wdheader->data);
92 strcpy(version->version, "libusb-driver.so version: " USB_DRIVER_VERSION);
93 version->versionul = 802;
94 DPRINTF("VERSION\n");
95 break;
96
97 case LICENSE:
98 DPRINTF("LICENSE\n");
99 break;
100
101 case CARD_REGISTER_OLD:
102 case CARD_REGISTER:
103 DPRINTF("CARD_REGISTER\n");
104 {
105 struct card_register* cr = (struct card_register*)(wdheader->data);
106
107 DPRINTF("-> Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
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
113 DPRINTF("-> Items: %lu, Addr: 0x%lx, bytes: %lu, bar: %lu\n",
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);
118 #ifndef NO_WINDRVR
119 ret = (*ioctl_func) (fd, request, wdioctl);
120 #else
121 cr->hCard = 0;
122
123 pport = config_get((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
124 if (!pport)
125 break;
126
127 ret = pport->open((unsigned long)cr->Card.Item[0].I.IO.dwAddr / 0x10);
128
129 ppbase = (unsigned long)cr->Card.Item[0].I.IO.dwAddr;
130
131 if (cr->Card.dwItems > 1 && cr->Card.Item[1].I.IO.dwAddr)
132 ecpbase = (unsigned long)cr->Card.Item[1].I.IO.dwAddr;
133
134 if (ret >= 0) {
135 cr->hCard = ret;
136 } else {
137 cr->hCard = 0;
138 }
139 #endif
140 DPRINTF("<-hCard: %lu\n", cr->hCard);
141 }
142 break;
143
144 case USB_TRANSFER:
145 DPRINTF("USB_TRANSFER\n");
146 {
147 struct usb_transfer *ut = (struct usb_transfer*)(wdheader->data);
148
149 #ifdef DEBUG
150 DPRINTF("-> unique: 0x%lx, pipe: %lu, read: %lu, options: %lx, size: %lu, timeout: %lx\n",
151 ut->dwUniqueID, ut->dwPipeNum, ut->fRead,
152 ut->dwOptions, ut->dwBufferSize, ut->dwTimeout);
153 if (ut->dwPipeNum == 0) {
154 DPRINTF("-> setup packet:");
155 hexdump(ut->SetupPacket, 8, "");
156 }
157
158 if (!ut->fRead && ut->dwBufferSize)
159 {
160 hexdump(ut->pBuffer, ut->dwBufferSize, "->");
161 }
162 #endif
163
164 #ifndef NO_WINDRVR
165 ret = (*ioctl_func) (fd, request, wdioctl);
166 #else
167 ret = xpcu_transfer(ut);
168 #endif
169
170 #ifdef DEBUG
171 DPRINTF("Transferred: %lu (%s)\n",ut->dwBytesTransferred, (ut->fRead?"read":"write"));
172 if (ut->fRead && ut->dwBytesTransferred)
173 {
174 hexdump(ut->pBuffer, ut->dwBytesTransferred, "<-");
175 }
176 #endif
177 }
178 break;
179
180 case INT_ENABLE_OLD:
181 case INT_ENABLE:
182 DPRINTF("INT_ENABLE\n");
183 {
184 struct interrupt *it = (struct interrupt*)(wdheader->data);
185
186 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
187 it->hInterrupt, it->dwOptions,
188 it->dwCmds, it->fEnableOk, it->dwCounter,
189 it->dwLost, it->fStopped);
190
191 #ifndef NO_WINDRVR
192 ret = (*ioctl_func) (fd, request, wdioctl);
193 #else
194 ret = xpcu_int_state(it, ENABLE_INTERRUPT);
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);
201 }
202
203 break;
204
205 case INT_DISABLE:
206 DPRINTF("INT_DISABLE\n");
207 {
208 struct interrupt *it = (struct interrupt*)(wdheader->data);
209
210 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
211 it->hInterrupt, it->dwOptions,
212 it->dwCmds, it->fEnableOk, it->dwCounter,
213 it->dwLost, it->fStopped);
214 #ifndef NO_WINDRVR
215 ret = (*ioctl_func) (fd, request, wdioctl);
216 #else
217 ret = xpcu_int_state(it, DISABLE_INTERRUPT);
218 #endif
219 DPRINTF("<- Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
220 it->hInterrupt, it->dwOptions,
221 it->dwCmds, it->fEnableOk, it->dwCounter,
222 it->dwLost, it->fStopped);
223 }
224 break;
225
226 case USB_SET_INTERFACE:
227 DPRINTF("USB_SET_INTERFACE\n");
228 {
229 struct usb_set_interface *usi = (struct usb_set_interface*)(wdheader->data);
230
231 DPRINTF("-> unique: 0x%lx, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
232 usi->dwUniqueID, usi->dwInterfaceNum,
233 usi->dwAlternateSetting, usi->dwOptions);
234 #ifndef NO_WINDRVR
235 ret = (*ioctl_func) (fd, request, wdioctl);
236 #else
237 ret = xpcu_set_interface(usi);
238 #endif
239 DPRINTF("<- unique: 0x%lx, interfacenum: %lu, alternatesetting: %lu, options: %lx\n",
240 usi->dwUniqueID, usi->dwInterfaceNum,
241 usi->dwAlternateSetting, usi->dwOptions);
242 }
243 break;
244
245 case USB_GET_DEVICE_DATA_OLD:
246 case USB_GET_DEVICE_DATA:
247 DPRINTF("USB_GET_DEVICE_DATA\n");
248 {
249 struct usb_get_device_data *ugdd = (struct usb_get_device_data*)(wdheader->data);
250
251 DPRINTF("-> unique: 0x%lx, bytes: %lu, options: %lx\n",
252 ugdd->dwUniqueID, ugdd->dwBytes,
253 ugdd->dwOptions);
254
255 ret = xpcu_deviceinfo(ugdd);
256
257 }
258 break;
259
260 case EVENT_REGISTER_OLD:
261 case EVENT_REGISTER:
262 DPRINTF("EVENT_REGISTER\n");
263 {
264 struct event *e = (struct event*)(wdheader->data);
265 #ifdef DEBUG
266 int i;
267 #endif
268
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",
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
278 #ifndef NO_WINDRVR
279 ret = (*ioctl_func) (fd, request, wdioctl);
280 #else
281 ret = xpcu_find(e);
282 #endif
283
284 #ifdef DEBUG
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",
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
294 for (i = 0; i < e->dwNumMatchTables; i++)
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);
303 #endif
304 }
305 break;
306
307 case TRANSFER_OLD:
308 case TRANSFER:
309 DPRINTF("TRANSFER\n");
310 {
311 WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
312
313 #ifndef NO_WINDRVR
314 ret = (*ioctl_func) (fd, request, wdioctl);
315 #else
316 ret = pport->transfer(tr, fd, request, ppbase, ecpbase, 1);
317 #endif
318 }
319 break;
320
321 case MULTI_TRANSFER_OLD:
322 case MULTI_TRANSFER:
323 DPRINTF("MULTI_TRANSFER\n");
324 {
325 WD_TRANSFER *tr = (WD_TRANSFER*)(wdheader->data);
326 unsigned long num = wdheader->size/sizeof(WD_TRANSFER);
327 #ifndef NO_WINDRVR
328 ret = (*ioctl_func) (fd, request, wdioctl);
329 #else
330 ret = pport->transfer(tr, fd, request, ppbase, ecpbase, num);
331 #endif
332 }
333 break;
334
335 case EVENT_UNREGISTER:
336 {
337 struct event *e = (struct event*)(wdheader->data);
338
339 DPRINTF("EVENT_UNREGISTER\n");
340 #ifndef NO_WINDRVR
341 ret = (*ioctl_func) (fd, request, wdioctl);
342 #else
343 ret = xpcu_close(e);
344 #endif
345 }
346 break;
347
348 case INT_WAIT:
349 DPRINTF("INT_WAIT\n");
350 {
351 struct interrupt *it = (struct interrupt*)(wdheader->data);
352
353 DPRINTF("-> Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
354 it->hInterrupt, it->dwOptions,
355 it->dwCmds, it->fEnableOk, it->dwCounter,
356 it->dwLost, it->fStopped);
357
358 #ifndef NO_WINDRVR
359 ret = (*ioctl_func) (fd, request, wdioctl);
360 #else
361 ret = xpcu_int_wait(it);
362 #endif
363
364 DPRINTF("<- INT_WAIT_RETURN: Handle: 0x%lx, Options: %lx, ncmds: %lu, enableok: %lu, count: %lu, lost: %lu, stopped: %lu\n",
365 it->hInterrupt, it->dwOptions, it->dwCmds,
366 it->fEnableOk, it->dwCounter, it->dwLost,
367 it->fStopped);
368 }
369 break;
370
371 case CARD_UNREGISTER:
372 DPRINTF("CARD_UNREGISTER\n");
373 {
374 struct card_register* cr = (struct card_register*)(wdheader->data);
375
376 DPRINTF("-> Addr: 0x%lx, bytes: %lu, bar: %lu\n",
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
381 DPRINTF("-> hCard: %lu\n", cr->hCard);
382
383 #ifndef NO_WINDRVR
384 ret = (*ioctl_func) (fd, request, wdioctl);
385 #else
386 if (pport)
387 pport->close(cr->hCard);
388
389 pport = NULL;
390 #endif
391 }
392 break;
393
394 case EVENT_PULL:
395 DPRINTF("EVENT_PULL\n");
396 {
397 struct event *e = (struct event*)(wdheader->data);
398 #ifdef DEBUG
399 int i;
400
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",
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
409 for (i = 0; i < e->dwNumMatchTables; i++)
410 DPRINTF("-> match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
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);
418 #endif
419
420 #ifndef NO_WINDRVR
421 ret = (*ioctl_func) (fd, request, wdioctl);
422 #else
423 ret = xpcu_found(e);
424 #endif
425
426 #ifdef DEBUG
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",
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
435 for (i = 0; i < e->dwNumMatchTables; i++)
436 DPRINTF("<- match: dev: %04x:%04x, class: %x, subclass: %x, intclass: %x, intsubclass: %x, intproto: %x\n",
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);
444 #endif
445
446 }
447 break;
448
449 default:
450 fprintf(stderr,"!!!Unsupported IOCTL: %x!!!\n", request);
451 #ifndef NO_WINDRVR
452 ret = (*ioctl_func) (fd, request, wdioctl);
453 #endif
454 break;
455 }
456
457 return ret;
458 }
459
460 int ioctl(int fd, unsigned long int request, ...) {
461 va_list args;
462 void *argp;
463 int i;
464
465 if (!ioctl_func)
466 ioctl_func = (int (*) (int, int, void *)) dlsym (RTLD_NEXT, "ioctl");
467
468 va_start (args, request);
469 argp = va_arg (args, void *);
470 va_end (args);
471
472 for (i = 0; i < windrvrfds_count; i++) {
473 if (fd == windrvrfds[i])
474 return do_wdioctl(fd, request, argp);
475 }
476
477 return (*ioctl_func) (fd, request, argp);
478 }
479
480 int open (const char *pathname, int flags, ...) {
481 static int (*func) (const char *, int, mode_t) = NULL;
482 mode_t mode = 0;
483 va_list args;
484 int fd;
485
486 if (!func)
487 func = (int (*) (const char *, int, mode_t)) dlsym (RTLD_NEXT, "open");
488
489 if (flags & O_CREAT) {
490 va_start(args, flags);
491 mode = va_arg(args, mode_t);
492 va_end(args);
493 }
494
495 if (!strcmp (pathname, "/dev/windrvr6")) {
496 DPRINTF("opening windrvr6 (%d)\n", windrvrfds_count);
497 windrvrfds = realloc(windrvrfds, sizeof(int) * (++windrvrfds_count));
498 if (!windrvrfds)
499 return -ENOMEM;
500
501 #ifdef NO_WINDRVR
502 windrvrfds[windrvrfds_count-1] = fd = (*func) ("/dev/null", flags, mode);
503 #else
504 windrvrfds[windrvrfds_count-1] = fd = (*func) (pathname, flags, mode);
505 #endif
506
507 return fd;
508 }
509
510 return (*func) (pathname, flags, mode);
511 }
512
513 int close(int fd) {
514 static int (*func) (int) = NULL;
515 int i;
516
517 if (!func)
518 func = (int (*) (int)) dlsym(RTLD_NEXT, "close");
519
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 }
531 }
532
533 return (*func) (fd);
534 }
535
536 FILE *fopen(const char *path, const char *mode) {
537 FILE *ret;
538 static FILE* (*func) (const char*, const char*) = NULL;
539 char buf[256];
540 int i;
541
542 if (!func)
543 func = (FILE* (*) (const char*, const char*)) dlsym(RTLD_NEXT, "fopen");
544
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);
565
566 if (!strcmp(path, "/proc/modules")) {
567 DPRINTF("opening /proc/modules\n");
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 }
574 #ifdef NO_WINDRVR
575 modulesfp = ret;
576 modules_read = 0;
577 #endif
578 }
579
580 return ret;
581 }
582
583 char *fgets(char *s, int size, FILE *stream) {
584 static char* (*func) (char*, int, FILE*) = NULL;
585 const char modules[][256] = {"windrvr6 1 0 - Live 0xdeadbeef\n", "parport_pc 1 0 - Live 0xdeadbeef\n"};
586 char buf[256];
587 char *ret = NULL;
588
589
590 if (!func)
591 func = (char* (*) (char*, int, FILE*)) dlsym(RTLD_NEXT, "fgets");
592
593 if (modulesfp == stream) {
594 if (modules_read < sizeof(modules) / sizeof(modules[0])) {
595 strcpy(s, modules[modules_read]);
596 ret = s;
597 modules_read++;
598 }
599 } else if (baseaddrfp == stream) {
600 snprintf(s, sizeof(buf), "%d\t%d\n",
601 (baseaddrnum) * 0x10,
602 ((baseaddrnum) * 0x10) + 0x400);
603 ret = s;
604 } else {
605 ret = (*func)(s,size,stream);
606 }
607
608 return ret;
609 }
610
611 int fclose(FILE *fp) {
612 static int (*func) (FILE*) = NULL;
613
614 if (!func)
615 func = (int (*) (FILE*)) dlsym(RTLD_NEXT, "fclose");
616
617 if (fp == modulesfp) {
618 modulesfp = NULL;
619 }
620
621 if (fp == baseaddrfp) {
622 baseaddrfp = NULL;
623 }
624
625 return (*func)(fp);
626 }
627
628 int access(const char *pathname, int mode) {
629 static int (*func) (const char*, int);
630
631 if (!func)
632 func = (int (*) (const char*, int)) dlsym(RTLD_NEXT, "access");
633
634 if (pathname && !strcmp(pathname, "/dev/windrvr6")) {
635 return 0;
636 } else {
637 return (*func)(pathname, mode);
638 }
639 }
640
641 #if 0
642 /* USB cable sharing needs to overload semop, TODO! */
643 int 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
664 /*
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...
669 * echo '_Z14isModuleLoadedPci' | c++filt
670 */
671 long int _Z14isModuleLoadedPci(char *module_name, int i) {
672 DPRINTF("_Z14isModuleLoadedPci: Checking for module %s (%d)\n", module_name, i);
673
674 return 1;
675 }
676
677 void 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
689 /* XilCommNS::CPortResources::Instance() */
690 void* _ZN9XilCommNS14CPortResources8InstanceEv() {
691 static void* (*func) (void) = NULL;
692 char *filename = NULL;
693 void *ret;
694 int i;
695
696 if (!func) {
697 struct sigaction act, oldact;
698 int sighand_installed = 0;
699
700 func = (void* (*) (void)) dlsym(RTLD_NEXT, "_ZN9XilCommNS14CPortResources8InstanceEv");
701
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
710 DPRINTF("Searching for filename starting at %p\n", func);
711 for(i = 0; i < 32768; i++) {
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 }
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");
724 }
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");
754 }
755
756 DPRINTF("-> XilCommNS::CPortResources::Instance()\n");
757
758 ret = func();
759
760 DPRINTF("<- XilCommNS::CPortResources::Instance()\n");
761
762 return ret;
763 }
764
765 static void __attribute__ ((constructor)) libusbdriver_init(void) {
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
782 #if __WORDSIZE == 32
783 {
784 struct utsname un;
785 int ret;
786
787 ret = uname(&un);
788
789 if (ret == 0 && (!strcmp(un.machine, "x86_64"))) {
790 DPRINTF("setting 32bit personality\n");
791 (long)syscall(SYS_personality, PER_LINUX32);
792 }
793 }
794 #endif
795 }
Impressum, Datenschutz