24 #define TAPE_SUPPORT 1
40 #ifndef LIBUSB_PATH_MAX
41 #define LIBUSB_PATH_MAX 512
44 static int debug_level = -1;
46 unsigned char DeviceDriveMode;
57 xum1541_dbg(
int level,
char *msg, ...)
62 if (debug_level == -1) {
63 char *val = getenv(
"XUM1541_DEBUG");
65 debug_level = atoi(val);
68 if (level <= debug_level) {
69 fprintf(stderr,
"[XUM1541] ");
71 vfprintf(stderr, msg, argp);
73 fprintf(stderr,
"\n");
99 usbGetStringAscii(usb_dev_handle *dev,
int index,
int langid,
100 char *buf,
int buflen)
105 rval = usb.control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
106 (USB_DT_STRING << 8) + index, langid,
107 buffer,
sizeof(buffer), 1000);
111 if (buffer[1] != USB_DT_STRING)
113 if ((
unsigned char)buffer[0] < rval)
114 rval = (
unsigned char)buffer[0];
118 for (i = 1; i < rval; i++) {
121 buf[i-1] = buffer[2 * i];
122 if (buffer[2 * i + 1] != 0)
131 xum1541_cleanup(usb_dev_handle **HandleXum1541,
char *msg, ...)
137 fprintf(stderr, msg, args);
140 if (*HandleXum1541 != NULL)
141 usb.close(*HandleXum1541);
142 *HandleXum1541 = NULL;
147 xum1541_enumerate(usb_dev_handle **HandleXum1541,
int PortNumber)
149 static char xumProduct[] =
"xum1541";
150 static int prodLen =
sizeof(xumProduct) - 1;
152 struct usb_device *dev, *preferredDefaultHandle;
154 int len, serialnum, leastserial;
156 if (PortNumber < 0 || PortNumber > MAX_ALLOWED_XUM1541_SERIALNUM) {
161 xum1541_dbg(0,
"scanning usb ...");
171 *HandleXum1541 = NULL;
172 preferredDefaultHandle = NULL;
173 leastserial = MAX_ALLOWED_XUM1541_SERIALNUM + 1;
174 for (bus = usb.get_busses(); !*HandleXum1541 && bus; bus = bus->next) {
175 xum1541_dbg(1,
"scanning bus %s", bus->dirname);
176 for (dev = bus->devices; !*HandleXum1541 && dev; dev = dev->next) {
177 xum1541_dbg(1,
"device %04x:%04x at %s",
178 dev->descriptor.idVendor, dev->descriptor.idProduct,
182 if (dev->descriptor.idVendor != XUM1541_VID ||
183 dev->descriptor.idProduct != XUM1541_PID)
186 xum1541_dbg(0,
"found xu/xum1541 version %04x on bus %s, device %s",
187 dev->descriptor.bcdDevice, bus->dirname, dev->filename);
188 if ((*HandleXum1541 = usb.open(dev)) == NULL) {
189 fprintf(stderr,
"error: Cannot open USB device: %s\n",
196 len = usbGetStringAscii(*HandleXum1541, dev->descriptor.iProduct,
197 0x0409,
string,
sizeof(
string) - 1);
199 xum1541_cleanup(HandleXum1541,
200 "error: cannot query product name: %s\n", usb.strerror());
204 if (len < prodLen || strstr(
string, xumProduct) == NULL) {
205 xum1541_cleanup(HandleXum1541, NULL);
208 xum1541_dbg(0,
"xum1541 name: %s",
string);
210 len = usbGetStringAscii(*HandleXum1541,
211 dev->descriptor.iSerialNumber, 0x0409,
212 string,
sizeof(
string) - 1);
213 if (len < 0 && PortNumber != 0){
215 xum1541_cleanup(HandleXum1541,
216 "error: cannot query serial number: %s\n",
221 if (len > 0 && len <=3 ) {
223 serialnum = atoi(
string);
225 if (PortNumber != serialnum) {
228 if(serialnum < leastserial) {
229 leastserial = serialnum;
230 preferredDefaultHandle = dev;
232 xum1541_cleanup(HandleXum1541, NULL);
236 xum1541_dbg(0,
"xum1541 serial number: %3u", serialnum);
242 if(preferredDefaultHandle != NULL) {
243 if ((*HandleXum1541 = usb.open(preferredDefaultHandle)) == NULL) {
244 fprintf(stderr,
"error: Cannot reopen USB device: %s\n",
252 xum1541_check_version(
int version)
254 xum1541_dbg(0,
"firmware version %d, library version %d", version,
256 if (version < XUM1541_VERSION) {
257 fprintf(stderr,
"xum1541 firmware version too low (%d < %d)\n",
258 version, XUM1541_VERSION);
259 fprintf(stderr,
"please update your xum1541 firmware\n");
261 }
else if (version > XUM1541_VERSION) {
262 fprintf(stderr,
"xum1541 firmware version too high (%d > %d)\n",
263 version, XUM1541_VERSION);
264 fprintf(stderr,
"please update your OpenCBM plugin\n");
289 #define PREFIX_OFFSET (sizeof("libusb/xum1541:") - 1)
290 usb_dev_handle *HandleXum1541;
291 static char dev_path[PREFIX_OFFSET + LIBUSB_PATH_MAX] =
"libusb/xum1541:";
293 dev_path[PREFIX_OFFSET + 1] =
'\0';
294 xum1541_enumerate(&HandleXum1541, PortNumber);
296 if (HandleXum1541 != NULL) {
297 strcpy(dev_path, (usb.device(HandleXum1541))->filename);
300 fprintf(stderr,
"error: no xum1541 device found\n");
308 xum1541_clear_halt(usb_dev_handle *handle)
312 ret = usb.clear_halt(handle, XUM_BULK_IN_ENDPOINT | USB_ENDPOINT_IN);
314 fprintf(stderr,
"USB clear halt request failed for in ep: %s\n",
318 ret = usb.clear_halt(handle, XUM_BULK_OUT_ENDPOINT);
320 fprintf(stderr,
"USB clear halt request failed for out ep: %s\n",
335 ret = usb.control_msg(handle, USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE,
336 0, XUM_BULK_IN_ENDPOINT | USB_ENDPOINT_IN, NULL, 0, USB_TIMEOUT);
338 fprintf(stderr,
"USB clear control req failed for in ep: %s\n",
342 ret = usb.control_msg(handle, USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE,
343 0, XUM_BULK_OUT_ENDPOINT, NULL, 0, USB_TIMEOUT);
345 fprintf(stderr,
"USB clear control req failed for out ep: %s\n",
376 unsigned char devInfo[XUM_DEVINFO_SIZE], devStatus;
380 DeviceDriveMode = DeviceDriveMode_Uninit;
382 xum1541_enumerate(HandleXum1541, PortNumber);
384 if (*HandleXum1541 == NULL) {
385 fprintf(stderr,
"error: no xum1541 device found\n");
390 if (usb.set_configuration(*HandleXum1541, 1) != 0) {
391 xum1541_cleanup(HandleXum1541,
"USB error: %s\n", usb.strerror());
400 if (usb.claim_interface(*HandleXum1541, 0) != 0) {
401 xum1541_cleanup(HandleXum1541,
"USB error: %s\n", usb.strerror());
406 memset(devInfo, 0,
sizeof(devInfo));
407 len = usb.control_msg(*HandleXum1541, USB_TYPE_CLASS | USB_ENDPOINT_IN,
408 XUM1541_INIT, 0, 0, (
char*)devInfo,
sizeof(devInfo), USB_TIMEOUT);
410 fprintf(stderr,
"USB request for XUM1541 info failed: %s\n",
415 if (xum1541_check_version(devInfo[0]) != 0) {
420 xum1541_dbg(0,
"device capabilities %02x status %02x",
421 devInfo[1], devInfo[2]);
425 devStatus = devInfo[2];
426 if ((devStatus & XUM1541_DOING_RESET) != 0) {
427 fprintf(stderr,
"previous command was interrupted, resetting\n");
429 if (xum1541_clear_halt(*HandleXum1541) < 0) {
436 if (devInfo[1] & XUM1541_CAP_TAP)
438 if (devInfo[2] & XUM1541_TAPE_PRESENT)
440 DeviceDriveMode = DeviceDriveMode_Tape;
441 xum1541_dbg(1,
"[xum1541_init] Tape supported, tape mode entered.");
445 DeviceDriveMode = DeviceDriveMode_Disk;
446 xum1541_dbg(1,
"[xum1541_init] Tape supported, disk mode entered.");
451 DeviceDriveMode = (
unsigned char) DeviceDriveMode_NoTapeSupport;
452 xum1541_dbg(1,
"[xum1541_init] No tape support.");
470 xum1541_dbg(0,
"Closing USB link");
472 ret = usb.control_msg(HandleXum1541, USB_TYPE_CLASS | USB_ENDPOINT_OUT,
473 XUM1541_SHUTDOWN, 0, 0, NULL, 0, 1000);
476 "USB request for XUM1541 close failed, continuing: %s\n",
479 if (usb.release_interface(HandleXum1541, 0) != 0)
480 fprintf(stderr,
"USB release intf error: %s\n", usb.strerror());
482 if (usb.close(HandleXum1541) != 0)
483 fprintf(stderr,
"USB close error: %s\n", usb.strerror());
503 xum1541_dbg(1,
"control msg %d", cmd);
505 nBytes = usb.control_msg(HandleXum1541, USB_TYPE_CLASS | USB_ENDPOINT_OUT,
506 cmd, 0, 0, NULL, 0, USB_TIMEOUT);
508 fprintf(stderr,
"USB error in xum1541_control_msg: %s\n",
517 xum1541_wait_status(usb_dev_handle *HandleXum1541)
519 int nBytes, deviceBusy, ret;
520 unsigned char statusBuf[XUM_STATUSBUF_SIZE];
522 xum1541_dbg(2,
"xum1541_wait_status checking for status");
525 nBytes = usb.bulk_read(HandleXum1541,
526 XUM_BULK_IN_ENDPOINT | USB_ENDPOINT_IN,
527 (
char*)statusBuf, XUM_STATUSBUF_SIZE, LIBUSB_NO_TIMEOUT);
528 if (nBytes == XUM_STATUSBUF_SIZE) {
529 switch (XUM_GET_STATUS(statusBuf)) {
530 case XUM1541_IO_BUSY:
531 xum1541_dbg(2,
"device busy, waiting");
533 case XUM1541_IO_ERROR:
534 fprintf(stderr,
"device reports error\n");
536 case XUM1541_IO_READY:
540 fprintf(stderr,
"unknown status value: %d\n",
541 XUM_GET_STATUS(statusBuf));
545 fprintf(stderr,
"USB error in xum1541_wait_status: %s\n",
552 if (XUM_GET_STATUS(statusBuf) == XUM1541_IO_READY)
553 ret = XUM_GET_STATUS_VAL(statusBuf);
557 xum1541_dbg(2,
"return val = %x", ret);
563 #define RefuseToWorkInWrongMode \
565 if (DeviceDriveMode == DeviceDriveMode_Uninit) \
567 xum1541_dbg(1, "[RefuseToWorkInWrongMode] cmd blocked - No disk or tape mode set."); \
568 return XUM1541_Error_NoDiskTapeMode; \
573 if (DeviceDriveMode == DeviceDriveMode_NoTapeSupport) \
575 xum1541_dbg(1, "[RefuseToWorkInWrongMode] cmd blocked - Firmware has no tape support."); \
576 return XUM1541_Error_NoTapeSupport; \
579 if (DeviceDriveMode == DeviceDriveMode_Disk) \
581 xum1541_dbg(1, "[RefuseToWorkInWrongMode] cmd blocked - Tape cmd in disk mode."); \
582 return XUM1541_Error_TapeCmdInDiskMode; \
587 if (DeviceDriveMode == DeviceDriveMode_Tape) \
589 xum1541_dbg(1, "[RefuseToWorkInWrongMode] cmd blocked - Disk cmd in tape mode."); \
590 return XUM1541_Error_DiskCmdInTapeMode; \
616 xum1541_ioctl(usb_dev_handle *HandleXum1541,
unsigned int cmd,
unsigned int addr,
unsigned int secaddr)
619 unsigned char cmdBuf[XUM_CMDBUF_SIZE];
620 BOOL isTapeCmd = ((XUM1541_TAP_MOTOR_ON <= cmd) && (cmd <= XUM1541_TAP_MOTOR_OFF));
622 xum1541_dbg(1,
"ioctl %d for device %d, sub %d", cmd, addr, secaddr);
624 RefuseToWorkInWrongMode;
626 cmdBuf[0] = (
unsigned char)cmd;
627 cmdBuf[1] = (
unsigned char)addr;
628 cmdBuf[2] = (
unsigned char)secaddr;
632 nBytes = usb.bulk_write(HandleXum1541,
633 XUM_BULK_OUT_ENDPOINT | USB_ENDPOINT_OUT,
634 (
char *)cmdBuf,
sizeof(cmdBuf), LIBUSB_NO_TIMEOUT);
636 fprintf(stderr,
"USB error in xum1541_ioctl cmd: %s\n",
642 ret = xum1541_wait_status(HandleXum1541);
643 xum1541_dbg(2,
"return val = %x", ret);
658 BOOL isTapeCmd = TRUE;
659 RefuseToWorkInWrongMode;
661 xum1541_dbg(1,
"[xum1541_tap_break] Sending tape break command.");
686 xum1541_write(usb_dev_handle *HandleXum1541,
unsigned char modeFlags,
const unsigned char *data,
size_t size)
689 size_t bytesWritten, bytes2write;
690 unsigned char cmdBuf[XUM_CMDBUF_SIZE];
691 BOOL isTapeCmd = ((modeFlags == XUM1541_TAP) || (modeFlags == XUM1541_TAP_CONFIG));
693 mode = modeFlags & 0xf0;
694 xum1541_dbg(1,
"write %d %d bytes from address %p flags %x",
695 mode, size, data, modeFlags & 0x0f);
697 RefuseToWorkInWrongMode;
700 cmdBuf[0] = XUM1541_WRITE;
701 cmdBuf[1] = modeFlags;
702 cmdBuf[2] = size & 0xff;
703 cmdBuf[3] = (size >> 8) & 0xff;
704 wr = usb.bulk_write(HandleXum1541,
705 XUM_BULK_OUT_ENDPOINT | USB_ENDPOINT_OUT,
706 (
char *)cmdBuf,
sizeof(cmdBuf), LIBUSB_NO_TIMEOUT);
708 fprintf(stderr,
"USB error in write cmd: %s\n",
714 while (bytesWritten < size) {
715 bytes2write = size - bytesWritten;
716 if (bytes2write > XUM_MAX_XFER_SIZE)
717 bytes2write = XUM_MAX_XFER_SIZE;
718 wr = usb.bulk_write(HandleXum1541,
719 XUM_BULK_OUT_ENDPOINT | USB_ENDPOINT_OUT,
720 (
char *)data, bytes2write, LIBUSB_NO_TIMEOUT);
724 if (usb.resetep(HandleXum1541, XUM_BULK_OUT_ENDPOINT | USB_ENDPOINT_OUT) < 0)
725 fprintf(stderr,
"USB reset ep request failed for out ep (tape stall): %s\n", usb.strerror());
726 if (usb.control_msg(HandleXum1541, USB_RECIP_ENDPOINT, USB_REQ_CLEAR_FEATURE, 0, XUM_BULK_OUT_ENDPOINT, NULL, 0, USB_TIMEOUT) < 0)
727 fprintf(stderr,
"USB error in xum1541_control_msg (tape stall): %s\n", usb.strerror());
730 fprintf(stderr,
"USB error in write data: %s\n",
734 xum1541_dbg(2,
"wrote %d bytes", wr);
743 if (wr < (
int)bytes2write)
748 if (mode == XUM1541_CBM) {
749 ret = xum1541_wait_status(HandleXum1541);
751 xum1541_dbg(2,
"wait done, extended status %d", ret);
753 xum1541_dbg(2,
"wait done with error");
757 xum1541_dbg(2,
"write done, got %d bytes", bytesWritten);
775 xum1541_write_ext(usb_dev_handle *HandleXum1541,
unsigned char modeFlags,
const unsigned char *data,
size_t size,
int *Status,
int *BytesWritten)
777 xum1541_dbg(1,
"[xum1541_write_ext]");
778 *BytesWritten =
xum1541_write(HandleXum1541, modeFlags, data, size);
779 if (*BytesWritten < 0)
780 return *BytesWritten;
781 xum1541_dbg(2,
"[xum1541_write_ext] BytesWritten = %d", *BytesWritten);
782 *Status = xum1541_wait_status(HandleXum1541);
783 xum1541_dbg(2,
"[xum1541_write_ext] Status = %d", *Status);
801 xum1541_read_ext(usb_dev_handle *HandleXum1541,
unsigned char mode,
unsigned char *data,
size_t size,
int *Status,
int *BytesRead)
803 xum1541_dbg(1,
"[xum1541_read_ext]");
804 *BytesRead =
xum1541_read(HandleXum1541, mode, data, size);
807 xum1541_dbg(2,
"[xum1541_read_ext] BytesRead = %d", *BytesRead);
808 *Status = xum1541_wait_status(HandleXum1541);
809 xum1541_dbg(2,
"[xum1541_read_ext] Status = %d", *Status);
833 xum1541_read(usb_dev_handle *HandleXum1541,
unsigned char mode,
unsigned char *data,
size_t size)
836 size_t bytesRead, bytes2read;
837 unsigned char cmdBuf[XUM_CMDBUF_SIZE];
838 BOOL isTapeCmd = ((mode == XUM1541_TAP) || (mode == XUM1541_TAP_CONFIG));
840 xum1541_dbg(1,
"read %d %d bytes to address %p",
843 RefuseToWorkInWrongMode;
846 cmdBuf[0] = XUM1541_READ;
848 cmdBuf[2] = size & 0xff;
849 cmdBuf[3] = (size >> 8) & 0xff;
850 rd = usb.bulk_write(HandleXum1541,
851 XUM_BULK_OUT_ENDPOINT | USB_ENDPOINT_OUT,
852 (
char *)cmdBuf,
sizeof(cmdBuf), LIBUSB_NO_TIMEOUT);
854 fprintf(stderr,
"USB error in read cmd: %s\n",
861 while (bytesRead < size) {
862 bytes2read = size - bytesRead;
863 if (bytes2read > XUM_MAX_XFER_SIZE)
864 bytes2read = XUM_MAX_XFER_SIZE;
865 rd = usb.bulk_read(HandleXum1541,
866 XUM_BULK_IN_ENDPOINT | USB_ENDPOINT_IN,
867 (
char *)data, bytes2read, LIBUSB_NO_TIMEOUT);
869 fprintf(stderr,
"USB error in read data(%p, %d): %s\n",
870 data, (
int)size, usb.strerror());
873 xum1541_dbg(2,
"read %d bytes", rd);
882 if (rd < (
int)bytes2read)
886 xum1541_dbg(2,
"read done, got %d bytes", bytesRead);
const char * xum1541_device_path(int PortNumber)
Query unique identifier for the xum1541 device This function tries to find an unique identifier for t...
void xum1541_close(usb_dev_handle *HandleXum1541)
close the xum1541 device
int xum1541_tap_break(usb_dev_handle *HandleXum1541)
Send tape operations abort command to the xum1541 device.
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 xum1541_write(usb_dev_handle *HandleXum1541, unsigned char modeFlags, const unsigned char *data, size_t size)
Write data to the xum1541 device.
int xum1541_read_ext(usb_dev_handle *HandleXum1541, unsigned char mode, unsigned char *data, size_t size, int *Status, int *BytesRead)
Wrapper for xum1541_read() forcing xum1541_wait_status(), with additional parameters: ...
DLL interface for accessing the driver.
int xum1541_init(usb_dev_handle **HandleXum1541, int PortNumber)
Initialize the xum1541 device This function tries to find and identify the xum1541 device...
Define makros and functions which account for differences between the different architectures.
int xum1541_write_ext(usb_dev_handle *HandleXum1541, unsigned char modeFlags, const unsigned char *data, size_t size, int *Status, int *BytesWritten)
Wrapper for xum1541_write() forcing xum1541_wait_status(), with additional parameters: ...
int xum1541_ioctl(usb_dev_handle *HandleXum1541, unsigned int cmd, unsigned int addr, unsigned int secaddr)
Perform an ioctl on the xum1541, which is any command other than read/write or special device managem...
int xum1541_control_msg(usb_dev_handle *HandleXum1541, unsigned int cmd)
Handle synchronous USB control messages, e.g. for RESET. xum1541_ioctl() is used for bulk messages...
int xum1541_read(usb_dev_handle *HandleXum1541, unsigned char mode, unsigned char *data, size_t size)
Read data from the xum1541 device.