OpenCBM
xu1541.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2007 Till Harbaum <till@harbaum.org>
8  * Copyright 2009 Spiro Trikaliotis
9  *
10 */
11 
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <errno.h>
25 
26 #include "opencbm.h"
27 
28 #include "arch.h"
29 #include "dynlibusb.h"
30 #include "getpluginaddress.h"
31 #include "xu1541.h"
32 
33 static int debug_level = -10000;
34 static usb_dev_handle *xu1541_handle = NULL;
37 #define TIMEOUT_DELAY 25000 // 25ms
38 
47 static void xu1541_dbg(int level, char *msg, ...)
48 {
49  va_list argp;
50 
51  /* determine debug mode if not yet known */
52  if(debug_level == -10000)
53  {
54  char *val = getenv("XU1541_DEBUG");
55  if(val)
56  debug_level = atoi(val);
57  }
58 
59  if(level <= debug_level)
60  {
61  fprintf(stderr, "[XU1541] ");
62  va_start(argp, msg);
63  vfprintf(stderr, msg, argp);
64  va_end(argp);
65  fprintf(stderr, "\n");
66  }
67 }
68 
83 static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid,
84  char *buf, int buflen)
85 {
86  char buffer[256];
87  int rval, i;
88 
89  if((rval = usb.control_msg(dev, USB_ENDPOINT_IN,
90  USB_REQ_GET_DESCRIPTOR,
91  (USB_DT_STRING << 8) + index,
92  langid, buffer, sizeof(buffer), 1000)) < 0)
93  return rval;
94 
95  if(buffer[1] != USB_DT_STRING)
96  return 0;
97 
98  if((unsigned char)buffer[0] < rval)
99  rval = (unsigned char)buffer[0];
100 
101  rval /= 2;
102  /* lossy conversion to ISO Latin1 */
103  for(i=1;i<rval;i++){
104  if(i > buflen) /* destination buffer overflow */
105  break;
106  buf[i-1] = buffer[2 * i];
107  if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
108  buf[i-1] = '?';
109  }
110  buf[i-1] = 0;
111  return i-1;
112 }
113 
131 /* try to find a xu1541 cable */
132 int xu1541_init(void) {
133  struct usb_bus *bus;
134  struct usb_device *dev;
135  unsigned char ret[4];
136  int len;
137 
138  xu1541_dbg(0, "Scanning usb ...");
139 
140  usb.init();
141 
142  usb.find_busses();
143  usb.find_devices();
144 
145  /* usb_find_devices sets errno if some devices don't reply 100% correct. */
146  /* make lib ignore this as this has nothing to do with our device */
147  errno = 0;
148 
149  for(bus = usb.get_busses(); !xu1541_handle && bus; bus = bus->next) {
150  xu1541_dbg(1, "Scanning bus %s", bus->dirname);
151 
152  for(dev = bus->devices; !xu1541_handle && dev; dev = dev->next) {
153  xu1541_dbg(1, "Device %04x:%04x at %s",
154  dev->descriptor.idVendor, dev->descriptor.idProduct,
155  dev->filename);
156 
157  if((dev->descriptor.idVendor == XU1541_VID) &&
158  (dev->descriptor.idProduct == XU1541_PID)) {
159  char string[256];
160  int len;
161 
162  xu1541_dbg(0, "Found xu1541 device on bus %s device %s.",
163  bus->dirname, dev->filename);
164 
165  /* open device */
166  if(!(xu1541_handle = usb.open(dev)))
167  fprintf(stderr, "Error: Cannot open USB device: %s\n",
168  usb.strerror());
169 
170  /* get device name and make sure the name is "xu1541" meaning */
171  /* that the device is not in boot loader mode */
172  len = usbGetStringAscii(xu1541_handle, dev->descriptor.iProduct,
173  0x0409, string, sizeof(string));
174  if(len < 0){
175  fprintf(stderr, "warning: cannot query product "
176  "name for device: %s\n", usb.strerror());
177  if(xu1541_handle) usb.close(xu1541_handle);
178  xu1541_handle = NULL;
179  }
180 
181  /* make sure the name matches what we expect */
182  if(strcmp(string, "xu1541") != 0) {
183  fprintf(stderr, "Error: Found xu1541 in unexpected state,"
184  " please make sure device is _not_ in bootloader mode!\n");
185 
186  if(xu1541_handle) usb.close(xu1541_handle);
187  xu1541_handle = NULL;
188  }
189  }
190  }
191  }
192 
193  if(!xu1541_handle) {
194  fprintf(stderr, "ERROR: No xu1541 device found\n");
195  return -1;
196  }
197 
198  if (usb.set_configuration(xu1541_handle, 1) != 0) {
199  fprintf(stderr, "USB error: %s\n", usb.strerror());
200  return -1;
201  }
202 
203  /* Get exclusive access to interface 0. */
204  if (usb.claim_interface(xu1541_handle, 0) != 0) {
205  fprintf(stderr, "USB error: %s\n", usb.strerror());
206  return -1;
207  }
208 
209  /* check the devices version number as firmware x.06 changed everything */
210  len = usb.control_msg(xu1541_handle,
211  USB_TYPE_CLASS | USB_ENDPOINT_IN,
212  XU1541_INFO, 0, 0, (char*)ret, sizeof(ret), 1000);
213 
214  if(len < 0) {
215  fprintf(stderr, "USB request for XU1541 info failed: %s!\n",
216  usb.strerror());
217  return -1;
218  }
219 
220  if(len != sizeof(ret)) {
221  fprintf(stderr, "Unexpected number of bytes (%d) returned\n", len);
222  return -1;
223  }
224 
225  xu1541_dbg(0, "firmware version %x.%02x", ret[0], ret[1]);
226 
227  if(ret[1] < 8) {
228  fprintf(stderr, "Device reports firmware version %x.%02x\n",
229  ret[0], ret[1]);
230  fprintf(stderr, "but this version of opencbm requires at least "
231  "version x.08\n");
232  return -1;
233  }
234 
235  return 0;
236 }
237 
243 void xu1541_close(void)
244 {
245  xu1541_dbg(0, "Closing USB link");
246 
247  if(usb.release_interface(xu1541_handle, 0))
248  fprintf(stderr, "USB error: %s\n", usb.strerror());
249 
250  usb.close(xu1541_handle);
251 }
252 
270 int xu1541_ioctl(unsigned int cmd, unsigned int addr, unsigned int secaddr)
271 {
272  int nBytes;
273  char ret[4];
274 
275  xu1541_dbg(1, "ioctl %d for device %d, sub %d", cmd, addr, secaddr);
276 
277  /* some commands are being handled asynchronously, namely the ones that */
278  /* send a iec byte. These need to ask for the result with a seperate */
279  /* command */
280  if((cmd == XU1541_TALK) || (cmd == XU1541_UNTALK) ||
281  (cmd == XU1541_LISTEN) || (cmd == XU1541_UNLISTEN) ||
282  (cmd == XU1541_OPEN) || (cmd == XU1541_CLOSE))
283  {
284  int link_ok = 0, err = 0;
285 
286  /* USB_TIMEOUT msec timeout required for reset */
287  if((nBytes = usb.control_msg(xu1541_handle,
288  USB_TYPE_CLASS | USB_ENDPOINT_IN,
289  cmd, (secaddr << 8) + addr, 0,
290  NULL, 0,
291  1000)) < 0)
292  {
293  fprintf(stderr, "USB error in xu1541_ioctl(async): %s\n",
294  usb.strerror());
295  exit(-1);
296  return -1;
297  }
298 
299  /* wait for USB to become available again by requesting the result */
300  do
301  {
302  unsigned char rv[2];
303 
304  /* request async result code */
305  if(usb.control_msg(xu1541_handle,
306  USB_TYPE_CLASS | USB_ENDPOINT_IN,
307  XU1541_GET_RESULT, 0, 0,
308  (char*)rv, sizeof(rv),
309  1000) == sizeof(rv))
310  {
311  /* we got a valid result */
312  if(rv[0] == XU1541_IO_RESULT)
313  {
314  /* use that result */
315  nBytes = sizeof(rv)-1;
316  ret[0] = rv[1];
317  /* a returned byte means that the USB link is fine */
318  link_ok = 1;
319  errno = 0;
320  }
321  else
322  {
323  xu1541_dbg(3, "unexpected result (%d/%d)", rv[0], rv[1]);
324 
325  /* not the expected result */
326  arch_usleep(TIMEOUT_DELAY);
327  }
328  }
329  else
330  {
331  xu1541_dbg(3, "usb timeout");
332 
333  /* count the error states (just out of couriosity) */
334  err++;
335 
336  arch_usleep(TIMEOUT_DELAY);
337  }
338  }
339  while(!link_ok);
340  }
341  else
342  {
343 
344  /* sync transfer, read result directly */
345  if((nBytes = usb.control_msg(xu1541_handle,
346  USB_TYPE_CLASS | USB_ENDPOINT_IN,
347  cmd, (secaddr << 8) + addr, 0,
348  ret, sizeof(ret),
349  USB_TIMEOUT)) < 0)
350  {
351  fprintf(stderr, "USB error in xu1541_ioctl(sync): %s\n",
352  usb.strerror());
353  exit(-1);
354  return -1;
355  }
356  }
357 
358  xu1541_dbg(2, "returned %d bytes", nBytes);
359 
360  /* return ok(0) if command does not have a return value */
361  if(nBytes == 0)
362  return 0;
363 
364  xu1541_dbg(2, "return val = %x", ret[0]);
365  return ret[0];
366 }
367 
379 int xu1541_write(const unsigned char *data, size_t len)
380 {
381  int bytesWritten = 0;
382 
383  xu1541_dbg(1, "write %d bytes from address %p", len, data);
384 
385  while(len)
386  {
387  int link_ok = 0, err = 0;
388  int wr, bytes2write;
389  bytes2write = (len > XU1541_IO_BUFFER_SIZE)?XU1541_IO_BUFFER_SIZE:len;
390 
391  /* the write itself moved the data into the buffer, the actual */
392  /* iec write is triggered _after_ this USB write is done */
393  if((wr = usb.control_msg(xu1541_handle,
394  USB_TYPE_CLASS | USB_ENDPOINT_OUT,
395  XU1541_WRITE, bytes2write, 0,
396  (char*)data, bytes2write,
397  USB_TIMEOUT)) < 0)
398  {
399  fprintf(stderr, "USB error xu1541_write(): %s\n", usb.strerror());
400  exit(-1);
401  return -1;
402  }
403 
404  len -= wr;
405  data += wr;
406  bytesWritten += wr;
407 
408  xu1541_dbg(2, "wrote chunk of %d bytes, total %d, left %d",
409  wr, bytesWritten, len);
410 
411  /* wait for USB to become available again by requesting the result */
412  do
413  {
414  unsigned char rv[2];
415 
416  /* request async result */
417  if(usb.control_msg(xu1541_handle,
418  USB_TYPE_CLASS | USB_ENDPOINT_IN,
419  XU1541_GET_RESULT, 0, 0,
420  (char*)rv, sizeof(rv),
421  1000) == sizeof(rv))
422  {
423  /* the USB link is available again if we got a valid result */
424  if(rv[0] == XU1541_IO_RESULT) {
425  /* device reports failure, stop writing */
426  if(!rv[1])
427  len = 0;
428 
429  link_ok = 1;
430  errno = 0;
431  }
432  else
433  {
434  xu1541_dbg(3, "unexpected result (%d/%d)", rv[0], rv[1]);
435  arch_usleep(TIMEOUT_DELAY);
436  }
437  }
438  else
439  {
440  xu1541_dbg(3, "usb timeout");
441  /* count the error states (just out of couriosity) */
442  err++;
443  }
444  }
445  while(!link_ok);
446  }
447  return bytesWritten;
448 }
449 
461 int xu1541_read(unsigned char *data, size_t len)
462 {
463  int bytesRead = 0;
464 
465  xu1541_dbg(1, "read %d bytes to address %p", len, data);
466 
467  while(len > 0)
468  {
469  int rd, bytes2read;
470  int link_ok = 0, err = 0;
471  unsigned char rv[2];
472 
473  /* limit transfer size */
474  bytes2read = (len > XU1541_IO_BUFFER_SIZE)?XU1541_IO_BUFFER_SIZE:len;
475 
476  /* request async read, ignore errors as they happen due to */
477  /* link being disabled */
478  rd = usb.control_msg(xu1541_handle,
479  USB_TYPE_CLASS | USB_ENDPOINT_IN,
480  XU1541_REQUEST_READ, bytes2read, 0,
481  NULL, 0,
482  1000);
483 
484  if(rd < 0) {
485  fprintf(stderr, "USB error in xu1541_request_read(): %s\n",
486  usb.strerror());
487  exit(-1);
488  return -1;
489  }
490 
491  /* since the xu1541 may disable interrupts and wouldn't be able */
492  /* to do proper USB communication we'd have to expect USB errors */
493 
494  /* try to get result, to make sure usb link is working again */
495  /* we can't do this in the read itself since windows returns */
496  /* just 0 bytes while the USB link is down which we can't */
497  /* distinguish from a real 0 byte read event */
498 
499  xu1541_dbg(2, "sent request for %d bytes, waiting for result",
500  bytes2read);
501 
502  do
503  {
504  /* get the result code which also contains the current state */
505  /* the xu1541 is in so we know when it's done reading on IEC */
506  if((rd = usb.control_msg(xu1541_handle,
507  USB_TYPE_CLASS | USB_ENDPOINT_IN,
508  XU1541_GET_RESULT, 0, 0,
509  (char*)rv, sizeof(rv),
510  1000)) == sizeof(rv))
511  {
512  xu1541_dbg(2, "got result %d/%d", rv[0], rv[1]);
513 
514  // if the first byte is still not XU1541_IO_READ_DONE,
515  // then the device hasn't even entered the copy routine yet,
516  // so sleep to not slow it down by overloading it with USB
517  // requests
518  if(rv[0] != XU1541_IO_READ_DONE)
519  {
520  xu1541_dbg(3, "unexpected result");
521  arch_usleep(TIMEOUT_DELAY);
522  }
523  else
524  {
525  xu1541_dbg(3, "link ok");
526 
527  link_ok = 1;
528  errno = 0;
529  }
530  }
531  else
532  {
533  xu1541_dbg(3, "usb timeout");
534 
535  /* count the error states (just out of couriosity) */
536  err++;
537  }
538  }
539  while(!link_ok);
540 
541  /* finally read data itself */
542  if((rd = usb.control_msg(xu1541_handle,
543  USB_TYPE_CLASS | USB_ENDPOINT_IN,
544  XU1541_READ, bytes2read, 0,
545  (char*)data, bytes2read, 1000)) < 0)
546  {
547  fprintf(stderr, "USB error in xu1541_read(): %s\n",
548  usb.strerror());
549  return -1;
550  }
551 
552  len -= rd;
553  data += rd;
554  bytesRead += rd;
555 
556  xu1541_dbg(2, "received chunk of %d bytes, total %d, left %d",
557  rd, bytesRead, len);
558 
559  /* force end of read */
560  if(rd < bytes2read)
561  len = 0;
562  }
563  return bytesRead;
564 }
565 
588 int xu1541_special_write(int mode, const unsigned char *data, size_t size)
589 {
590  int bytesWritten = 0;
591 
592  xu1541_dbg(1, "special write %d %d bytes from address %p",
593  mode, size, data);
594 
595  while(size > 0)
596  {
597  int wr, bytes2write = (size>128)?128:size;
598 
599  if((wr = usb.control_msg(xu1541_handle,
600  USB_TYPE_CLASS | USB_ENDPOINT_OUT,
601  mode, XU1541_WRITE, bytes2write,
602  (char*)data, bytes2write, 1000)) < 0)
603  {
604  fprintf(stderr, "USB error in xu1541_special_write(): %s\n",
605  usb.strerror());
606  return -1;
607  }
608 
609  xu1541_dbg(2, "special wrote %d bytes", wr);
610 
611  size -= wr;
612  data += wr;
613  bytesWritten += wr;
614  }
615 
616  return bytesWritten;
617 }
618 
636 int xu1541_special_read(int mode, unsigned char *data, size_t size)
637 {
638  int bytesRead = 0;
639 
640  xu1541_dbg(1, "special read %d %d bytes to address %p",
641  mode, size, data);
642 
643  while(size > 0)
644  {
645  int rd, bytes2read = (size>128)?128:size;
646 
647  if((rd = usb.control_msg(xu1541_handle,
648  USB_TYPE_CLASS | USB_ENDPOINT_IN,
649  mode, XU1541_READ, bytes2read,
650  (char*)data, bytes2read,
651  USB_TIMEOUT)) < 0)
652  {
653  fprintf(stderr, "USB error in xu1541_special_read(): %s\n",
654  usb.strerror());
655  return -1;
656  }
657 
658  xu1541_dbg(2, "special read %d bytes", rd);
659 
660  size -= rd;
661  data += rd;
662  bytesRead += rd;
663 
664  /* stop if there's nothing more to read */
665  if(rd < bytes2read)
666  size = 0;
667  }
668 
669  return bytesRead;
670 }
int xu1541_special_read(int mode, unsigned char *data, size_t size)
"special" read data from the xu1541 device
Definition: xu1541.c:636
#define TIMEOUT_DELAY
timeout value, used mainly after errors
Definition: xu1541.c:37
void xu1541_close(void)
close the xu1541 device
Definition: xu1541.c:243
Allow for libusb (0.1) to be loaded dynamically (Currently, this is used on Windows only) ...
Shared library / DLL for accessing the driver Functions for obtaining the addresses of plugin functio...
int xu1541_ioctl(unsigned int cmd, unsigned int addr, unsigned int secaddr)
perform an ioctl on the xu1541
Definition: xu1541.c:270
int xu1541_special_write(int mode, const unsigned char *data, size_t size)
"special" write data to the xu1541 device
Definition: xu1541.c:588
int xu1541_init(void)
initialise the xu1541 device
Definition: xu1541.c:132
int xu1541_read(unsigned char *data, size_t len)
read data from the xu1541 device
Definition: xu1541.c:461
DLL interface for accessing the driver.
Define makros and functions which account for differences between the different architectures.
Definition: usb.h:260
int xu1541_write(const unsigned char *data, size_t len)
write data to the xu1541 device
Definition: xu1541.c:379