diff --git a/CHANGELOG b/CHANGELOG index d0652af..41398d9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -5,6 +5,7 @@ drivers (openbsd, netbsd, and others) set a byte-to-byte timeout which can be exceeded by SD card latency. - Upgrade to PSoC Creator 3.1 and gcc 4.8.4. + - Integrated scsi2sd-debug functionality with scsi2sd-util. 20150108 4.0 - Fix handling requests for LUNs other than 0 from SCSI-2 hosts. diff --git a/hardware/gerber/scsi2sd.xy b/hardware/gerber/scsi2sd.xy deleted file mode 100644 index 444b04c..0000000 --- a/hardware/gerber/scsi2sd.xy +++ /dev/null @@ -1,55 +0,0 @@ -# PcbXY Version 1.0 -# Date: Tue 09 Dec 2014 09:51:33 GMT UTC -# Author: Michael McMaster -# Title: (unknown) - PCB X-Y -# RefDes, Description, Value, X, Y, rotation, top/bottom -# X,Y in mil. rotation in degrees. -# -------------------------------------------- -Q1,"SOT23_MOSFET","unknown",3327.09,2042.42,90,top -U4,"SO14","unknown",2243.00,2414.50,270,top -C22,"cap_0402","100nF",2940.94,188.00,180,top -U3,"SO14","unknown",2820.00,2412.00,270,top -U5,"SO14","unknown",1742.00,2410.50,270,top -R5,"SMD_SIMPLE-80-50","22?",2266.41,1116.78,0,top -J5,"fci-10118192-0001LF","unknown",1952.25,128.13,0,top -R4,"SMD_SIMPLE-80-50","22?",2226.00,1211.00,0,top -C2,"SMD_SIMPLE-80-50","10uF",1845.00,1252.00,0,top -C9,"cap_0402","100nF",1949.69,1352.00,0,top -C8,"cap_0402","1uF",2369.68,1217.00,180,top -C20,"cap_0402","1uF",2397.06,1296.82,90,top -C21,"cap_0402","100nF",2770.31,2007.00,180,top -C11,"cap_0402","100nF",1970.00,2306.68,270,top -C3,"cap_0402","100nF",3045.00,2306.68,270,top -C19,"cap_0402","100nF",2355.00,2141.68,270,top -C23,"cap_0402","100nF",2345.63,1297.32,90,top -C10,"cap_0402","100nF",2465.00,2306.68,270,top -C17,"cap_0402","100nF",2030.00,2112.31,270,top -C28,"cap_0402","100nF",2705.00,1347.32,90,top -D2,"diode-DO-214AA-SMB","unknown",190.00,2882.35,90,top -F1,"SMD_SIMPLE-120-60","1.5A Hold",146.00,3203.00,270,top -D1,"diode-DO-214AA-SMB","unknown",925.00,2881.65,90,top -F2,"SMD_SIMPLE-120-60","500mA Hold",1624.00,164.00,180,top -D3,"diode-DO-214AA-SMB","unknown",1355.35,207.00,0,top -R3,"SMD_SIMPLE-80-50","1600",3108.59,2124.22,180,top -C26,"cap_0402","1uF",2815.00,1756.68,270,top -C24,"cap_0402","100nF",2750.00,1757.31,270,top -C27,"cap_0402","1uF",2815.00,1662.32,90,top -U1,"TQFP100_14_reflow","unknown",2339.53,1723.95,0,top -C13,"SMD_SIMPLE-80-50","10uF",2977.20,334.06,180,top -U6,"DPAK","unknown",725.00,812.00,0,top -C12,"SMD_SIMPLE-80-50","10uF",497.06,584.80,0,top -U2,"DPAK","unknown",725.00,1987.00,0,top -C5,"SMD_SIMPLE-80-50","10uF",548.23,1752.12,180,top -J6,"wurth-microsd","unknown",2542.10,257.35,180,top -R6,"SMD_SIMPLE-80-50","22?",3330.00,1907.00,0,top -R7,"SMD_SIMPLE-80-50","56?",3325.00,2202.00,0,top -C6,"SMD_SIMPLE-80-50","10uF",410.00,2312.00,0,top -R9,"SMD_SIMPLE-80-50","154?",410.00,2217.00,0,top -R8,"SMD_SIMPLE-80-50","120?",570.00,2217.00,0,top -C16,"cap_0402","0.1uF",1335.00,2886.68,270,top -C15,"cap_0402","0.1uF",2410.35,2886.03,270,top -C14,"SMD_SIMPLE-120-60","47uF",785.00,1047.00,0,top -C4,"SMD_SIMPLE-120-60","47uF",185.00,2622.00,0,top -C7,"SMD_SIMPLE-120-60","47uF",845.00,1752.00,0,top -C1,"SMD_SIMPLE-120-60","47uF",1225.00,2949.00,270,top -LED1,"SMD_DIODE-80-50","unknown",3109.00,2015.00,0,top diff --git a/software/SCSI2SD/src/mode.c b/software/SCSI2SD/src/mode.c index 56f34d7..e748b1b 100755 --- a/software/SCSI2SD/src/mode.c +++ b/software/SCSI2SD/src/mode.c @@ -27,7 +27,18 @@ static const uint8 ReadWriteErrorRecoveryPage[] = { 0x01, // Page code 0x0A, // Page length -0x00, // No error recovery options for now + +// VMS 5.5-2 is very particular regarding the mode page values. +// The required values for a SCSI2/NoTCQ device are: +// AWRE=0 ARRE=0 TB=1 RC=0 EER=? PER=1 DTE=1 DCR=? +// See ftp://www.digiater.nl/openvms/decus/vms94b/net94b/scsi_params_dkdriver.txt +// X-Newsgroups: comp.os.vms +// Subject: Re: VMS 6.1 vs. Seagate Disk Drives +// Message-Id: <32g87h$8q@nntpd.lkg.dec.com> +// From: weber@evms.enet.dec.com (Ralph O. Weber -- OpenVMS AXP) +// Date: 12 Aug 1994 16:32:49 GMT +0x26, + 0x00, // Don't try recovery algorithm during reads 0x00, // Correction span 0 0x00, // Head offset count 0, @@ -305,7 +316,7 @@ static void doModeSense( case 0x0A: pageIn(pc, idx, ControlModePage, sizeof(ControlModePage)); idx += sizeof(ControlModePage); - break; + if (pageCode != 0x3f) break; case 0x30: pageIn(pc, idx, AppleVendorPage, sizeof(AppleVendorPage)); diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/USBFS_descr.c b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/USBFS_descr.c index 3144a03..ccd6a78 100644 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/USBFS_descr.c +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/USBFS_descr.c @@ -94,7 +94,7 @@ const uint8 CYCODE USBFS_DEVICE0_CONFIGURATION0_DESCR[73u] = { /* bEndpointAddress */ 0x01u, /* bmAttributes */ 0x03u, /* wMaxPacketSize */ 0x40u, 0x00u, -/* bInterval */ 0x80u, +/* bInterval */ 0x20u, /********************************************************************* * Endpoint Descriptor *********************************************************************/ @@ -103,7 +103,7 @@ const uint8 CYCODE USBFS_DEVICE0_CONFIGURATION0_DESCR[73u] = { /* bEndpointAddress */ 0x82u, /* bmAttributes */ 0x03u, /* wMaxPacketSize */ 0x40u, 0x00u, -/* bInterval */ 0x40u, +/* bInterval */ 0x20u, /********************************************************************* * Interface Descriptor *********************************************************************/ @@ -135,7 +135,7 @@ const uint8 CYCODE USBFS_DEVICE0_CONFIGURATION0_DESCR[73u] = { /* bEndpointAddress */ 0x03u, /* bmAttributes */ 0x03u, /* wMaxPacketSize */ 0x40u, 0x00u, -/* bInterval */ 0x80u, +/* bInterval */ 0x20u, /********************************************************************* * Endpoint Descriptor *********************************************************************/ @@ -144,7 +144,7 @@ const uint8 CYCODE USBFS_DEVICE0_CONFIGURATION0_DESCR[73u] = { /* bEndpointAddress */ 0x84u, /* bmAttributes */ 0x03u, /* wMaxPacketSize */ 0x40u, 0x00u, -/* bInterval */ 0x40u +/* bInterval */ 0x20u }; /********************************************************************* diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c index dfdc40a..acda16c 100644 --- a/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c +++ b/software/SCSI2SD/v3/SCSI2SD.cydsn/Generated_Source/PSoC5/cymetadata.c @@ -28,7 +28,7 @@ __attribute__ ((__section__(".cyloadablemeta"), used)) const uint8 cy_meta_loadable[] = { 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x05u, 0x04u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0xD1u, 0x10u, 0x04u, 0x01u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit b/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit index 3040c7e..cf48a6b 100644 Binary files a/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/v3/SCSI2SD.cydsn/SCSI2SD.cyfit differ diff --git a/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch b/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch index 8bbd6de..6a33d2e 100755 Binary files a/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/v3/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ diff --git a/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyfit b/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyfit index 953ab81..c2bb61e 100644 Binary files a/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyfit and b/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyfit differ diff --git a/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyprj.Micha_000 b/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyprj.Micha_000 index 688eb60..cbfc68c 100755 --- a/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyprj.Micha_000 +++ b/software/SCSI2SD/v3/USB_Bootloader.cydsn/USB_Bootloader.cyprj.Micha_000 @@ -1492,6 +1492,7 @@ + @@ -1525,7 +1526,7 @@ - + @@ -2141,14 +2142,14 @@ C:\Program Files (x86)\Cypress\PSoC Creator\3.1\PSoC Creator\psoc\content\cyprimitives\CyPrimitives.cylib\ZeroTerminal\ZeroTerminal.v C:\Program Files (x86)\Cypress\PSoC Creator\3.1\PSoC Creator\warp\lib\common\stdlogic\rtlpkg.vif - + - + - + diff --git a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit index 1dbc822..67548f7 100644 Binary files a/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/v4/SCSI2SD.cydsn/SCSI2SD.cyfit differ diff --git a/software/SCSI2SD/v4/USB_Bootloader.cydsn/USB_Bootloader.cyfit b/software/SCSI2SD/v4/USB_Bootloader.cydsn/USB_Bootloader.cyfit index 8d65665..73330ab 100644 Binary files a/software/SCSI2SD/v4/USB_Bootloader.cydsn/USB_Bootloader.cyfit and b/software/SCSI2SD/v4/USB_Bootloader.cydsn/USB_Bootloader.cyfit differ diff --git a/software/build.sh b/software/build.sh index d437f60..8834607 100755 --- a/software/build.sh +++ b/software/build.sh @@ -5,8 +5,7 @@ Linux) # Builds all of the utilities (not firmware) under Linux. # Requires mingw installed to cross-compile Windows targets. - (cd scsi2sd-util && ./build.sh) && - (cd scsi2sd-debug && ./build.sh) + (cd scsi2sd-util && ./build.sh) if [ $? -eq 0 ]; then mkdir -p build/linux @@ -14,25 +13,20 @@ Linux) mkdir -p build/windows/32bit cp scsi2sd-util/build/linux/scsi2sd-util build/linux - cp scsi2sd-debug/build/linux/scsi2sd-debug build/linux cp scsi2sd-util/build/windows/32bit/scsi2sd-util.exe build/windows/32bit - cp scsi2sd-debug/build/windows/32bit/scsi2sd-debug.exe build/windows/32bit cp scsi2sd-util/build/windows/64bit/scsi2sd-util.exe build/windows/64bit - cp scsi2sd-debug/build/windows/64bit/scsi2sd-debug.exe build/windows/64bit fi ;; Darwin) - make -C scsi2sd-util && - make -C scsi2sd-debug + make -C scsi2sd-util if [ $? -eq 0 ]; then mkdir -p build/mac cp scsi2sd-util/build/mac/scsi2sd-util build/mac - cp scsi2sd-debug/build/mac/scsi2sd-debug build/mac fi esac diff --git a/software/scsi2sd-debug/.gitignore b/software/scsi2sd-debug/.gitignore deleted file mode 100644 index 567609b..0000000 --- a/software/scsi2sd-debug/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/software/scsi2sd-debug/Makefile b/software/scsi2sd-debug/Makefile deleted file mode 100644 index 5690879..0000000 --- a/software/scsi2sd-debug/Makefile +++ /dev/null @@ -1,63 +0,0 @@ - -CPPFLAGS = -I ../bootloaderhost/hidapi/hidapi -I ../bootloaderhost -CFLAGS += -Wall -Wno-pointer-sign -O2 -CXXFLAGS += -Wall -O2 -VPATH += ../bootloaderhost - -TARGET ?= $(shell uname -s) -ifeq ($(TARGET),Win32) - VPATH += hidapi/windows - LDFLAGS += -static -mconsole -mwindows -lsetupapi -lws2_32 - BUILD = build/windows/32bit - CC=i686-w64-mingw32-gcc - CXX=i686-w64-mingw32-g++ - EXE=.exe -endif -ifeq ($(TARGET),Win64) - VPATH += hidapi/windows - LDFLAGS += -static -mconsole -mwindows -lsetupapi -lws2_32 - BUILD = build/windows/64bit - CC=x86_64-w64-mingw32-gcc - CXX=x86_64-w64-mingw32-g++ - EXE=.exe -endif -ifeq ($(TARGET),Linux) - VPATH += hidapi/linux - LDFLAGS += -ludev - BUILD = build/linux -endif -ifeq ($(TARGET),Darwin) - # Should match OSX - VPATH += ../bootloaderhost/hidapi-mac - LDFLAGS += -framework IOKit -framework CoreFoundation - CFLAGS += -mmacosx-version-min=10.7 - CXXFLAGS += -stdlib=libc++ -mmacosx-version-min=10.7 -std=c++0x - CC=clang - CXX=clang++ - BUILD=build/mac -endif - -all: $(BUILD)/scsi2sd-debug$(EXE) - -HIDAPI = \ - $(BUILD)/hid.o \ - -OBJ = \ - $(HIDAPI) \ - $(BUILD)/scsi2sd-debug.o \ - $(BUILD)/SCSI2SD_HID.o \ - -$(BUILD)/%.o: %.c - mkdir -p $(dir $@) - $(CC) $(CPPFLAGS) $(CFLAGS) $^ -c -o $@ - -$(BUILD)/%.o: %.cc - mkdir -p $(dir $@) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ -c -o $@ - -$(BUILD)/scsi2sd-debug$(EXE): $(OBJ) - mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@ - -clean: - rm $(BUILD)/scsi2sd-debug$(EXE) $(OBJ) diff --git a/software/scsi2sd-debug/build.sh b/software/scsi2sd-debug/build.sh deleted file mode 100755 index 64b4eea..0000000 --- a/software/scsi2sd-debug/build.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -rm -rf build/ -make && \ - make TARGET=Win32 && - make TARGET=Win64 - diff --git a/software/scsi2sd-debug/scsi2sd-debug.cc b/software/scsi2sd-debug/scsi2sd-debug.cc deleted file mode 100644 index 542f162..0000000 --- a/software/scsi2sd-debug/scsi2sd-debug.cc +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (C) 2014 Michael McMaster -// -// This file is part of SCSI2SD. -// -// SCSI2SD is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// SCSI2SD is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with SCSI2SD. If not, see . - -#include -#include -#include -#include -#include -#include -#include - -// htonl/ntohl includes. -#ifdef _WIN32 -#include -#else -#include -#endif - -#include "hidapi.h" - -#define MIN(a,b) (a < b ? a : b) - -FILE* logfile = NULL; - -static void readConfig(hid_device* handle) -{ - // First byte is the report ID (0) - unsigned char buf[65]; - memset(buf, 0, sizeof(buf)); - int result = hid_read(handle, buf, sizeof(buf)); - - if (result < 0) - { - fprintf(stderr, "USB HID Read Failure: %ls\n", hid_error(handle)); - } - int i; - for (i = 0; i < 32; ++i) - { - fprintf(logfile, "%02x ", buf[i]); - } - fprintf(logfile, "\n"); - fflush(logfile); -} - -static void usage() -{ - printf("Usage: scsi2sd-debug outputfile\n"); - printf("\n"); - printf("outputfile\tPath to the output log file.\n\n"); - printf("\n\n"); - exit(1); -} - - -int main(int argc, char* argv[]) -{ - printf("SCSI2SD Debug Utility.\n"); - printf("Copyright (C) 2014 Michael McMaster \n\n"); - - if (argc != 2) - { - usage(); - exit(1); - } - - logfile = fopen(argv[1], "w"); - if (!logfile) - { - fprintf(stderr, "Could not write to file %s.\n", argv[1]); - exit(1); - } - - - uint16_t vendorId = 0x04B4; // Cypress - uint16_t productId = 0x1337; // SCSI2SD - - printf( - "USB device parameters\n\tVendor ID:\t0x%04X\n\tProduct ID:\t0x%04X\n", - vendorId, - productId); - - // Enumerate and print the HID devices on the system - struct hid_device_info *dev = hid_enumerate(vendorId, productId); - - if (!dev) - { - fprintf(stderr, "ERROR: SCSI2SD USB device not found.\n"); - exit(1); - } - - // We need the SECOND interface for debug data - while (dev && dev->interface_number != 1) - { - dev = dev->next; - } - if (!dev) - { - fprintf(stderr, "ERROR: SCSI2SD Debug firmware not enabled.\n"); - exit(1); - } - - printf("USB Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", - dev->vendor_id, dev->product_id, dev->path, dev->serial_number); - printf("\n"); - printf(" Manufacturer: %ls\n", dev->manufacturer_string); - printf(" Product: %ls\n", dev->product_string); - printf("\n"); - - hid_device* handle = hid_open_path(dev->path); - if (!handle) - { - fprintf( - stderr, - "ERROR: Could not open device %s. Check permissions.\n", dev->path - ); - exit(1); - } - - - while (1) - { - readConfig(handle); - } - - return 0; -} - diff --git a/software/scsi2sd-util/SCSI2SD_HID.cc b/software/scsi2sd-util/SCSI2SD_HID.cc index e81821b..6944b83 100644 --- a/software/scsi2sd-util/SCSI2SD_HID.cc +++ b/software/scsi2sd-util/SCSI2SD_HID.cc @@ -90,7 +90,7 @@ HID::HID(hid_device_info* hidInfo) : for (int i = 0; i < 4; ++i) { buf[0] = 0; // report id - hid_read(dev, buf, HID_PACKET_SIZE); + hid_read_timeout(dev, buf, HID_PACKET_SIZE, HID_TIMEOUT_MS); if (watchVal == -1) watchVal = buf[25]; configIntFound = configIntFound && (buf[25] == watchVal); } @@ -177,7 +177,7 @@ HID::enterBootloader() }; int result = hid_write(myDebugHandle, hidBuf, sizeof(hidBuf)); - if (result < 0) + if (result <= 0) { const wchar_t* err = hid_error(myDebugHandle); std::stringstream ss; @@ -196,7 +196,7 @@ HID::readFlashRow(int array, int row, std::vector& out) static_cast(array), static_cast(row) }; - sendHIDPacket(cmd, out); + sendHIDPacket(cmd, out, HIDPACKET_MAX_LEN / 62); } void @@ -208,7 +208,7 @@ HID::writeFlashRow(int array, int row, const std::vector& in) cmd.push_back(static_cast(array)); cmd.push_back(static_cast(row)); std::vector out; - sendHIDPacket(cmd, out); + sendHIDPacket(cmd, out, 1); if ((out.size() < 1) || (out[0] != CONFIG_STATUS_GOOD)) { std::stringstream ss; @@ -217,6 +217,30 @@ HID::writeFlashRow(int array, int row, const std::vector& in) } } +bool +HID::readSCSIDebugInfo(std::vector& buf) +{ + buf[0] = 0; // report id + hid_set_nonblocking(myDebugHandle, 1); + int result = + hid_read_timeout( + myDebugHandle, + &buf[0], + HID_PACKET_SIZE, + HID_TIMEOUT_MS); + hid_set_nonblocking(myDebugHandle, 0); + + if (result <= 0) + { + const wchar_t* err = hid_error(myDebugHandle); + std::stringstream ss; + ss << "USB HID read failure: " << err; + throw std::runtime_error(ss.str()); + } + return result > 0; +} + + void HID::readHID(uint8_t* buffer, size_t len) { @@ -224,9 +248,9 @@ HID::readHID(uint8_t* buffer, size_t len) buffer[0] = 0; // report id int result = -1; - for (int retry = 0; retry < 3 && result < 0; ++retry) + for (int retry = 0; retry < 3 && result <= 0; ++retry) { - result = hid_read(myConfigHandle, buffer, len); + result = hid_read_timeout(myConfigHandle, buffer, len, HID_TIMEOUT_MS); } if (result < 0) @@ -243,9 +267,14 @@ HID::readDebugData() { uint8_t buf[HID_PACKET_SIZE]; buf[0] = 0; // report id - int result = hid_read(myDebugHandle, buf, HID_PACKET_SIZE); + int result = + hid_read_timeout( + myDebugHandle, + buf, + HID_PACKET_SIZE, + HID_TIMEOUT_MS); - if (result < 0) + if (result <= 0) { const wchar_t* err = hid_error(myDebugHandle); std::stringstream ss; @@ -292,7 +321,7 @@ HID::ping() std::vector out; try { - sendHIDPacket(cmd, out); + sendHIDPacket(cmd, out, 1); } catch (std::runtime_error& e) { @@ -302,26 +331,66 @@ HID::ping() return (out.size() >= 1) && (out[0] == CONFIG_STATUS_GOOD); } +std::vector +HID::getSD_CSD() +{ + std::vector cmd { CONFIG_SDINFO }; + std::vector out; + try + { + sendHIDPacket(cmd, out, 1); + } + catch (std::runtime_error& e) + { + return std::vector(16); + } + + out.resize(16); + return out; +} + +std::vector +HID::getSD_CID() +{ + std::vector cmd { CONFIG_SDINFO }; + std::vector out; + try + { + sendHIDPacket(cmd, out, 1); + } + catch (std::runtime_error& e) + { + return std::vector(16); + } + + std::vector result(16); + for (size_t i = 0; i < 16; ++i) result[i] = out[16 + i]; + return result; +} + void -HID::sendHIDPacket(const std::vector& cmd, std::vector& out) +HID::sendHIDPacket( + const std::vector& cmd, + std::vector& out, + size_t responseLength) { assert(cmd.size() <= HIDPACKET_MAX_LEN); hidPacket_send(&cmd[0], cmd.size()); uint8_t hidBuf[HID_PACKET_SIZE]; const uint8_t* chunk = hidPacket_getHIDBytes(hidBuf); + while (chunk) { uint8_t reportBuf[HID_PACKET_SIZE + 1] = { 0x00 }; // Report ID memcpy(&reportBuf[1], chunk, HID_PACKET_SIZE); int result = -1; - for (int retry = 0; retry < 10 && result < 0; ++retry) + for (int retry = 0; retry < 10 && result <= 0; ++retry) { result = hid_write(myConfigHandle, reportBuf, sizeof(reportBuf)); - if (result < 0) wxMilliSleep(8); } - if (result < 0) + if (result <= 0) { const wchar_t* err = hid_error(myConfigHandle); std::stringstream ss; @@ -335,16 +404,11 @@ HID::sendHIDPacket(const std::vector& cmd, std::vector& out) size_t respLen; resp = hidPacket_getPacket(&respLen); - // We need to poll quick enough to not skip packets - // This depends on the USB HID device poll rate parameter. - // SCSI2SD uses a 32ms poll rate, so we check for new chunks at 4x - // that rate. - for (int retry = 0; retry < (HIDPACKET_MAX_LEN / 62) * 30 && !resp; ++retry) + for (int retry = 0; retry < responseLength * 2 && !resp; ++retry) { - readHID(hidBuf, sizeof(hidBuf)); + readHID(hidBuf, sizeof(hidBuf)); // Will block hidPacket_recv(hidBuf, HID_PACKET_SIZE); resp = hidPacket_getPacket(&respLen); - if (!resp) wxMilliSleep(8); } if (!resp) diff --git a/software/scsi2sd-util/SCSI2SD_HID.hh b/software/scsi2sd-util/SCSI2SD_HID.hh index 98d62ed..443b3df 100644 --- a/software/scsi2sd-util/SCSI2SD_HID.hh +++ b/software/scsi2sd-util/SCSI2SD_HID.hh @@ -43,6 +43,11 @@ public: static const size_t HID_PACKET_SIZE = 64; + // HID intervals for 4.0.3 firmware: <= 128ms + // > 4.0.3 = 32ms. + static const size_t HID_TIMEOUT_MS = 256; // 2x HID Interval. + + static HID* Open(); ~HID(); @@ -50,19 +55,26 @@ public: uint16_t getFirmwareVersion() const { return myFirmwareVersion; } std::string getFirmwareVersionStr() const; uint32_t getSDCapacity() const { return mySDCapacity; } + std::vector getSD_CSD(); + std::vector getSD_CID(); void enterBootloader(); void readFlashRow(int array, int row, std::vector& out); void writeFlashRow(int array, int row, const std::vector& in); bool ping(); + + bool readSCSIDebugInfo(std::vector& buf); + private: HID(hid_device_info* hidInfo); void destroy(); void readDebugData(); void readHID(uint8_t* buffer, size_t len); void sendHIDPacket( - const std::vector& cmd, std::vector& out + const std::vector& cmd, + std::vector& out, + size_t responseLength ); hid_device_info* myHidInfo; diff --git a/software/scsi2sd-util/scsi2sd-util.cc b/software/scsi2sd-util/scsi2sd-util.cc index c608e32..a5ec3ee 100644 --- a/software/scsi2sd-util/scsi2sd-util.cc +++ b/software/scsi2sd-util/scsi2sd-util.cc @@ -41,6 +41,7 @@ #include "Firmware.hh" #include +#include #include #include #include @@ -135,7 +136,8 @@ public: AppFrame() : wxFrame(NULL, wxID_ANY, "scsi2sd-util", wxPoint(50, 50), wxSize(600, 650)), myInitialConfig(false), - myTickCounter(0) + myTickCounter(0), + myLastPollTime(0) { wxMenu *menuFile = new wxMenu(); menuFile->Append( @@ -155,17 +157,23 @@ public: "Show &Log", "Show debug log window"); + wxMenu *menuDebug = new wxMenu(); + mySCSILogChk = menuDebug->AppendCheckItem( + ID_SCSILog, + "Log SCSI data", + "Log SCSI commands"); + wxMenu *menuHelp = new wxMenu(); menuHelp->Append(wxID_ABOUT); wxMenuBar *menuBar = new wxMenuBar(); menuBar->Append( menuFile, "&File" ); + menuBar->Append( menuDebug, "&Debug" ); menuBar->Append( menuWindow, "&Window" ); menuBar->Append( menuHelp, "&Help" ); SetMenuBar( menuBar ); CreateStatusBar(); - wxLogStatus(this, "Searching for SCSI2SD"); { wxPanel* cfgPanel = new wxPanel(this); @@ -208,16 +216,19 @@ public: //Fit(); // Needed to reduce window size on Windows FitInside(); // Needed on Linux to prevent status bar overlap - myTimer = new wxTimer(this, ID_Timer); - myTimer->Start(1000); //ms - myLogWindow = new wxLogWindow(this, wxT("scsi2sd-util debug log"), true); + myLogWindow->PassMessages(false); // Prevent messagebox popups + + myTimer = new wxTimer(this, ID_Timer); + myTimer->Start(16); //ms, suitable for scsi debug logging } + private: wxLogWindow* myLogWindow; std::vector myTargets; wxButton* myLoadButton; wxButton* mySaveButton; + wxMenuItem* mySCSILogChk; wxTimer* myTimer; shared_ptr myHID; shared_ptr myBootloader; @@ -225,6 +236,16 @@ private: uint8_t myTickCounter; + time_t myLastPollTime; + + void mmLogStatus(const std::string& msg) + { + // We set PassMessages to false on our log window to prevent popups, but + // this also prevents wxLogStatus from updating the status bar. + SetStatusText(msg); + wxLogMessage(this, "%s", msg.c_str()); + } + void onConfigChanged(wxCommandEvent& event) { evaluate(); @@ -307,7 +328,8 @@ private: ID_Notebook, ID_BtnLoad, ID_BtnSave, - ID_LogWindow + ID_LogWindow, + ID_SCSILog }; void OnID_ConfigDefaults(wxCommandEvent& event) @@ -350,7 +372,7 @@ private: this, wxPD_AUTO_HIDE | wxPD_CAN_ABORT) ); - wxLogStatus(this, "Searching for bootloader"); + mmLogStatus("Searching for bootloader"); while (true) { try @@ -358,7 +380,7 @@ private: if (!myHID) myHID.reset(HID::Open()); if (myHID) { - wxLogStatus(this, "Resetting SCSI2SD into bootloader"); + mmLogStatus("Resetting SCSI2SD into bootloader"); myHID->enterBootloader(); myHID.reset(); @@ -370,7 +392,7 @@ private: myBootloader.reset(Bootloader::Open()); if (myBootloader) { - wxLogStatus(this, "Bootloader found"); + mmLogStatus("Bootloader found"); break; } } @@ -380,19 +402,19 @@ private: // Verify the USB HID connection is valid if (!myBootloader->ping()) { - wxLogStatus(this, "Bootloader ping failed"); + mmLogStatus("Bootloader ping failed"); myBootloader.reset(); } else { - wxLogStatus(this, "Bootloader found"); + mmLogStatus("Bootloader found"); break; } } } catch (std::exception& e) { - wxLogStatus(this, "%s", e.what()); + mmLogStatus(e.what()); myHID.reset(); myBootloader.reset(); } @@ -414,19 +436,19 @@ private: { if (myBootloader->isCorrectFirmware((*it)->getPath())) { - wxLogStatus(this, - "Found firmware entry %s within archive %s", - (*it)->getPath(), - filename); + std::stringstream msg; + msg << "Found firmware entry " << (*it)->getPath() << + " within archive " << filename; + mmLogStatus(msg.str()); tmpFile = wxFileName::CreateTempFileName( wxT("SCSI2SD_Firmware"), static_cast(NULL) ); zipper::FileWriter out(tmpFile); (*it)->decompress(out); - wxLogStatus(this, - "Firmware extracted to %s", - tmpFile); + msg.clear(); + msg << "Firmware extracted to " << tmpFile; + mmLogStatus(msg.str()); break; } } @@ -446,7 +468,7 @@ private: } catch (std::exception& e) { - wxLogStatus(this, "%s", e.what()); + mmLogStatus(e.what()); std::stringstream msg; msg << "Could not open firmware file: " << e.what(); wxMessageBox( @@ -469,7 +491,9 @@ private: TheProgressWrapper.setProgressDialog(progress, totalFlashRows); } - wxLogStatus(this, "Upgrading firmware from file: %s", tmpFile); + std::stringstream msg; + msg << "Upgrading firmware from file: " << tmpFile; + mmLogStatus(msg.str()); try { @@ -480,7 +504,7 @@ private: "Firmware update successful", "Firmware OK", wxOK); - wxLogStatus(this, "Firmware update successful"); + mmLogStatus("Firmware update successful"); myHID.reset(); @@ -489,7 +513,7 @@ private: catch (std::exception& e) { TheProgressWrapper.clearProgressDialog(); - wxLogStatus(this, "%s", e.what()); + mmLogStatus(e.what()); myHID.reset(); myBootloader.reset(); @@ -502,8 +526,42 @@ private: } } + void logSCSI() + { + if (!mySCSILogChk->IsChecked() || + !myHID) + { + return; + } + try + { + std::vector info(HID::HID_PACKET_SIZE); + if (myHID->readSCSIDebugInfo(info)) + { + std::stringstream msg; + msg << std::hex; + for (size_t i = 0; i < 32 && i < info.size(); ++i) + { + msg << std::setfill('0') << std::setw(2) << + static_cast(info[i]) << ' '; + } + wxLogMessage(this, msg.str().c_str()); + } + } + catch (std::exception& e) + { + wxLogWarning(this, e.what()); + myHID.reset(); + } + } + void OnID_Timer(wxTimerEvent& event) { + logSCSI(); + time_t now = time(NULL); + if (now == myLastPollTime) return; + myLastPollTime = now; + // Check if we are connected to the HID device. // AND/or bootloader device. try @@ -523,7 +581,7 @@ private: if (myBootloader) { - wxLogStatus(this, "%s", "SCSI2SD Bootloader Ready"); + mmLogStatus("SCSI2SD Bootloader Ready"); } } @@ -551,24 +609,49 @@ private: if (!supressLog) { // Oh dear, old firmware - wxLogStatus( - this, - "Firmware update required. Version %s", - myHID->getFirmwareVersionStr()); + std::stringstream msg; + msg << "Firmware update required. Version " << + myHID->getFirmwareVersionStr(); + mmLogStatus(msg.str()); } } else { - wxLogStatus( - this, - "SCSI2SD Ready, firmware version %s", - myHID->getFirmwareVersionStr()); + std::stringstream msg; + msg << "SCSI2SD Ready, firmware version " << + myHID->getFirmwareVersionStr(); + mmLogStatus(msg.str()); + + std::vector csd(myHID->getSD_CSD()); + std::vector cid(myHID->getSD_CID()); + std::stringstream sdinfo; + sdinfo << "SD Capacity (512-byte sectors): " << + myHID->getSDCapacity() << std::endl; + + sdinfo << "SD CSD Register: "; + for (size_t i = 0; i < csd.size(); ++i) + { + sdinfo << + std::hex << std::setfill('0') << std::setw(2) << + static_cast(csd[i]); + } + sdinfo << std::endl; + sdinfo << "SD CID Register: "; + for (size_t i = 0; i < cid.size(); ++i) + { + sdinfo << + std::hex << std::setfill('0') << std::setw(2) << + static_cast(cid[i]); + } + + wxLogMessage(this, "%s", sdinfo.str()); if (!myInitialConfig) { wxCommandEvent loadEvent(wxEVT_NULL, ID_BtnLoad); GetEventHandler()->AddPendingEvent(loadEvent); } + } } else @@ -583,7 +666,8 @@ private: } catch (std::runtime_error& e) { - wxLogStatus(this, "%s", e.what()); + std::cerr << e.what() << std::endl; + mmLogStatus(e.what()); } evaluate(); @@ -594,7 +678,7 @@ private: TimerLock lock(myTimer); if (!myHID) return; - wxLogStatus(this, "Loading configuration"); + mmLogStatus("Loading configuration"); wxWindowPtr progress( new wxGenericProgressDialog( @@ -619,7 +703,7 @@ private: std::stringstream ss; ss << "Reading flash array " << SCSI_CONFIG_ARRAY << " row " << (flashRow + j); - wxLogStatus(this, "%s", ss.str()); + mmLogStatus(ss.str()); currentProgress += 1; if (!progress->Update( (100 * currentProgress) / totalProgress, @@ -640,7 +724,7 @@ private: } catch (std::runtime_error& e) { - wxLogStatus(this, "%s", e.what()); + mmLogStatus(e.what()); goto err; } @@ -653,7 +737,7 @@ private: } myInitialConfig = true; - wxLogStatus(this, "%s", "Load Complete"); + mmLogStatus("Load Complete"); while (progress->Update(100, "Load Complete")) { // Wait for the user to click "Close" @@ -662,7 +746,7 @@ private: goto out; err: - wxLogStatus(this, "%s", "Load failed"); + mmLogStatus("Load failed"); while (progress->Update(100, "Load failed")) { // Wait for the user to click "Close" @@ -671,7 +755,7 @@ private: goto out; abort: - wxLogStatus(this, "Load Aborted"); + mmLogStatus("Load Aborted"); out: return; @@ -682,7 +766,7 @@ private: TimerLock lock(myTimer); if (!myHID) return; - wxLogStatus(this, "Saving configuration"); + mmLogStatus("Saving configuration"); wxWindowPtr progress( new wxGenericProgressDialog( @@ -708,7 +792,7 @@ private: std::stringstream ss; ss << "Programming flash array " << SCSI_CONFIG_ARRAY << " row " << (flashRow + j); - wxLogStatus(this, "%s", ss.str()); + mmLogStatus(ss.str()); currentProgress += 1; if (!progress->Update( (100 * currentProgress) / totalProgress, @@ -731,7 +815,7 @@ private: } catch (std::runtime_error& e) { - wxLogStatus(this, "%s", e.what()); + mmLogStatus(e.what()); goto err; } } @@ -741,7 +825,7 @@ private: myHID->enterBootloader(); myHID.reset(); - wxLogStatus(this, "Save Complete"); + mmLogStatus("Save Complete"); while (progress->Update(100, "Save Complete")) { // Wait for the user to click "Close" @@ -750,7 +834,7 @@ private: goto out; err: - wxLogStatus(this, "Save failed"); + mmLogStatus("Save failed"); while (progress->Update(100, "Save failed")) { // Wait for the user to click "Close" @@ -759,10 +843,10 @@ private: goto out; abort: - wxLogStatus(this, "Save Aborted"); + mmLogStatus("Save Aborted"); out: - (void) true; // empty statement. + return; } void OnExit(wxCommandEvent& event)