From 8dd68a081172b7a69b62ba91e8797ad423842542 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Wed, 29 Mar 2023 17:05:11 +0200 Subject: [PATCH 01/11] added copy of hackrf usb stack --- firmware/application/CMakeLists.txt | 1 + firmware/application/apps/ui_sd_over_usb.cpp | 49 +++ firmware/application/apps/ui_sd_over_usb.hpp | 63 ++++ firmware/application/ui_navigation.cpp | 5 +- firmware/baseband/CMakeLists.txt | 25 ++ .../baseband/sd_over_usb/proc_sd_over_usb.cpp | 49 +++ .../baseband/sd_over_usb/proc_sd_over_usb.hpp | 48 +++ firmware/baseband/sd_over_usb/sd_over_usb.c | 77 +++++ firmware/baseband/sd_over_usb/sd_over_usb.h | 39 +++ .../baseband/sd_over_usb/usb_bulk_buffer.h | 39 +++ .../baseband/sd_over_usb/usb_descriptor.c | 314 ++++++++++++++++++ .../baseband/sd_over_usb/usb_descriptor.h | 42 +++ firmware/baseband/sd_over_usb/usb_device.c | 56 ++++ firmware/baseband/sd_over_usb/usb_device.h | 31 ++ firmware/baseband/sd_over_usb/usb_endpoint.c | 70 ++++ firmware/baseband/sd_over_usb/usb_endpoint.h | 42 +++ firmware/common/spi_image.hpp | 1 + 17 files changed, 949 insertions(+), 2 deletions(-) create mode 100644 firmware/application/apps/ui_sd_over_usb.cpp create mode 100644 firmware/application/apps/ui_sd_over_usb.hpp create mode 100644 firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp create mode 100644 firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp create mode 100644 firmware/baseband/sd_over_usb/sd_over_usb.c create mode 100644 firmware/baseband/sd_over_usb/sd_over_usb.h create mode 100644 firmware/baseband/sd_over_usb/usb_bulk_buffer.h create mode 100644 firmware/baseband/sd_over_usb/usb_descriptor.c create mode 100644 firmware/baseband/sd_over_usb/usb_descriptor.h create mode 100644 firmware/baseband/sd_over_usb/usb_device.c create mode 100644 firmware/baseband/sd_over_usb/usb_device.h create mode 100644 firmware/baseband/sd_over_usb/usb_endpoint.c create mode 100644 firmware/baseband/sd_over_usb/usb_endpoint.h diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 723e2f6e0..9e03d7376 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -235,6 +235,7 @@ set(CPPSRC apps/ui_encoders.cpp apps/ui_fileman.cpp apps/ui_flash_utility.cpp + apps/ui_sd_over_usb.cpp apps/ui_freqman.cpp apps/ui_jammer.cpp apps/ui_keyfob.cpp diff --git a/firmware/application/apps/ui_sd_over_usb.cpp b/firmware/application/apps/ui_sd_over_usb.cpp new file mode 100644 index 000000000..87d195bad --- /dev/null +++ b/firmware/application/apps/ui_sd_over_usb.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ui_sd_over_usb.hpp" +#include "portapack_shared_memory.hpp" + +namespace ui { + +SdOverUsbView::SdOverUsbView(NavigationView& nav) : nav_ (nav) { + baseband::run_image(portapack::spi_flash::image_tag_usb_sd); + add_children({ + &labels, + &button_close + }); + + button_close.on_select = [this](Button&) { + nav_.pop(); + }; + +} + +SdOverUsbView::~SdOverUsbView() { + baseband::shutdown(); +} + +void SdOverUsbView::focus() { + button_close.focus(); +} + +} /* namespace ui */ diff --git a/firmware/application/apps/ui_sd_over_usb.hpp b/firmware/application/apps/ui_sd_over_usb.hpp new file mode 100644 index 000000000..ff8fc89dc --- /dev/null +++ b/firmware/application/apps/ui_sd_over_usb.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __UI_SD_OVER_USB_H__ +#define __UI_SD_OVER_USB_H__ + +#include "ui_widget.hpp" +#include "ui_navigation.hpp" +#include "string_format.hpp" +#include "ff.h" +#include "baseband_api.hpp" +#include "core_control.hpp" + +#include + +namespace ui { + +class SdOverUsbView : public View { +public: + SdOverUsbView(NavigationView& nav); + ~SdOverUsbView(); + + void focus() override; + + std::string title() const override { return "Flash Utility"; }; + +private: + NavigationView& nav_; + + Labels labels { + { { 4, 4 }, "Use USB", Color::white() } + }; + + Button button_close { + { 2 * 8, 15 * 16, 12 * 8, 3 * 16 }, + "Close" + }; + + +}; + +} /* namespace ui */ + +#endif /*__UI_SD_OVER_USB_H__*/ diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index c85417d5f..37c6d5cf7 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -71,6 +71,7 @@ #include "ui_view_wav.hpp" #include "ui_whipcalc.hpp" #include "ui_flash_utility.hpp" +#include "ui_sd_over_usb.hpp" //#include "acars_app.hpp" #include "ais_app.hpp" @@ -614,8 +615,8 @@ UtilitiesMenuView::UtilitiesMenuView(NavigationView& nav) { { "Antenna length", ui::Color::green(), &bitmap_icon_tools_antenna, [&nav](){ nav.push(); } }, { "Wipe SD card", ui::Color::red(), &bitmap_icon_tools_wipesd, [&nav](){ nav.push(); } }, - { "Flash Utility", ui::Color::red(), &bitmap_icon_temperature, [&nav](){ nav.push(); } }, - + { "Flash Utility", ui::Color::red(), &bitmap_icon_temperature, [&nav](){ nav.push(); } }, + { "SD over USB", ui::Color::yellow(), &bitmap_icon_hackrf, [&nav](){ nav.push(); } }, }); set_max_rows(2); // allow wider buttons } diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 76065cdd4..8c8a61275 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -515,6 +515,31 @@ set(MODE_CPPSRC ) DeclareTargets(PFUT flash_utility) +### SD over USB ${PATH_HACKRF_FIRMWARE} + +set(MODE_INCDIR + ${HACKRF_PATH}/firmware + ${HACKRF_PATH}/firmware/common + ${HACKRF_PATH}/firmware/libopencm3/include +) +set(MODE_CPPSRC + sd_over_usb/proc_sd_over_usb.cpp + + sd_over_usb/sd_over_usb.c + sd_over_usb/usb_descriptor.c + sd_over_usb/usb_device.c + sd_over_usb/usb_endpoint.c + + ${HACKRF_PATH}/firmware/common/usb.c + ${HACKRF_PATH}/firmware/common/usb_queue.c + ${HACKRF_PATH}/firmware/common/usb_request.c + ${HACKRF_PATH}/firmware/common/usb_standard_request.c + ${HACKRF_PATH}/firmware/libopencm3/lib/cm3/nvic.c + ${HACKRF_PATH}/firmware/libopencm3/lib/cm3/sync.c + +) +DeclareTargets(PUSB sd_over_usb) + ### HackRF "factory" firmware add_custom_command( diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp new file mode 100644 index 000000000..075833268 --- /dev/null +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "ch.h" +#include "hal.h" + +#include "proc_sd_over_usb.hpp" + +#include "debug.hpp" +#include "portapack_shared_memory.hpp" +#include "event_m4.hpp" + +extern "C" { +void start_usb(void); +void stop_usb(void); +void irq_usb(void); + +CH_IRQ_HANDLER(Vector60) { + irq_usb(); +} +} + +int main() { + EventDispatcher event_dispatcher { std::make_unique() }; + HALT_UNTIL_DEBUGGING(); + start_usb(); + event_dispatcher.run(); + stop_usb(); + return 0; +} diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp new file mode 100644 index 000000000..5aba4227d --- /dev/null +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __UI_PROC_SD_OVER_USB_H__ +#define __UI_PROC_SD_OVER_USB_H__ + +#include "portapack_shared_memory.hpp" +#include "baseband_processor.hpp" +#include "baseband_thread.hpp" + + +class USBProcessor : public BasebandProcessor { +public: + void execute(const buffer_c8_t&) override {}; + + //void on_message(const Message* const p) override; + +private: + + + //bool configured { false }; + + //BasebandThread baseband_thread { 3072000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; + + + //RequestSignalMessage sig_message { RequestSignalMessage::Signal::FillRequest }; +}; + +#endif /*__UI_PROC_SD_OVER_USB_H__*/ diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.c b/firmware/baseband/sd_over_usb/sd_over_usb.c new file mode 100644 index 000000000..12a43c8fe --- /dev/null +++ b/firmware/baseband/sd_over_usb/sd_over_usb.c @@ -0,0 +1,77 @@ +#include "sd_over_usb.h" + +//extern usb_request_handlers_t usb_request_handlers; + + +usb_request_status_t dummy( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + (void)(endpoint); + (void)(stage); + return USB_REQUEST_STATUS_OK; +} + +static usb_request_handler_fn vendor_request_handler[] = { + NULL, + dummy // USB_WCID_VENDOR_REQ +}; + +static const uint32_t vendor_request_handler_count = + sizeof(vendor_request_handler) / sizeof(vendor_request_handler[0]); + +usb_request_status_t usb_vendor_request( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + usb_request_status_t status = USB_REQUEST_STATUS_STALL; + + if (endpoint->setup.request < vendor_request_handler_count) { + usb_request_handler_fn handler = + vendor_request_handler[endpoint->setup.request]; + if (handler) { + status = handler(endpoint, stage); + } + } + + return status; +} + +const usb_request_handlers_t usb_request_handlers = { + .standard = usb_standard_request, + .class = 0, + .vendor = usb_vendor_request, + .reserved = 0, +}; + + + +void start_usb(void) { + usb_peripheral_reset(); + + usb_device_init(0, &usb_device); + + usb_queue_init(&usb_endpoint_control_out_queue); + usb_queue_init(&usb_endpoint_control_in_queue); + usb_queue_init(&usb_endpoint_bulk_out_queue); + usb_queue_init(&usb_endpoint_bulk_in_queue); + + usb_endpoint_init(&usb_endpoint_control_out); + usb_endpoint_init(&usb_endpoint_control_in); + + nvic_set_priority(NVIC_USB0_IRQ, 255); + + usb_run(&usb_device); + + +} + + +void stop_usb(void) { + usb_peripheral_reset(); + +} + +void irq_usb(void) { + usb0_isr(); +} diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.h b/firmware/baseband/sd_over_usb/sd_over_usb.h new file mode 100644 index 000000000..d953e9072 --- /dev/null +++ b/firmware/baseband/sd_over_usb/sd_over_usb.h @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Bernd Herzog + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __USB_SD_OVER_USB_H__ +#define __USB_SD_OVER_USB_H__ + + +#include +#include +#include +#include +#include "usb_device.h" +#include "usb_endpoint.h" +#include + +void start_usb(void); +void stop_usb(void); + + + +#endif /* __USB_SD_OVER_USB_H__ */ \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/usb_bulk_buffer.h b/firmware/baseband/sd_over_usb/usb_bulk_buffer.h new file mode 100644 index 000000000..3e2841432 --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb_bulk_buffer.h @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __USB_BULK_BUFFER_H__ +#define __USB_BULK_BUFFER_H__ + +#include +#include + +#define USB_BULK_BUFFER_SIZE 0x8000 +#define USB_BULK_BUFFER_MASK 0x7FFF + +/* Address of usb_bulk_buffer is set in ldscripts. If you change the name of this + * variable, it won't be where it needs to be in the processor's address space, + * unless you also adjust the ldscripts. + */ +extern uint8_t usb_bulk_buffer[USB_BULK_BUFFER_SIZE]; + +#endif /*__USB_BULK_BUFFER_H__*/ diff --git a/firmware/baseband/sd_over_usb/usb_descriptor.c b/firmware/baseband/sd_over_usb/usb_descriptor.c new file mode 100644 index 000000000..ecf094d9d --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb_descriptor.c @@ -0,0 +1,314 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Jared Boone + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include + +#include "usb_type.h" +#include "usb_descriptor.h" + +#define USB_VENDOR_ID (0x1D50) + +#ifdef HACKRF_ONE + #define USB_PRODUCT_ID (0x6089) +#elif JAWBREAKER + #define USB_PRODUCT_ID (0x604B) +#elif RAD1O + #define USB_PRODUCT_ID (0xCC15) +#else + #define USB_PRODUCT_ID (0xFFFF) +#endif + +#define USB_API_VERSION (0x0107) + +#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF) + +#define USB_MAX_PACKET0 (64) +#define USB_MAX_PACKET_BULK_FS (64) +#define USB_MAX_PACKET_BULK_HS (512) + +#define USB_BULK_IN_EP_ADDR (0x81) +#define USB_BULK_OUT_EP_ADDR (0x02) + +#define USB_STRING_LANGID (0x0409) + +uint8_t usb_descriptor_device[] = { + 18, // bLength + USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType + USB_WORD(0x0200), // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + USB_MAX_PACKET0, // bMaxPacketSize0 + USB_WORD(USB_VENDOR_ID), // idVendor + USB_WORD(USB_PRODUCT_ID), // idProduct + USB_WORD(USB_API_VERSION), // bcdDevice + 0x01, // iManufacturer + 0x02, // iProduct + 0x04, // iSerialNumber + 0x01 // bNumConfigurations +}; + +uint8_t usb_descriptor_device_qualifier[] = { + 10, // bLength + USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType + USB_WORD(0x0200), // bcdUSB + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + 64, // bMaxPacketSize0 + 0x01, // bNumOtherSpeedConfigurations + 0x00 // bReserved +}; + +uint8_t usb_descriptor_configuration_full_speed[] = { + 9, // bLength + USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType + USB_WORD(32), // wTotalLength + 0x01, // bNumInterfaces + 0x01, // bConfigurationValue + 0x03, // iConfiguration + 0x80, // bmAttributes: USB-powered + 250, // bMaxPower: 500mA + + 9, // bLength + USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + 0xFF, // bInterfaceClass: vendor-specific + 0xFF, // bInterfaceSubClass + 0xFF, // bInterfaceProtocol: vendor-specific + 0x00, // iInterface + + 7, // bLength + USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType + USB_BULK_IN_EP_ADDR, // bEndpointAddress + 0x02, // bmAttributes: BULK + USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize + 0x00, // bInterval: no NAK + + 7, // bLength + USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType + USB_BULK_OUT_EP_ADDR, // bEndpointAddress + 0x02, // bmAttributes: BULK + USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize + 0x00, // bInterval: no NAK + + 0, // TERMINATOR +}; + +uint8_t usb_descriptor_configuration_high_speed[] = { + 9, // bLength + USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType + USB_WORD(32), // wTotalLength + 0x01, // bNumInterfaces + 0x01, // bConfigurationValue + 0x03, // iConfiguration + 0x80, // bmAttributes: USB-powered + 250, // bMaxPower: 500mA + + 9, // bLength + USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + 0xFF, // bInterfaceClass: vendor-specific + 0xFF, // bInterfaceSubClass + 0xFF, // bInterfaceProtocol: vendor-specific + 0x00, // iInterface + + 7, // bLength + USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType + USB_BULK_IN_EP_ADDR, // bEndpointAddress + 0x02, // bmAttributes: BULK + USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize + 0x00, // bInterval: no NAK + + 7, // bLength + USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType + USB_BULK_OUT_EP_ADDR, // bEndpointAddress + 0x02, // bmAttributes: BULK + USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize + 0x00, // bInterval: no NAK + + 0, // TERMINATOR +}; + +uint8_t usb_descriptor_string_languages[] = { + 0x04, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + USB_WORD(USB_STRING_LANGID), // wLANGID +}; + +// clang-format off +uint8_t usb_descriptor_string_manufacturer[] = { + 40, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'G', 0x00, + 'r', 0x00, + 'e', 0x00, + 'a', 0x00, + 't', 0x00, + ' ', 0x00, + 'S', 0x00, + 'c', 0x00, + 'o', 0x00, + 't', 0x00, + 't', 0x00, + ' ', 0x00, + 'G', 0x00, + 'a', 0x00, + 'd', 0x00, + 'g', 0x00, + 'e', 0x00, + 't', 0x00, + 's', 0x00, +}; + +uint8_t usb_descriptor_string_product[] = { +#ifdef HACKRF_ONE + 22, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'H', 0x00, + 'a', 0x00, + 'c', 0x00, + 'k', 0x00, + 'R', 0x00, + 'F', 0x00, + ' ', 0x00, + 'O', 0x00, + 'n', 0x00, + 'e', 0x00, +#elif JAWBREAKER + 36, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'H', 0x00, + 'a', 0x00, + 'c', 0x00, + 'k', 0x00, + 'R', 0x00, + 'F', 0x00, + ' ', 0x00, + 'J', 0x00, + 'a', 0x00, + 'w', 0x00, + 'b', 0x00, + 'r', 0x00, + 'e', 0x00, + 'a', 0x00, + 'k', 0x00, + 'e', 0x00, + 'r', 0x00, +#elif RAD1O + 12, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'r', 0x00, + 'a', 0x00, + 'd', 0x00, + '1', 0x00, + 'o', 0x00, +#else + 14, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'H', 0x00, + 'a', 0x00, + 'c', 0x00, + 'k', 0x00, + 'R', 0x00, + 'F', 0x00, +#endif +}; + +uint8_t usb_descriptor_string_config_description[] = { + 24, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'T', 0x00, + 'r', 0x00, + 'a', 0x00, + 'n', 0x00, + 's', 0x00, + 'c', 0x00, + 'e', 0x00, + 'i', 0x00, + 'v', 0x00, + 'e', 0x00, + 'r', 0x00, +}; + +#ifdef DFU_MODE +uint8_t usb_descriptor_string_serial_number[] = { + 30, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'R', 0x00, + 'u', 0x00, + 'n', 0x00, + 'n', 0x00, + 'i', 0x00, + 'n', 0x00, + 'g', 0x00, + 'F', 0x00, + 'r', 0x00, + 'o', 0x00, + 'm', 0x00, + 'R', 0x00, + 'A', 0x00, + 'M', 0x00, +}; +#else +uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN]; +#endif + +uint8_t* usb_descriptor_strings[] = { + usb_descriptor_string_languages, + usb_descriptor_string_manufacturer, + usb_descriptor_string_product, + usb_descriptor_string_config_description, + usb_descriptor_string_serial_number, + 0, // TERMINATOR +}; + +uint8_t wcid_string_descriptor[] = { + 18, // bLength + USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType + 'M', 0x00, + 'S', 0x00, + 'F', 0x00, + 'T', 0x00, + '1', 0x00, + '0', 0x00, + '0', 0x00, + USB_WCID_VENDOR_REQ, // vendor request code for further descriptor + 0x00 +}; + +uint8_t wcid_feature_descriptor[] = { + 0x28, 0x00, 0x00, 0x00, // bLength + USB_WORD(0x0100), // WCID version + USB_WORD(0x0004), // WICD descriptor index + 0x01, // bNumSections + 0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Reserved + 0x00, // bInterfaceNumber + 0x01, // Reserved + 'W', 'I', 'N', 'U', 'S', 'B', 0x00,0x00, // Compatible ID, padded with zeros + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Sub-compatible ID + 0x00,0x00,0x00,0x00,0x00,0x00 // Reserved +}; diff --git a/firmware/baseband/sd_over_usb/usb_descriptor.h b/firmware/baseband/sd_over_usb/usb_descriptor.h new file mode 100644 index 000000000..2c2990e01 --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb_descriptor.h @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Jared Boone + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include + +extern uint8_t usb_descriptor_device[]; +extern uint8_t usb_descriptor_device_qualifier[]; +extern uint8_t usb_descriptor_configuration_full_speed[]; +extern uint8_t usb_descriptor_configuration_high_speed[]; +extern uint8_t usb_descriptor_string_languages[]; +extern uint8_t usb_descriptor_string_manufacturer[]; +extern uint8_t usb_descriptor_string_product[]; + +#define USB_DESCRIPTOR_STRING_SERIAL_LEN 32 +#define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN \ + (USB_DESCRIPTOR_STRING_SERIAL_LEN * 2 + 2) /* UTF-16LE */ +extern uint8_t usb_descriptor_string_serial_number[]; + +extern uint8_t* usb_descriptor_strings[]; + +#define USB_WCID_VENDOR_REQ 0x19 +extern uint8_t wcid_string_descriptor[]; +extern uint8_t wcid_feature_descriptor[]; diff --git a/firmware/baseband/sd_over_usb/usb_device.c b/firmware/baseband/sd_over_usb/usb_device.c new file mode 100644 index 000000000..b689ce9fe --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb_device.c @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "usb_device.h" + +#include + +#include "usb_descriptor.h" + +usb_configuration_t usb_configuration_high_speed = { + .number = 1, + .speed = USB_SPEED_HIGH, + .descriptor = usb_descriptor_configuration_high_speed, +}; + +usb_configuration_t usb_configuration_full_speed = { + .number = 1, + .speed = USB_SPEED_FULL, + .descriptor = usb_descriptor_configuration_full_speed, +}; + +usb_configuration_t* usb_configurations[] = { + &usb_configuration_high_speed, + &usb_configuration_full_speed, + 0, +}; + +usb_device_t usb_device = { + .descriptor = usb_descriptor_device, + .descriptor_strings = usb_descriptor_strings, + .qualifier_descriptor = usb_descriptor_device_qualifier, + .configurations = &usb_configurations, + .configuration = 0, + .wcid_string_descriptor = wcid_string_descriptor, + .wcid_feature_descriptor = wcid_feature_descriptor, +}; diff --git a/firmware/baseband/sd_over_usb/usb_device.h b/firmware/baseband/sd_over_usb/usb_device.h new file mode 100644 index 000000000..05008dca1 --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb_device.h @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2013 Great Scott Gadgets + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __USB_DEVICE_H__ +#define __USB_DEVICE_H__ + +#include + +extern usb_device_t usb_device; + +#endif /* end of include guard: __USB_DEVICE_H__ */ diff --git a/firmware/baseband/sd_over_usb/usb_endpoint.c b/firmware/baseband/sd_over_usb/usb_endpoint.c new file mode 100644 index 000000000..028327087 --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb_endpoint.c @@ -0,0 +1,70 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "usb_endpoint.h" + +#include + +#include "usb_device.h" + +usb_endpoint_t usb_endpoint_control_out = { + .address = 0x00, + .device = &usb_device, + .in = &usb_endpoint_control_in, + .out = &usb_endpoint_control_out, + .setup_complete = usb_setup_complete, + .transfer_complete = usb_control_out_complete, +}; +USB_DEFINE_QUEUE(usb_endpoint_control_out, 4); + +usb_endpoint_t usb_endpoint_control_in = { + .address = 0x80, + .device = &usb_device, + .in = &usb_endpoint_control_in, + .out = &usb_endpoint_control_out, + .setup_complete = 0, + .transfer_complete = usb_control_in_complete, +}; +static USB_DEFINE_QUEUE(usb_endpoint_control_in, 4); + +// NOTE: Endpoint number for IN and OUT are different. I wish I had some +// evidence that having BULK IN and OUT on separate endpoint numbers was +// actually a good idea. Seems like everybody does it that way, but why? + +usb_endpoint_t usb_endpoint_bulk_in = { + .address = 0x81, + .device = &usb_device, + .in = &usb_endpoint_bulk_in, + .out = 0, + .setup_complete = 0, + .transfer_complete = usb_queue_transfer_complete}; +static USB_DEFINE_QUEUE(usb_endpoint_bulk_in, 1); + +usb_endpoint_t usb_endpoint_bulk_out = { + .address = 0x02, + .device = &usb_device, + .in = 0, + .out = &usb_endpoint_bulk_out, + .setup_complete = 0, + .transfer_complete = usb_queue_transfer_complete}; +static USB_DEFINE_QUEUE(usb_endpoint_bulk_out, 1); diff --git a/firmware/baseband/sd_over_usb/usb_endpoint.h b/firmware/baseband/sd_over_usb/usb_endpoint.h new file mode 100644 index 000000000..7a594cd5a --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb_endpoint.h @@ -0,0 +1,42 @@ +/* + * Copyright 2012-2013 Great Scott Gadgets + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __USB_ENDPOINT_H__ +#define __USB_ENDPOINT_H__ + +#include +#include + +extern usb_endpoint_t usb_endpoint_control_out; +extern USB_DECLARE_QUEUE(usb_endpoint_control_out); + +extern usb_endpoint_t usb_endpoint_control_in; +extern USB_DECLARE_QUEUE(usb_endpoint_control_in); + +extern usb_endpoint_t usb_endpoint_bulk_in; +extern USB_DECLARE_QUEUE(usb_endpoint_bulk_in); + +extern usb_endpoint_t usb_endpoint_bulk_out; +extern USB_DECLARE_QUEUE(usb_endpoint_bulk_out); + +#endif /* end of include guard: __USB_ENDPOINT_H__ */ diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index 709807fb6..89679284f 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -107,6 +107,7 @@ constexpr image_tag_t image_tag_siggen { 'P', 'S', 'I', 'G' }; constexpr image_tag_t image_tag_sstv_tx { 'P', 'S', 'T', 'X' }; constexpr image_tag_t image_tag_tones { 'P', 'T', 'O', 'N' }; constexpr image_tag_t image_tag_flash_utility { 'P', 'F', 'U', 'T' }; +constexpr image_tag_t image_tag_usb_sd { 'P', 'U', 'S', 'B' }; constexpr image_tag_t image_tag_noop { 'P', 'N', 'O', 'P' }; From a6eb430830c7c2e189b133c7d06b41840e0bbd28 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Thu, 30 Mar 2023 11:46:36 +0200 Subject: [PATCH 02/11] integrated usb stack --- firmware/application/apps/ui_sd_over_usb.cpp | 12 ++++- firmware/baseband/CMakeLists.txt | 21 ++++++++ .../baseband/sd_over_usb/proc_sd_over_usb.cpp | 31 +++++++++-- firmware/baseband/sd_over_usb/sd_over_usb.c | 51 +++++++++++++++++++ firmware/baseband/sd_over_usb/sd_over_usb.h | 3 ++ .../baseband/sd_over_usb/usb_descriptor.c | 20 +++++--- 6 files changed, 128 insertions(+), 10 deletions(-) diff --git a/firmware/application/apps/ui_sd_over_usb.cpp b/firmware/application/apps/ui_sd_over_usb.cpp index 87d195bad..b8d6c9113 100644 --- a/firmware/application/apps/ui_sd_over_usb.cpp +++ b/firmware/application/apps/ui_sd_over_usb.cpp @@ -26,7 +26,17 @@ namespace ui { SdOverUsbView::SdOverUsbView(NavigationView& nav) : nav_ (nav) { - baseband::run_image(portapack::spi_flash::image_tag_usb_sd); + + sdcDisconnect(&SDCD1); + sdcStop(&SDCD1); + + portapack::shutdown(); + m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, true); + //m4_init(portapack::spi_flash::image_tag_hackrf, portapack::memory::map::m4_code_hackrf, true); + m0_halt(); /* will not return*/ + //baseband::run_image(); + + add_children({ &labels, &button_close diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 8c8a61275..cab5fe56c 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -534,8 +534,29 @@ set(MODE_CPPSRC ${HACKRF_PATH}/firmware/common/usb_queue.c ${HACKRF_PATH}/firmware/common/usb_request.c ${HACKRF_PATH}/firmware/common/usb_standard_request.c + ${HACKRF_PATH}/firmware/common/platform_detect.c + ${HACKRF_PATH}/firmware/common/hackrf_core.c + ${HACKRF_PATH}/firmware/common/gpio_lpc.c + ${HACKRF_PATH}/firmware/common/firmware_info.c + ${HACKRF_PATH}/firmware/common/si5351c.c + ${HACKRF_PATH}/firmware/common/i2c_bus.c + ${HACKRF_PATH}/firmware/common/mixer.c + ${HACKRF_PATH}/firmware/common/clkin.c + ${HACKRF_PATH}/firmware/common/spi_bus.c + ${HACKRF_PATH}/firmware/common/sgpio.c + ${HACKRF_PATH}/firmware/common/rf_path.c + ${HACKRF_PATH}/firmware/common/i2c_lpc.c + ${HACKRF_PATH}/firmware/common/spi_ssp.c + ${HACKRF_PATH}/firmware/common/rffc5071_spi.c + ${HACKRF_PATH}/firmware/common/rffc5071.c + ${HACKRF_PATH}/firmware/common/clkin.c + ${HACKRF_PATH}/firmware/common/gpdma.c + ${HACKRF_PATH}/firmware/libopencm3/lib/cm3/nvic.c ${HACKRF_PATH}/firmware/libopencm3/lib/cm3/sync.c + ${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/scu.c + ${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/timer.c + ${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/i2c.c ) DeclareTargets(PUSB sd_over_usb) diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp index 075833268..5109dc64f 100644 --- a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp @@ -40,10 +40,35 @@ CH_IRQ_HANDLER(Vector60) { } int main() { - EventDispatcher event_dispatcher { std::make_unique() }; - HALT_UNTIL_DEBUGGING(); + //EventDispatcher event_dispatcher { std::make_unique() }; + + //HALT_UNTIL_DEBUGGING(); + + //LPC_CGU->PLL0USB_CTRL.PD = 1; + //LPC_CGU->PLL0USB_CTRL.AUTOBLOCK = 1; + //LPC_CGU->PLL0USB_CTRL.CLK_SEL = 0x06; +// + //while (LPC_CGU->PLL0USB_STAT.LOCK) {} + // + //LPC_CGU->PLL0USB_MDIV = 0x06167FFA; // 0x71A7FAA; // + //LPC_CGU->PLL0USB_NP_DIV = 0x00302062; +// + ////LPC_CGU->PLL0USB_CTRL.PD |= 1; + //LPC_CGU->PLL0USB_CTRL.DIRECTI = 1; + //LPC_CGU->PLL0USB_CTRL.DIRECTO = 1; + //LPC_CGU->PLL0USB_CTRL.CLKEN = 1; +// + //LPC_CGU->PLL0USB_CTRL.PD = 0; +// + //while (!(LPC_CGU->PLL0USB_STAT.LOCK)) {} + ////chThdSleepMilliseconds(800); +// + //LPC_CGU->BASE_USB0_CLK.AUTOBLOCK = 1; + //LPC_CGU->BASE_USB0_CLK.CLK_SEL = 0x07; + start_usb(); - event_dispatcher.run(); + //event_dispatcher.run(); + while (true); stop_usb(); return 0; } diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.c b/firmware/baseband/sd_over_usb/sd_over_usb.c index 12a43c8fe..594eb7846 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.c +++ b/firmware/baseband/sd_over_usb/sd_over_usb.c @@ -45,8 +45,59 @@ const usb_request_handlers_t usb_request_handlers = { }; +void usb_configuration_changed(usb_device_t* const device) +{ + /* Reset transceiver to idle state until other commands are received */ + // request_transceiver_mode(TRANSCEIVER_MODE_OFF); + // if (device->configuration->number == 1) { + // // transceiver configuration + // led_on(LED1); + // } else { + // /* Configuration number equal 0 means usb bus reset. */ + // led_off(LED1); + // } + usb_endpoint_init(&usb_endpoint_bulk_in); + usb_endpoint_init(&usb_endpoint_bulk_out); +} + void start_usb(void) { + + /* use XTAL_OSC as clock source for PLL0USB */ + // CGU_PLL0USB_CTRL = + // CGU_PLL0USB_CTRL_PD(1) /* PLL0 power down */ | + // CGU_PLL0USB_CTRL_AUTOBLOCK(1) /* Block clock automatically during frequency change */ | + // CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL); /* Clock source selection */ + + // while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {} + + /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */ + /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */ + + // CGU_PLL0USB_MDIV = 0x06167FFA; + // CGU_PLL0USB_NP_DIV = 0x00302062; + + // CGU_PLL0USB_CTRL |= + // CGU_PLL0USB_CTRL_PD(1) /* PLL0 power down */ | + // CGU_PLL0USB_CTRL_DIRECTI(1) /* PLL0 direct input */ | + // CGU_PLL0USB_CTRL_DIRECTO(1) /* PLL0 direct output */ | + // CGU_PLL0USB_CTRL_CLKEN(1) /* PLL0 clock enable */; + + // /* power on PLL0USB and wait until stable */ + // CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK /* PLL0 power down */ ; + + // while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {} + + /* use PLL0USB as clock source for USB0 */ + // CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) | + // CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB); + + detect_hardware_platform(); + pin_setup(); + cpu_clock_init(); + + + usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); usb_device_init(0, &usb_device); diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.h b/firmware/baseband/sd_over_usb/sd_over_usb.h index d953e9072..ecdb0d4dc 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.h +++ b/firmware/baseband/sd_over_usb/sd_over_usb.h @@ -30,6 +30,9 @@ #include "usb_device.h" #include "usb_endpoint.h" #include +#include +#include "platform_detect.h" +#include "hackrf_core.h" void start_usb(void); void stop_usb(void); diff --git a/firmware/baseband/sd_over_usb/usb_descriptor.c b/firmware/baseband/sd_over_usb/usb_descriptor.c index ecf094d9d..7f5adc474 100644 --- a/firmware/baseband/sd_over_usb/usb_descriptor.c +++ b/firmware/baseband/sd_over_usb/usb_descriptor.c @@ -186,18 +186,26 @@ uint8_t usb_descriptor_string_manufacturer[] = { uint8_t usb_descriptor_string_product[] = { #ifdef HACKRF_ONE - 22, // bLength + 43, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType - 'H', 0x00, + 'P', 0x00, + 'o', 0x00, + 'r', 0x00, + 't', 0x00, + 'a', 0x00, + 'P', 0x00, 'a', 0x00, 'c', 0x00, 'k', 0x00, - 'R', 0x00, - 'F', 0x00, ' ', 0x00, - 'O', 0x00, - 'n', 0x00, + + 'M', 0x00, + 'a', 0x00, + 'y', 0x00, + 'h', 0x00, 'e', 0x00, + 'm', 0x00, + #elif JAWBREAKER 36, // bLength USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType From 776ac652a80e025ffe5335732bf82950e7629536 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Fri, 31 Mar 2023 19:18:39 +0200 Subject: [PATCH 03/11] implemented scsi inquiry --- firmware/baseband/CMakeLists.txt | 3 +- .../baseband/sd_over_usb/proc_sd_over_usb.cpp | 5 +- firmware/baseband/sd_over_usb/scsi.c | 170 +++++ firmware/baseband/sd_over_usb/scsi.h | 46 ++ firmware/baseband/sd_over_usb/sd_over_usb.c | 222 ++++-- firmware/baseband/sd_over_usb/sd_over_usb.h | 5 +- firmware/baseband/sd_over_usb/usb.c | 676 ++++++++++++++++++ .../baseband/sd_over_usb/usb_descriptor.c | 16 +- .../GCC/ARMCMx/LPC43xx_M4/ld/LPC43xx_M4.ld | 2 + 9 files changed, 1070 insertions(+), 75 deletions(-) create mode 100644 firmware/baseband/sd_over_usb/scsi.c create mode 100644 firmware/baseband/sd_over_usb/scsi.h create mode 100644 firmware/baseband/sd_over_usb/usb.c diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index cab5fe56c..2d7cbb6c2 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -525,12 +525,13 @@ set(MODE_INCDIR set(MODE_CPPSRC sd_over_usb/proc_sd_over_usb.cpp + sd_over_usb/scsi.c sd_over_usb/sd_over_usb.c sd_over_usb/usb_descriptor.c sd_over_usb/usb_device.c sd_over_usb/usb_endpoint.c + sd_over_usb/usb.c - ${HACKRF_PATH}/firmware/common/usb.c ${HACKRF_PATH}/firmware/common/usb_queue.c ${HACKRF_PATH}/firmware/common/usb_request.c ${HACKRF_PATH}/firmware/common/usb_standard_request.c diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp index 5109dc64f..9dec3bbcc 100644 --- a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp @@ -33,6 +33,7 @@ extern "C" { void start_usb(void); void stop_usb(void); void irq_usb(void); +void usb_transfer(void); CH_IRQ_HANDLER(Vector60) { irq_usb(); @@ -68,7 +69,9 @@ int main() { start_usb(); //event_dispatcher.run(); - while (true); + while (true) { + usb_transfer(); + } stop_usb(); return 0; } diff --git a/firmware/baseband/sd_over_usb/scsi.c b/firmware/baseband/sd_over_usb/scsi.c new file mode 100644 index 000000000..b4b035364 --- /dev/null +++ b/firmware/baseband/sd_over_usb/scsi.c @@ -0,0 +1,170 @@ +#include "scsi.h" + + +#define HALT_UNTIL_DEBUGGING() \ + while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \ + __asm__ __volatile__("bkpt 1") + +typedef struct { + uint8_t peripheral; + uint8_t removable; + uint8_t version; + uint8_t response_data_format; + uint8_t additional_length; + uint8_t sccstp; + uint8_t bqueetc; + uint8_t cmdque; + uint8_t vendorID[8]; + uint8_t productID[16]; + uint8_t productRev[4]; +} scsi_inquiry_response_t; + + +static const scsi_inquiry_response_t default_scsi_inquiry_response = { + 0x00, /* direct access block device */ + 0x80, /* removable */ + 0x04, /* SPC-2 */ + 0x02, /* response data format */ + 0x20, /* response has 0x20 + 4 bytes */ + 0x00, + 0x00, + 0x00, + "Mayhem", + "Mass Storage", + {'v','1','.','6'} +}; + +typedef struct { + uint32_t signature; + uint32_t tag; + uint32_t data_residue; + uint8_t status; +} __attribute__((packed)) msd_csw_t; + +#define MSD_CBW_SIGNATURE 0x43425355 +#define MSD_CSW_SIGNATURE 0x53425355 + +// void handle_inquiry_4(void* user_data, unsigned int bytes_transferred) { +// HALT_UNTIL_DEBUGGING(); +// } + +// void handle_inquiry_3(void* user_data, unsigned int bytes_transferred) +// { +// //msd_cbw_t *msd_cbw_data = (msd_cbw_t *)user_data; + +// //HALT_UNTIL_DEBUGGING(); + + +// } + + +volatile bool inquiry_stage_one_send = false; +void inquiry_cb(void* user_data, unsigned int bytes_transferred) +{ + inquiry_stage_one_send = true; + + //HALT_UNTIL_DEBUGGING(); + + //faulty + // usb_transfer_schedule_block( + // &usb_endpoint_bulk_out, + // &usb_bulk_buffer[0], + // USB_TRANSFER_SIZE, + // handle_inquiry_3, + // msd_cbw_data); + + +//does not send + +} + +void handle_inquiry(msd_cbw_t *msd_cbw_data){ + inquiry_stage_one_send = false; + memcpy(&usb_bulk_buffer[0], &default_scsi_inquiry_response, sizeof(scsi_inquiry_response_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0], + sizeof(scsi_inquiry_response_t), + inquiry_cb, + msd_cbw_data); + + while (!inquiry_stage_one_send); + + msd_csw_t csw = { + .signature = MSD_CSW_SIGNATURE, + .tag = msd_cbw_data->tag, + .data_residue = 0, + .status = 0 + }; + + memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); + // does not gets send + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0x4000], + sizeof(msd_csw_t), + NULL, //handle_inquiry_3, + NULL); //msd_cbw_data); + +} + +void scsi_command(msd_cbw_t *msd_cbw_data) { + + switch (msd_cbw_data->cmd_data[0]) { + case SCSI_CMD_INQUIRY: + handle_inquiry(msd_cbw_data); + + + break; + + default: + HALT_UNTIL_DEBUGGING(); + break; +/* + case SCSI_CMD_REQUEST_SENSE: + ret = request_sense(scsip, cmd); + break; + + case SCSI_CMD_READ_CAPACITY_10: + ret = read_capacity10(scsip, cmd); + break; + + case SCSI_CMD_READ_10: + ret = data_read_write10(scsip, cmd); + break; + + case SCSI_CMD_WRITE_10: + ret = data_read_write10(scsip, cmd); + break; + + case SCSI_CMD_TEST_UNIT_READY: + ret = test_unit_ready(scsip, cmd); + break; + + case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + ret = cmd_ignored(scsip, cmd); + break; + + case SCSI_CMD_MODE_SENSE_6: + ret = mode_sense6(scsip, cmd); + break; + + case SCSI_CMD_READ_FORMAT_CAPACITIES: + ret = read_format_capacities(scsip, cmd); + break; + + case SCSI_CMD_VERIFY_10: + ret = cmd_ignored(scsip, cmd); + break; + + default: + ret = cmd_unhandled(scsip, cmd); + break; + */ + } + +// if (ret == SCSI_SUCCESS) +// set_sense_ok(scsip); + + +} \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/scsi.h b/firmware/baseband/sd_over_usb/scsi.h new file mode 100644 index 000000000..616c9aff9 --- /dev/null +++ b/firmware/baseband/sd_over_usb/scsi.h @@ -0,0 +1,46 @@ +#ifndef __SCSI_H__ +#define __SCSI_H__ + +#include +#include +#include +#include +#include "usb_device.h" +#include "usb_endpoint.h" +#include +#include +#include "platform_detect.h" +#include "hackrf_core.h" +#include "usb_bulk_buffer.h" + +#define SCSI_CMD_TEST_UNIT_READY 0x00 +#define SCSI_CMD_REQUEST_SENSE 0x03 +#define SCSI_CMD_INQUIRY 0x12 +#define SCSI_CMD_MODE_SENSE_6 0x1A +#define SCSI_CMD_START_STOP_UNIT 0x1B +#define SCSI_CMD_SEND_DIAGNOSTIC 0x1D +#define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E +#define SCSI_CMD_READ_CAPACITY_10 0x25 +#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23 +#define SCSI_CMD_READ_10 0x28 +#define SCSI_CMD_WRITE_10 0x2A +#define SCSI_CMD_VERIFY_10 0x2F + +#define MSD_CBW_SIGNATURE 0x43425355 +#define MSD_CSW_SIGNATURE 0x53425355 + +#define USB_TRANSFER_SIZE 0x2000 + +typedef struct { + uint32_t signature; + uint32_t tag; + uint32_t data_len; + uint8_t flags; + uint8_t lun; + uint8_t cmd_len; + uint8_t cmd_data[16]; +} __attribute__((packed)) msd_cbw_t; + +void scsi_command(msd_cbw_t *msd_cbw_data); + +#endif /* __SCSI_H__ */ \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.c b/firmware/baseband/sd_over_usb/sd_over_usb.c index 594eb7846..5557d0ac7 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.c +++ b/firmware/baseband/sd_over_usb/sd_over_usb.c @@ -1,102 +1,175 @@ #include "sd_over_usb.h" +#include "scsi.h" //extern usb_request_handlers_t usb_request_handlers; +#define HALT_UNTIL_DEBUGGING() \ + while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \ + __asm__ __volatile__("bkpt 1") + +// uint8_t usb_buffer[USB_TRANSFER_SIZE]; -usb_request_status_t dummy( +bool scsi_running = false; + +usb_request_status_t report_max_lun( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { + if (stage == USB_TRANSFER_STAGE_SETUP) { + endpoint->buffer[0] = 0; + usb_transfer_schedule_block( + endpoint->in, + &endpoint->buffer, + 1, + NULL, + NULL); + + usb_transfer_schedule_ack(endpoint->out); + + /* start loop here?*/ + scsi_running = true; + // Host to Device. receive inquiry LUN + return USB_REQUEST_STATUS_OK; + } + else if (stage == USB_TRANSFER_STAGE_DATA) { + return USB_REQUEST_STATUS_OK; + } + else if (stage == USB_TRANSFER_STAGE_STATUS) { + // response here? + return USB_REQUEST_STATUS_OK; + } +} + + +usb_request_status_t report_magic_scsi( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + + // return USB_REQUEST_STATUS_OK; + + + // if (endpoint->address != 0x02) { + // HALT_UNTIL_DEBUGGING(); + // return USB_REQUEST_STATUS_OK; + // } + + if (stage == USB_TRANSFER_STAGE_SETUP) { + return USB_REQUEST_STATUS_OK; + // usb_bulk_buffer[0] = 0x55; + // usb_bulk_buffer[1] = 0x55; + // usb_bulk_buffer[2] = 0x55; + // usb_bulk_buffer[3] = 0x55; + // usb_bulk_buffer[4] = 0; + + // usb_transfer_schedule_block( + // &usb_endpoint_bulk_out, + // &usb_bulk_buffer[0x0000], + // 5, + // NULL, + // NULL); + + // usb_transfer_schedule_ack(endpoint->out); + + + + } + else if (stage == USB_TRANSFER_STAGE_DATA) { + HALT_UNTIL_DEBUGGING(); + } + else if (stage == USB_TRANSFER_STAGE_STATUS) { + HALT_UNTIL_DEBUGGING(); + } + return USB_REQUEST_STATUS_OK; + + (void)(endpoint); (void)(stage); return USB_REQUEST_STATUS_OK; } -static usb_request_handler_fn vendor_request_handler[] = { - NULL, - dummy // USB_WCID_VENDOR_REQ -}; - -static const uint32_t vendor_request_handler_count = - sizeof(vendor_request_handler) / sizeof(vendor_request_handler[0]); - usb_request_status_t usb_vendor_request( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { usb_request_status_t status = USB_REQUEST_STATUS_STALL; - if (endpoint->setup.request < vendor_request_handler_count) { - usb_request_handler_fn handler = - vendor_request_handler[endpoint->setup.request]; - if (handler) { - status = handler(endpoint, stage); - } + volatile uint_fast8_t address = endpoint->address; + volatile uint8_t request = endpoint->setup.request; + volatile uint32_t b = 0; + + if (request == 25) { // unknown code + return report_magic_scsi(endpoint, stage); } + b = request + (address << 16); + HALT_UNTIL_DEBUGGING(); + + return status; } +usb_request_status_t usb_class_request( + usb_endpoint_t* const endpoint, + const usb_transfer_stage_t stage) +{ + usb_request_status_t status = USB_REQUEST_STATUS_STALL; + + volatile uint_fast8_t address = endpoint->address; + volatile uint8_t request = endpoint->setup.request; + volatile uint32_t b = 0; + + if (request == 0xFE) { + return report_max_lun(endpoint, stage); + } + + b = request + (address << 16); + HALT_UNTIL_DEBUGGING(); + + // if (address == 0x80) { + + // HALT_UNTIL_DEBUGGING(); + // return USB_REQUEST_STATUS_OK; + // } + + // else if (address == 0x00) { + // if (request == 0xFE) { + // return USB_REQUEST_STATUS_OK; // ??????????????????? + // } + // b = request + (address << 16); + // HALT_UNTIL_DEBUGGING(); + // } + + // else if (address == 0x02) { + // if (request == 0xFE) { + // return USB_REQUEST_STATUS_OK; // ??????????????????? + // } + // //return USB_REQUEST_STATUS_OK; + // } + + + // HALT_UNTIL_DEBUGGING(); + return status + b; +} + const usb_request_handlers_t usb_request_handlers = { .standard = usb_standard_request, - .class = 0, + .class = usb_class_request, .vendor = usb_vendor_request, - .reserved = 0, + .reserved = 0 }; - void usb_configuration_changed(usb_device_t* const device) { - /* Reset transceiver to idle state until other commands are received */ - // request_transceiver_mode(TRANSCEIVER_MODE_OFF); - // if (device->configuration->number == 1) { - // // transceiver configuration - // led_on(LED1); - // } else { - // /* Configuration number equal 0 means usb bus reset. */ - // led_off(LED1); - // } usb_endpoint_init(&usb_endpoint_bulk_in); usb_endpoint_init(&usb_endpoint_bulk_out); } - void start_usb(void) { - - /* use XTAL_OSC as clock source for PLL0USB */ - // CGU_PLL0USB_CTRL = - // CGU_PLL0USB_CTRL_PD(1) /* PLL0 power down */ | - // CGU_PLL0USB_CTRL_AUTOBLOCK(1) /* Block clock automatically during frequency change */ | - // CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL); /* Clock source selection */ - - // while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {} - - /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */ - /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */ - - // CGU_PLL0USB_MDIV = 0x06167FFA; - // CGU_PLL0USB_NP_DIV = 0x00302062; - - // CGU_PLL0USB_CTRL |= - // CGU_PLL0USB_CTRL_PD(1) /* PLL0 power down */ | - // CGU_PLL0USB_CTRL_DIRECTI(1) /* PLL0 direct input */ | - // CGU_PLL0USB_CTRL_DIRECTO(1) /* PLL0 direct output */ | - // CGU_PLL0USB_CTRL_CLKEN(1) /* PLL0 clock enable */; - - // /* power on PLL0USB and wait until stable */ - // CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK /* PLL0 power down */ ; - - // while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {} - - /* use PLL0USB as clock source for USB0 */ - // CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) | - // CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB); - detect_hardware_platform(); pin_setup(); cpu_clock_init(); - usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); @@ -113,16 +186,39 @@ void start_usb(void) { nvic_set_priority(NVIC_USB0_IRQ, 255); usb_run(&usb_device); - - } - void stop_usb(void) { usb_peripheral_reset(); - } void irq_usb(void) { usb0_isr(); } + +volatile bool transfer_complete = false; +void scsi_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred) +{ + transfer_complete = true; +} + +void usb_transfer(void) { + if (scsi_running) { + transfer_complete = false; + usb_transfer_schedule_block( + &usb_endpoint_bulk_out, + &usb_bulk_buffer[0], + USB_TRANSFER_SIZE, + scsi_bulk_transfer_complete, + NULL); + + while (!transfer_complete); + + msd_cbw_t *msd_cbw_data = (msd_cbw_t *) &usb_bulk_buffer[0]; + + if (msd_cbw_data->signature == MSD_CBW_SIGNATURE){ + scsi_command(msd_cbw_data); + } + + } +} \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.h b/firmware/baseband/sd_over_usb/sd_over_usb.h index ecdb0d4dc..536ac3814 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.h +++ b/firmware/baseband/sd_over_usb/sd_over_usb.h @@ -33,10 +33,11 @@ #include #include "platform_detect.h" #include "hackrf_core.h" +#include "usb_bulk_buffer.h" void start_usb(void); void stop_usb(void); - - +void irq_usb(void); +void usb_transfer(void); #endif /* __USB_SD_OVER_USB_H__ */ \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/usb.c b/firmware/baseband/sd_over_usb/usb.c new file mode 100644 index 000000000..fd212f311 --- /dev/null +++ b/firmware/baseband/sd_over_usb/usb.c @@ -0,0 +1,676 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Jared Boone + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include +#include "usb_type.h" +#include "usb_queue.h" +#include "usb_standard_request.h" + +#include +#include +#include +#include + +#define HALT_UNTIL_DEBUGGING() \ + while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \ + __asm__ __volatile__("bkpt 1") + + +usb_device_t* usb_device_usb0 = 0; + +usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048); + +#define USB_QH_INDEX(endpoint_address) \ + (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) + +usb_queue_head_t* usb_queue_head(const uint_fast8_t endpoint_address) +{ + return &usb_qh[USB_QH_INDEX(endpoint_address)]; +} + +usb_endpoint_t* usb_endpoint_from_address(const uint_fast8_t endpoint_address) +{ + return (usb_endpoint_t*) usb_queue_head(endpoint_address)->_reserved_0; +} + +static uint_fast8_t usb_endpoint_address( + const usb_transfer_direction_t direction, + const uint_fast8_t number) +{ + return ((direction == USB_TRANSFER_DIRECTION_IN) ? 0x80 : 0x00) + number; +} + +static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address) +{ + return (endpoint_address & 0x80) ? true : false; +} + +static uint_fast8_t usb_endpoint_number(const uint_fast8_t endpoint_address) +{ + return (endpoint_address & 0xF); +} + +void usb_peripheral_reset() +{ + RESET_CTRL0 = RESET_CTRL0_USB0_RST; + RESET_CTRL0 = 0; + + while ((RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0) {} +} + +void usb_phy_enable() +{ + CREG_CREG0 &= ~CREG_CREG0_USB0PHY; +} + +static void usb_clear_pending_interrupts(const uint32_t mask) +{ + USB0_ENDPTNAK = mask; + USB0_ENDPTNAKEN = mask; + USB0_USBSTS_D = mask; + USB0_ENDPTSETUPSTAT = USB0_ENDPTSETUPSTAT & mask; + USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE & mask; +} + +static void usb_clear_all_pending_interrupts() +{ + usb_clear_pending_interrupts(0xFFFFFFFF); +} + +static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) +{ + // Wait until controller has parsed new transfer descriptors and prepared + // receive buffers. + while (USB0_ENDPTPRIME & mask) {} +} + +static void usb_flush_endpoints(const uint32_t mask) +{ + // Clear any primed buffers. If a packet is in progress, that transfer + // will continue until completion. + USB0_ENDPTFLUSH = mask; +} + +static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask) +{ + // Wait until controller has flushed all endpoints / cleared any primed + // buffers. + while (USB0_ENDPTFLUSH & mask) {} +} + +static void usb_flush_primed_endpoints(const uint32_t mask) +{ + usb_wait_for_endpoint_priming_to_finish(mask); + usb_flush_endpoints(mask); + usb_wait_for_endpoint_flushing_to_finish(mask); +} + +static void usb_flush_all_primed_endpoints() +{ + usb_flush_primed_endpoints(0xFFFFFFFF); +} + +static void usb_endpoint_set_type( + const usb_endpoint_t* const endpoint, + const usb_transfer_type_t transfer_type) +{ + // NOTE: UM10503 section 23.6.24 "Endpoint 1 to 5 control registers" says + // that the disabled side of an endpoint must be set to a non-control type + // (e.g. bulk, interrupt, or iso). + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + USB0_ENDPTCTRL(endpoint_number) = + (USB0_ENDPTCTRL(endpoint_number) & + ~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK)) | + (USB0_ENDPTCTRL_TXT1_0(transfer_type) | + USB0_ENDPTCTRL_RXT(transfer_type)); +} + +static void usb_endpoint_enable(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + USB0_ENDPTCTRL(endpoint_number) |= + (USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR); + } else { + USB0_ENDPTCTRL(endpoint_number) |= + (USB0_ENDPTCTRL_RXE | USB0_ENDPTCTRL_RXR); + } +} + +static void usb_endpoint_clear_pending_interrupts(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + usb_clear_pending_interrupts( + USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number)); + } else { + usb_clear_pending_interrupts( + USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number)); + } +} + +void usb_endpoint_disable(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_TXE); + } else { + USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE); + } + usb_queue_flush_endpoint(endpoint); + usb_endpoint_clear_pending_interrupts(endpoint); + usb_endpoint_flush(endpoint); +} + +void usb_endpoint_prime( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const first_td) +{ + usb_queue_head_t* const qh = usb_queue_head(endpoint->address); + + qh->next_dtd_pointer = first_td; + qh->total_bytes &= + ~(USB_TD_DTD_TOKEN_STATUS_ACTIVE | USB_TD_DTD_TOKEN_STATUS_HALTED); + + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + USB0_ENDPTPRIME = USB0_ENDPTPRIME_PETB(1 << endpoint_number); + } else { + USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number); + } +} + +static bool usb_endpoint_is_priming(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number); + } else { + return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number); + } +} + +// Schedule an already filled-in transfer descriptor for execution on +// the given endpoint, waiting until the endpoint has finished. +void usb_endpoint_schedule_wait( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const td) +{ + // Ensure that endpoint is ready to be primed. + // It may have been flushed due to an aborted transaction. + // TODO: This should be preceded by a flush? + while (usb_endpoint_is_ready(endpoint)) {} + + td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; + + usb_endpoint_prime(endpoint, td); +} + +// Schedule an already filled-in transfer descriptor for execution on +// the given endpoint, appending to the end of the endpoint's queue if +// there are pending TDs. Note that this requires that one knows the +// tail of the endpoint's TD queue. Moreover, the user is responsible +// for setting the TERMINATE bit of next_dtd_pointer if needed. +void usb_endpoint_schedule_append( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const tail_td, + usb_transfer_descriptor_t* const new_td) +{ + bool done; + + tail_td->next_dtd_pointer = new_td; + + if (usb_endpoint_is_priming(endpoint)) { + return; + } + + do { + USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW; + done = usb_endpoint_is_ready(endpoint); + } while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW)); + + USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW; + if (!done) { + usb_endpoint_prime(endpoint, new_td); + } +} + +void usb_endpoint_flush(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + usb_queue_flush_endpoint(endpoint); + if (usb_endpoint_is_in(endpoint->address)) { + usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FETB(1 << endpoint_number)); + } else { + usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FERB(1 << endpoint_number)); + } +} + +/* +static bool usb_endpoint_is_flushing( + const usb_endpoint_t* const endpoint +) { + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if( usb_endpoint_is_in(endpoint->address) ) { + return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FETB(1 << endpoint_number); + } else { + return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FERB(1 << endpoint_number); + } +} +*/ +bool usb_endpoint_is_ready(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ETBR(1 << endpoint_number); + } else { + return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ERBR(1 << endpoint_number); + } +} + +bool usb_endpoint_is_complete(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number); + } else { + return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number); + } +} + +void usb_endpoint_stall(const usb_endpoint_t* const endpoint) +{ + // Endpoint is to be stalled as a pair -- both OUT and IN. + // See UM10503 section 23.10.5.2 "Stalling" + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXS | USB0_ENDPTCTRL_TXS); + + // TODO: Also need to reset data toggle in both directions? +} + +void usb_endpoint_reset_data_toggle(const usb_endpoint_t* const endpoint) +{ + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + if (usb_endpoint_is_in(endpoint->address)) { + USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_TXR; + } else { + USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_RXR; + } +} + +static void usb_controller_run() +{ + USB0_USBCMD_D |= USB0_USBCMD_D_RS; +} + +static void usb_controller_stop() +{ + USB0_USBCMD_D &= ~USB0_USBCMD_D_RS; +} + +static uint_fast8_t usb_controller_is_resetting() +{ + return (USB0_USBCMD_D & USB0_USBCMD_D_RST) != 0; +} + +static void usb_controller_set_device_mode() +{ + // Set USB0 peripheral mode + USB0_USBMODE_D = USB0_USBMODE_D_CM1_0(2); + + // Set device-related OTG flags + // OTG termination: controls pull-down on USB_DM + USB0_OTGSC = USB0_OTGSC_OT; +} + +usb_speed_t usb_speed(const usb_device_t* const device) +{ + if (device == usb_device_usb0) { + switch (USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK) { + case USB0_PORTSC1_D_PSPD(0): + return USB_SPEED_FULL; + + case USB0_PORTSC1_D_PSPD(2): + return USB_SPEED_HIGH; + + default: + // TODO: What to do/return here? Is this even possible? + return USB_SPEED_FULL; + } + } else { + // TODO: This should not be possible with a more class-like + // implementation. + return USB_SPEED_FULL; + } +} + +static void usb_clear_status(const uint32_t status) +{ + USB0_USBSTS_D = status; +} + +static uint32_t usb_get_status() +{ + // Mask status flags with enabled flag interrupts. + const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D; + + // Clear flags that were just read, leaving alone any flags that + // were just set (after the read). It's important to read and + // reset flags atomically! :-) + usb_clear_status(status); + + return status; +} + +static void usb_clear_endpoint_setup_status(const uint32_t endpoint_setup_status) +{ + USB0_ENDPTSETUPSTAT = endpoint_setup_status; +} + +static uint32_t usb_get_endpoint_setup_status() +{ + return USB0_ENDPTSETUPSTAT; +} + +static void usb_clear_endpoint_complete(const uint32_t endpoint_complete) +{ + USB0_ENDPTCOMPLETE = endpoint_complete; +} + +static uint32_t usb_get_endpoint_complete() +{ + return USB0_ENDPTCOMPLETE; +} + +static void usb_disable_all_endpoints() +{ + // Endpoint 0 is always enabled. TODO: So why set ENDPTCTRL0? + USB0_ENDPTCTRL0 &= ~(USB0_ENDPTCTRL0_RXE | USB0_ENDPTCTRL0_TXE); + USB0_ENDPTCTRL1 &= ~(USB0_ENDPTCTRL1_RXE | USB0_ENDPTCTRL1_TXE); + USB0_ENDPTCTRL2 &= ~(USB0_ENDPTCTRL2_RXE | USB0_ENDPTCTRL2_TXE); + USB0_ENDPTCTRL3 &= ~(USB0_ENDPTCTRL3_RXE | USB0_ENDPTCTRL3_TXE); + USB0_ENDPTCTRL4 &= ~(USB0_ENDPTCTRL4_RXE | USB0_ENDPTCTRL4_TXE); + USB0_ENDPTCTRL5 &= ~(USB0_ENDPTCTRL5_RXE | USB0_ENDPTCTRL5_TXE); +} + +void usb_set_address_immediate( + const usb_device_t* const device, + const uint_fast8_t address) +{ + if (device == usb_device_usb0) { + USB0_DEVICEADDR = USB0_DEVICEADDR_USBADR(address); + } +} + +void usb_set_address_deferred(const usb_device_t* const device, const uint_fast8_t address) +{ + if (device == usb_device_usb0) { + USB0_DEVICEADDR = + USB0_DEVICEADDR_USBADR(address) | USB0_DEVICEADDR_USBADRA; + } +} + +static void usb_reset_all_endpoints() +{ + usb_disable_all_endpoints(); + usb_clear_all_pending_interrupts(); + usb_flush_all_primed_endpoints(); +} + +static void usb_controller_reset() +{ + // TODO: Good to disable some USB interrupts to avoid priming new + // new endpoints before the controller is reset? + usb_reset_all_endpoints(); + usb_controller_stop(); + + // Reset controller. Resets internal pipelines, timers, counters, state + // machines to initial values. Not recommended when device is in attached + // state -- effect on attached host is undefined. Detach first by flushing + // all primed endpoints and stopping controller. + USB0_USBCMD_D = USB0_USBCMD_D_RST; + + while (usb_controller_is_resetting()) {} +} + +static void usb_bus_reset(usb_device_t* const device) +{ + // According to UM10503 v1.4 section 23.10.3 "Bus reset": + usb_reset_all_endpoints(); + usb_set_address_immediate(device, 0); + usb_set_configuration(device, 0); + + // TODO: Enable endpoint 0, which might not actually be necessary, + // as the datasheet claims it can't be disabled. + + //wait_ms(3); + // + //if( USB0_PORTSC1 & USB0_PORTSC1_PR ) { + // // Port still is in the reset state. + //} else { + // usb_hardware_reset(); + //} +} + +static void usb_interrupt_enable(usb_device_t* const device) +{ + if (device == usb_device_usb0) { + nvic_enable_irq(NVIC_USB0_IRQ); + } +} + +void usb_device_init(const uint_fast8_t device_ordinal, usb_device_t* const device) +{ + if (device_ordinal == 0) { + usb_device_usb0 = device; + + usb_phy_enable(); + usb_controller_reset(); + usb_controller_set_device_mode(); + + // Set interrupt threshold interval to 0 + USB0_USBCMD_D &= ~USB0_USBCMD_D_ITC_MASK; + + // Configure endpoint list address + USB0_ENDPOINTLISTADDR = (uint32_t) usb_qh; + + // Enable interrupts + USB0_USBINTR_D = USB0_USBINTR_D_UE | USB0_USBINTR_D_UEE | + USB0_USBINTR_D_PCE | + USB0_USBINTR_D_URE + //| USB0_USBINTR_D_SRE + | USB0_USBINTR_D_SLE + //| USB0_USBINTR_D_NAKE + ; + } +} + +void usb_run(usb_device_t* const device) +{ + usb_interrupt_enable(device); + usb_controller_run(device); +} + +static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src) +{ + dst->request_type = src[0]; + dst->request = src[1]; + dst->value_l = src[2]; + dst->value_h = src[3]; + dst->index_l = src[4]; + dst->index_h = src[5]; + dst->length_l = src[6]; + dst->length_h = src[7]; +} + +void usb_endpoint_init(const usb_endpoint_t* const endpoint) +{ + usb_endpoint_flush(endpoint); + + uint_fast16_t max_packet_size = endpoint->device->descriptor[7]; + usb_transfer_type_t transfer_type = USB_TRANSFER_TYPE_CONTROL; + const uint8_t* const endpoint_descriptor = usb_endpoint_descriptor(endpoint); + if (endpoint_descriptor) { + max_packet_size = + usb_endpoint_descriptor_max_packet_size(endpoint_descriptor); + transfer_type = + usb_endpoint_descriptor_transfer_type(endpoint_descriptor); + } + + // TODO: There are more capabilities to adjust based on the endpoint + // descriptor. + usb_queue_head_t* const qh = usb_queue_head(endpoint->address); + qh->capabilities = USB_QH_CAPABILITIES_MULT(0) | USB_QH_CAPABILITIES_ZLT | + USB_QH_CAPABILITIES_MPL(max_packet_size) | + ((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS : + 0); + qh->current_dtd_pointer = 0; + qh->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; + qh->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(0) | USB_TD_DTD_TOKEN_MULTO(0); + qh->buffer_pointer_page[0] = 0; + qh->buffer_pointer_page[1] = 0; + qh->buffer_pointer_page[2] = 0; + qh->buffer_pointer_page[3] = 0; + qh->buffer_pointer_page[4] = 0; + + // This is how we look up an endpoint structure from an endpoint address: + qh->_reserved_0 = (uint32_t) endpoint; + + // TODO: Should NAK be enabled? I'm kinda squishy on this... + //USB0_ENDPTNAKEN |= + // USB0_ENDPTNAKEN_EPRNE(1 << endpoint_out->number); + + usb_endpoint_set_type(endpoint, transfer_type); + + usb_endpoint_enable(endpoint); +} + +static void usb_check_for_setup_events() { + const uint32_t endptsetupstat = usb_get_endpoint_setup_status(); + if (endptsetupstat) { + for (uint_fast8_t i = 0; i < 6; i++) { + const uint32_t endptsetupstat_bit = USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i); + if (endptsetupstat & endptsetupstat_bit) { + usb_endpoint_t* const endpoint = usb_endpoint_from_address(usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)); + if (endpoint && endpoint->setup_complete) { + usb_queue_head_t *head = usb_queue_head(endpoint->address); + + //HALT_UNTIL_DEBUGGING(); + + copy_setup(&endpoint->setup, head->setup); + // TODO: Clean up this duplicated effort by providing + // a cleaner way to get the SETUP data. + copy_setup(&endpoint->in->setup, head->setup); + + usb_clear_endpoint_setup_status(endptsetupstat_bit); + endpoint->setup_complete(endpoint); + } else { + usb_clear_endpoint_setup_status(endptsetupstat_bit); + } + } + } + } +} + +static void usb_check_for_transfer_events() { + const uint32_t endptcomplete = usb_get_endpoint_complete(); + + if (endptcomplete) { + for (uint_fast8_t i = 0; i < 6; i++) { + const uint32_t endptcomplete_out_bit = USB0_ENDPTCOMPLETE_ERCE(1 << i); + + if (endptcomplete & endptcomplete_out_bit) { + usb_clear_endpoint_complete(endptcomplete_out_bit); + usb_endpoint_t* const endpoint = usb_endpoint_from_address(usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)); + if (endpoint && endpoint->transfer_complete) { + endpoint->transfer_complete(endpoint); + } + } + + const uint32_t endptcomplete_in_bit = USB0_ENDPTCOMPLETE_ETCE(1 << i); + + if (endptcomplete & endptcomplete_in_bit) { + usb_clear_endpoint_complete(endptcomplete_in_bit); + usb_endpoint_t* const endpoint = usb_endpoint_from_address(usb_endpoint_address(USB_TRANSFER_DIRECTION_IN, i)); + if (endpoint && endpoint->transfer_complete) { + endpoint->transfer_complete(endpoint); + } + } + } + } +} + +void usb0_isr() +{ + const uint32_t status = usb_get_status(); + + if (status == 0) { + // Nothing to do. + return; + } + + if (status & USB0_USBSTS_D_UI) { + // USB: + // - Completed transaction transfer descriptor has IOC set. + // - Short packet detected. + // - SETUP packet received. + + usb_check_for_setup_events(); + usb_check_for_transfer_events(); + + // TODO: Reset ignored ENDPTSETUPSTAT and ENDPTCOMPLETE flags? + } + + if (status & USB0_USBSTS_D_SRI) { + // Start Of Frame received. + } + + if (status & USB0_USBSTS_D_PCI) { + // Port change detect: + // Port controller entered full- or high-speed operational state. + } + + if (status & USB0_USBSTS_D_SLI) { + // Device controller suspend. + } + + if (status & USB0_USBSTS_D_URI) { + // USB reset received. + usb_bus_reset(usb_device_usb0); + } + + if (status & USB0_USBSTS_D_UEI) { + // USB error: + // Completion of a USB transaction resulted in an error condition. + // Set along with USBINT if the TD on which the error interrupt + // occurred also had its interrupt on complete (IOC) bit set. + // The device controller detects resume signalling only. + } + + if (status & USB0_USBSTS_D_NAKI) { + // Both the TX/RX endpoint NAK bit and corresponding TX/RX endpoint + // NAK enable bit are set. + } +} diff --git a/firmware/baseband/sd_over_usb/usb_descriptor.c b/firmware/baseband/sd_over_usb/usb_descriptor.c index 7f5adc474..fdba7b1dd 100644 --- a/firmware/baseband/sd_over_usb/usb_descriptor.c +++ b/firmware/baseband/sd_over_usb/usb_descriptor.c @@ -85,7 +85,7 @@ uint8_t usb_descriptor_configuration_full_speed[] = { USB_WORD(32), // wTotalLength 0x01, // bNumInterfaces 0x01, // bConfigurationValue - 0x03, // iConfiguration + 0x00, // iConfiguration 0x80, // bmAttributes: USB-powered 250, // bMaxPower: 500mA @@ -94,9 +94,9 @@ uint8_t usb_descriptor_configuration_full_speed[] = { 0x00, // bInterfaceNumber 0x00, // bAlternateSetting 0x02, // bNumEndpoints - 0xFF, // bInterfaceClass: vendor-specific - 0xFF, // bInterfaceSubClass - 0xFF, // bInterfaceProtocol: vendor-specific + 0x08, // bInterfaceClass: vendor-specific + 0x06, // bInterfaceSubClass + 0x50, // bInterfaceProtocol: vendor-specific 0x00, // iInterface 7, // bLength @@ -122,7 +122,7 @@ uint8_t usb_descriptor_configuration_high_speed[] = { USB_WORD(32), // wTotalLength 0x01, // bNumInterfaces 0x01, // bConfigurationValue - 0x03, // iConfiguration + 0x00, // iConfiguration 0x80, // bmAttributes: USB-powered 250, // bMaxPower: 500mA @@ -131,9 +131,9 @@ uint8_t usb_descriptor_configuration_high_speed[] = { 0x00, // bInterfaceNumber 0x00, // bAlternateSetting 0x02, // bNumEndpoints - 0xFF, // bInterfaceClass: vendor-specific - 0xFF, // bInterfaceSubClass - 0xFF, // bInterfaceProtocol: vendor-specific + 0x08, // bInterfaceClass: vendor-specific + 0x06, // bInterfaceSubClass + 0x50, // bInterfaceProtocol: vendor-specific 0x00, // iInterface 7, // bLength diff --git a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC43xx_M4.ld b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC43xx_M4.ld index 6eb411753..08bcc093b 100755 --- a/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC43xx_M4.ld +++ b/firmware/chibios-portapack/os/ports/GCC/ARMCMx/LPC43xx_M4/ld/LPC43xx_M4.ld @@ -25,8 +25,10 @@ MEMORY { flash (rx) : org = 0x00000000, len = 32752 /* Local SRAM @ 0x10080000 */ ram (rwx) : org = 0x10000000, len = 96k /* Local SRAM @ 0x10000000 */ + ram_usb (rwx) : org = 0x20008000, len = 32K } +usb_bulk_buffer = ORIGIN(ram_usb); __ram_start__ = ORIGIN(ram); __ram_size__ = LENGTH(ram); __ram_end__ = __ram_start__ + __ram_size__; From fc1b676ce64cec7274ea985ceae1fc3e2f1e1d86 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Fri, 31 Mar 2023 22:34:55 +0200 Subject: [PATCH 04/11] implemented rest of scsi stack --- firmware/baseband/sd_over_usb/scsi.c | 378 ++++++++++++++++++++++----- firmware/baseband/sd_over_usb/scsi.h | 78 ++++++ 2 files changed, 396 insertions(+), 60 deletions(-) diff --git a/firmware/baseband/sd_over_usb/scsi.c b/firmware/baseband/sd_over_usb/scsi.c index b4b035364..18397ecdc 100644 --- a/firmware/baseband/sd_over_usb/scsi.c +++ b/firmware/baseband/sd_over_usb/scsi.c @@ -62,23 +62,9 @@ volatile bool inquiry_stage_one_send = false; void inquiry_cb(void* user_data, unsigned int bytes_transferred) { inquiry_stage_one_send = true; - - //HALT_UNTIL_DEBUGGING(); - - //faulty - // usb_transfer_schedule_block( - // &usb_endpoint_bulk_out, - // &usb_bulk_buffer[0], - // USB_TRANSFER_SIZE, - // handle_inquiry_3, - // msd_cbw_data); - - -//does not send - } -void handle_inquiry(msd_cbw_t *msd_cbw_data){ +void handle_inquiry(msd_cbw_t *msd_cbw_data) { inquiry_stage_one_send = false; memcpy(&usb_bulk_buffer[0], &default_scsi_inquiry_response, sizeof(scsi_inquiry_response_t)); usb_transfer_schedule_block( @@ -98,16 +84,290 @@ void handle_inquiry(msd_cbw_t *msd_cbw_data){ }; memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - // does not gets send usb_transfer_schedule_block( &usb_endpoint_bulk_in, &usb_bulk_buffer[0x4000], sizeof(msd_csw_t), - NULL, //handle_inquiry_3, - NULL); //msd_cbw_data); + NULL, + NULL); } +typedef struct { + uint8_t header[4]; + uint8_t blocknum[4]; + uint8_t blocklen[4]; +} scsi_read_format_capacities_response_t; + +volatile bool capacities_stage_one_send = false; +void capacities_cb(void* user_data, unsigned int bytes_transferred) +{ + capacities_stage_one_send = true; +} + +void read_format_capacities(msd_cbw_t *msd_cbw_data) { + uint16_t len = msd_cbw_data->cmd_data[7] << 8 | msd_cbw_data->cmd_data[8]; + + if (len != 0) { + scsi_read_format_capacities_response_t ret = { + .header = {0, 0, 0, 1 * 8 /* num_entries * 8 */}, + .blocknum = {0, 0, (1024 * 8) >> 8, 0}, // 32GB + .blocklen = {0b10 /* formated */, 0, (512) >> 8, 0} + }; + + capacities_stage_one_send = false; + memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_format_capacities_response_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0], + sizeof(scsi_inquiry_response_t), + capacities_cb, + msd_cbw_data); + + while (!capacities_stage_one_send); + } + + + msd_csw_t csw = { + .signature = MSD_CSW_SIGNATURE, + .tag = msd_cbw_data->tag, + .data_residue = 0, + .status = 0 + }; + + memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0x4000], + sizeof(msd_csw_t), + NULL, + NULL); + +} + +typedef struct { + uint32_t last_block_addr; + uint32_t block_size; +} scsi_read_capacity10_response_t; + +volatile bool capacity10_stage_one_send = false; +void capacity10_cb(void* user_data, unsigned int bytes_transferred) +{ + capacity10_stage_one_send = true; +} + +void read_capacity10(msd_cbw_t *msd_cbw_data) { + capacity10_stage_one_send = false; + + scsi_read_capacity10_response_t ret = { + .last_block_addr = cpu_to_be32(8 * 1024 * 1024 - 1), + .block_size = cpu_to_be32(512) + }; + + memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_capacity10_response_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0], + sizeof(scsi_read_capacity10_response_t), + capacity10_cb, + msd_cbw_data); + + while (!capacity10_stage_one_send); + + msd_csw_t csw = { + .signature = MSD_CSW_SIGNATURE, + .tag = msd_cbw_data->tag, + .data_residue = 0, + .status = 0 + }; + + memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0x4000], + sizeof(msd_csw_t), + NULL, + NULL); + +} + + +typedef struct { + uint8_t byte[18]; +} scsi_sense_response_t; + +volatile bool sense_stage_one_send = false; +void sense_cb(void* user_data, unsigned int bytes_transferred) +{ + sense_stage_one_send = true; +} + + +void request_sense(msd_cbw_t *msd_cbw_data) { + sense_stage_one_send = false; + + scsi_sense_response_t ret = { + .byte = { 0x70, 0, SCSI_SENSE_KEY_GOOD, 0, + 0, 0, 0, 8, + 0, 0 ,0 ,0, + SCSI_ASENSE_NO_ADDITIONAL_INFORMATION, SCSI_ASENSEQ_NO_QUALIFIER, 0, 0, + 0, 0 } + }; + + memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_sense_response_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0], + sizeof(scsi_sense_response_t), + sense_cb, + msd_cbw_data); + + while (!sense_stage_one_send); + + msd_csw_t csw = { + .signature = MSD_CSW_SIGNATURE, + .tag = msd_cbw_data->tag, + .data_residue = 0, + .status = 0 + }; + + memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0x4000], + sizeof(msd_csw_t), + NULL, + NULL); +} + +typedef struct { + uint8_t byte[4]; +} scsi_mode_sense6_response_t; + +volatile bool sense6_stage_one_send = false; +void sense6_cb(void* user_data, unsigned int bytes_transferred) +{ + sense6_stage_one_send = true; +} + +void mode_sense6 (msd_cbw_t *msd_cbw_data) { + sense6_stage_one_send = false; + + scsi_mode_sense6_response_t ret = { + .byte = { + sizeof(scsi_mode_sense6_response_t) - 1, + 0, + 0x01 << 7, // 0 for not write protected + 0 } + }; + + memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_mode_sense6_response_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0], + sizeof(scsi_mode_sense6_response_t), + sense6_cb, + msd_cbw_data); + + while (!sense6_stage_one_send); + + msd_csw_t csw = { + .signature = MSD_CSW_SIGNATURE, + .tag = msd_cbw_data->tag, + .data_residue = 0, + .status = 0 + }; + + memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0x4000], + sizeof(msd_csw_t), + NULL, + NULL); +} + +typedef struct { + uint32_t first_lba; + uint16_t blk_cnt; +} data_request_t; + +static data_request_t decode_data_request(const uint8_t *cmd) { + + data_request_t req; + uint32_t lba; + uint16_t blk; + + memcpy(&lba, &cmd[2], sizeof(lba)); + memcpy(&blk, &cmd[7], sizeof(blk)); + + req.first_lba = be32_to_cpu(lba); + req.blk_cnt = be16_to_cpu(blk); + + return req; +} + +volatile uint32_t read10_blocks_send = 0; +void read10_cb(void* user_data, unsigned int bytes_transferred) +{ + read10_blocks_send++; +} + + +void data_read10(msd_cbw_t *msd_cbw_data) { + read10_blocks_send = 0; + + data_request_t req = decode_data_request(msd_cbw_data->cmd_data); + + for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) { + memset(&usb_bulk_buffer[0], 0, 512); + + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0], + 512, + read10_cb, + msd_cbw_data); + + while (read10_blocks_send <= block_index); + } + + msd_csw_t csw = { + .signature = MSD_CSW_SIGNATURE, + .tag = msd_cbw_data->tag, + .data_residue = 0, + .status = 0 + }; + + memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0x4000], + sizeof(msd_csw_t), + NULL, + NULL); +} + + + + +void test_unit_ready(msd_cbw_t *msd_cbw_data) { + msd_csw_t csw = { + .signature = MSD_CSW_SIGNATURE, + .tag = msd_cbw_data->tag, + .data_residue = 0, + .status = 0 + }; + + memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); + usb_transfer_schedule_block( + &usb_endpoint_bulk_in, + &usb_bulk_buffer[0x4000], + sizeof(msd_csw_t), + NULL, + NULL); +} + void scsi_command(msd_cbw_t *msd_cbw_data) { switch (msd_cbw_data->cmd_data[0]) { @@ -117,50 +377,48 @@ void scsi_command(msd_cbw_t *msd_cbw_data) { break; - default: - HALT_UNTIL_DEBUGGING(); + case SCSI_CMD_REQUEST_SENSE: + request_sense(msd_cbw_data); + break; + + case SCSI_CMD_READ_CAPACITY_10: + read_capacity10(msd_cbw_data); + break; + + case SCSI_CMD_READ_10: + data_read10(msd_cbw_data); + break; + + /* + case SCSI_CMD_WRITE_10: + ret = data_read_write10(scsip, cmd); + break; +*/ + case SCSI_CMD_TEST_UNIT_READY: + test_unit_ready(msd_cbw_data); + break; + + case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + test_unit_ready(msd_cbw_data); + // ret = cmd_ignored(scsip, cmd); + break; + + case SCSI_CMD_MODE_SENSE_6: + mode_sense6(msd_cbw_data); + break; + + case SCSI_CMD_READ_FORMAT_CAPACITIES: + read_format_capacities(msd_cbw_data); + break; + + case SCSI_CMD_VERIFY_10: + test_unit_ready(msd_cbw_data); break; /* - case SCSI_CMD_REQUEST_SENSE: - ret = request_sense(scsip, cmd); - break; - - case SCSI_CMD_READ_CAPACITY_10: - ret = read_capacity10(scsip, cmd); - break; - - case SCSI_CMD_READ_10: - ret = data_read_write10(scsip, cmd); - break; - - case SCSI_CMD_WRITE_10: - ret = data_read_write10(scsip, cmd); - break; - - case SCSI_CMD_TEST_UNIT_READY: - ret = test_unit_ready(scsip, cmd); - break; - - case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - ret = cmd_ignored(scsip, cmd); - break; - - case SCSI_CMD_MODE_SENSE_6: - ret = mode_sense6(scsip, cmd); - break; - - case SCSI_CMD_READ_FORMAT_CAPACITIES: - ret = read_format_capacities(scsip, cmd); - break; - - case SCSI_CMD_VERIFY_10: - ret = cmd_ignored(scsip, cmd); - break; - - default: - ret = cmd_unhandled(scsip, cmd); - break; - */ + default: + ret = cmd_unhandled(scsip, cmd); + break; + */ } // if (ret == SCSI_SUCCESS) diff --git a/firmware/baseband/sd_over_usb/scsi.h b/firmware/baseband/sd_over_usb/scsi.h index 616c9aff9..85dedd1a2 100644 --- a/firmware/baseband/sd_over_usb/scsi.h +++ b/firmware/baseband/sd_over_usb/scsi.h @@ -26,6 +26,36 @@ #define SCSI_CMD_WRITE_10 0x2A #define SCSI_CMD_VERIFY_10 0x2F +#define SCSI_SENSE_KEY_GOOD 0x00 +#define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01 +#define SCSI_SENSE_KEY_NOT_READY 0x02 +#define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03 +#define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04 +#define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05 +#define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06 +#define SCSI_SENSE_KEY_DATA_PROTECT 0x07 +#define SCSI_SENSE_KEY_BLANK_CHECK 0x08 +#define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09 +#define SCSI_SENSE_KEY_COPY_ABORTED 0x0A +#define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B +#define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D +#define SCSI_SENSE_KEY_MISCOMPARE 0x0E + +#define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00 +#define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04 +#define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24 +#define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28 +#define SCSI_ASENSE_WRITE_PROTECTED 0x27 +#define SCSI_ASENSE_FORMAT_ERROR 0x31 +#define SCSI_ASENSE_INVALID_COMMAND 0x20 +#define SCSI_ASENSE_LBA_OUT_OF_RANGE 0x21 +#define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A + +#define SCSI_ASENSEQ_NO_QUALIFIER 0x00 +#define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01 +#define SCSI_ASENSEQ_INIT_COMMAND_REQUIRED 0x02 +#define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07 + #define MSD_CBW_SIGNATURE 0x43425355 #define MSD_CSW_SIGNATURE 0x53425355 @@ -41,6 +71,54 @@ typedef struct { uint8_t cmd_data[16]; } __attribute__((packed)) msd_cbw_t; +static inline uint16_t bswap_16(const uint16_t x) + __attribute__ ((warn_unused_result)) + __attribute__ ((const)) + __attribute__ ((always_inline)); + +static inline uint16_t bswap_16(const uint16_t x) { + + uint8_t tmp; + union { uint16_t x; uint8_t b[2]; } data; + + data.x = x; + tmp = data.b[0]; + data.b[0] = data.b[1]; + data.b[1] = tmp; + + return data.x; +} + +static inline uint32_t bswap_32(const uint32_t x) + __attribute__ ((warn_unused_result)) + __attribute__ ((const)) + __attribute__ ((always_inline)); + + +static inline uint32_t bswap_32(const uint32_t x) { + + uint8_t tmp; + union { uint32_t x; uint8_t b[4]; } data; + + data.x = x; + tmp = data.b[0]; + data.b[0] = data.b[3]; + data.b[3] = tmp; + tmp = data.b[1]; + data.b[1] = data.b[2]; + data.b[2] = tmp; + + return data.x; +} + +#define be16_to_cpu(x) bswap_16(x) +#define be32_to_cpu(x) bswap_32(x) + +#define cpu_to_be16(x) bswap_16(x) +#define cpu_to_be32(x) bswap_32(x) + + + void scsi_command(msd_cbw_t *msd_cbw_data); #endif /* __SCSI_H__ */ \ No newline at end of file From 50859171f411c103b157fb91ca90787ab27e4355 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 1 Apr 2023 17:21:57 +0200 Subject: [PATCH 05/11] implemented msd read --- firmware/application/apps/ui_sd_over_usb.cpp | 2 +- firmware/baseband/CMakeLists.txt | 6 +- firmware/baseband/halconf.h | 2 +- firmware/baseband/sd_over_usb/diskio.c | 12 + firmware/baseband/sd_over_usb/diskio.h | 10 + firmware/baseband/sd_over_usb/hackrf_core.c | 1089 +++++++++++++++++ .../baseband/sd_over_usb/proc_sd_over_usb.cpp | 35 +- firmware/baseband/sd_over_usb/scsi.c | 466 +++---- firmware/baseband/sd_over_usb/scsi.h | 64 + firmware/baseband/sd_over_usb/sd_over_usb.c | 19 +- 10 files changed, 1353 insertions(+), 352 deletions(-) create mode 100644 firmware/baseband/sd_over_usb/diskio.c create mode 100644 firmware/baseband/sd_over_usb/diskio.h create mode 100644 firmware/baseband/sd_over_usb/hackrf_core.c diff --git a/firmware/application/apps/ui_sd_over_usb.cpp b/firmware/application/apps/ui_sd_over_usb.cpp index b8d6c9113..068579d62 100644 --- a/firmware/application/apps/ui_sd_over_usb.cpp +++ b/firmware/application/apps/ui_sd_over_usb.cpp @@ -31,7 +31,7 @@ SdOverUsbView::SdOverUsbView(NavigationView& nav) : nav_ (nav) { sdcStop(&SDCD1); portapack::shutdown(); - m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, true); + m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, false); //m4_init(portapack::spi_flash::image_tag_hackrf, portapack::memory::map::m4_code_hackrf, true); m0_halt(); /* will not return*/ //baseband::run_image(); diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 2d7cbb6c2..1deaa6b4a 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -515,7 +515,7 @@ set(MODE_CPPSRC ) DeclareTargets(PFUT flash_utility) -### SD over USB ${PATH_HACKRF_FIRMWARE} +### SD over USB set(MODE_INCDIR ${HACKRF_PATH}/firmware @@ -526,17 +526,18 @@ set(MODE_CPPSRC sd_over_usb/proc_sd_over_usb.cpp sd_over_usb/scsi.c + sd_over_usb/diskio.c sd_over_usb/sd_over_usb.c sd_over_usb/usb_descriptor.c sd_over_usb/usb_device.c sd_over_usb/usb_endpoint.c sd_over_usb/usb.c + sd_over_usb/hackrf_core.c ${HACKRF_PATH}/firmware/common/usb_queue.c ${HACKRF_PATH}/firmware/common/usb_request.c ${HACKRF_PATH}/firmware/common/usb_standard_request.c ${HACKRF_PATH}/firmware/common/platform_detect.c - ${HACKRF_PATH}/firmware/common/hackrf_core.c ${HACKRF_PATH}/firmware/common/gpio_lpc.c ${HACKRF_PATH}/firmware/common/firmware_info.c ${HACKRF_PATH}/firmware/common/si5351c.c @@ -558,7 +559,6 @@ set(MODE_CPPSRC ${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/scu.c ${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/timer.c ${HACKRF_PATH}/firmware/libopencm3/lib/lpc43xx/i2c.c - ) DeclareTargets(PUSB sd_over_usb) diff --git a/firmware/baseband/halconf.h b/firmware/baseband/halconf.h index d79a158eb..3f24c6999 100755 --- a/firmware/baseband/halconf.h +++ b/firmware/baseband/halconf.h @@ -119,7 +119,7 @@ * @brief Enables the SDC subsystem. */ #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) -#ifdef BASEBAND_flash_utility +#if defined(BASEBAND_flash_utility) || defined(BASEBAND_sd_over_usb) #define HAL_USE_SDC TRUE #else #define HAL_USE_SDC FALSE diff --git a/firmware/baseband/sd_over_usb/diskio.c b/firmware/baseband/sd_over_usb/diskio.c new file mode 100644 index 000000000..2fcbcfd99 --- /dev/null +++ b/firmware/baseband/sd_over_usb/diskio.c @@ -0,0 +1,12 @@ +#include "diskio.h" + +#include "ch.h" +#include "hal.h" + +uint32_t get_capacity(void) { + return mmcsdGetCardCapacity(&SDCD1); +} + +bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n) { + return sdcRead(&SDCD1, startblk, buf, n); +} diff --git a/firmware/baseband/sd_over_usb/diskio.h b/firmware/baseband/sd_over_usb/diskio.h new file mode 100644 index 000000000..5bfe9b308 --- /dev/null +++ b/firmware/baseband/sd_over_usb/diskio.h @@ -0,0 +1,10 @@ +#ifndef __DISKIO_H__ +#define __DISKIO_H__ + +#include +#include + +uint32_t get_capacity(void); +bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n); + +#endif /* __DISKIO_H__ */ \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/hackrf_core.c b/firmware/baseband/sd_over_usb/hackrf_core.c new file mode 100644 index 000000000..73d91a4b4 --- /dev/null +++ b/firmware/baseband/sd_over_usb/hackrf_core.c @@ -0,0 +1,1089 @@ +/* + * Copyright 2012-2022 Great Scott Gadgets + * Copyright 2012 Jared Boone + * Copyright 2013 Benjamin Vernoux + * + * This file is part of HackRF. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "hackrf_core.h" +#include "hackrf_ui.h" +#include "sgpio.h" +#include "si5351c.h" +#include "spi_ssp.h" +#include "max283x.h" +#include "max5864.h" +#include "max5864_target.h" +#include "w25q80bv.h" +#include "w25q80bv_target.h" +#include "i2c_bus.h" +#include "i2c_lpc.h" +#include "cpld_jtag.h" +#include "platform_detect.h" +#include "clkin.h" +#include +#include +#include +#include + +#ifdef HACKRF_ONE + #include "portapack.h" +#endif + +#include "gpio_lpc.h" + +/* GPIO Output PinMux */ +static struct gpio_t gpio_led[] = { + GPIO(2, 1), + GPIO(2, 2), + GPIO(2, 8), +#ifdef RAD1O + GPIO(5, 26), +#endif +}; + +// clang-format off +static struct gpio_t gpio_1v8_enable = GPIO(3, 6); + +/* MAX283x GPIO (XCVR_CTL) PinMux */ +static struct gpio_t gpio_max283x_select = GPIO(0, 15); + +/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */ +static struct gpio_t gpio_max5864_select = GPIO(2, 7); + +/* RFFC5071 GPIO serial interface PinMux */ +// #ifdef RAD1O +// static struct gpio_t gpio_rffc5072_select = GPIO(2, 13); +// static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6); +// static struct gpio_t gpio_rffc5072_data = GPIO(3, 3); +// static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14); +// #endif + +/* RF supply (VAA) control */ +#ifdef HACKRF_ONE +static struct gpio_t gpio_vaa_disable = GPIO(2, 9); +#endif +#ifdef RAD1O +static struct gpio_t gpio_vaa_enable = GPIO(2, 9); +#endif + +static struct gpio_t gpio_w25q80bv_hold = GPIO(1, 14); +static struct gpio_t gpio_w25q80bv_wp = GPIO(1, 15); +static struct gpio_t gpio_w25q80bv_select = GPIO(5, 11); + +/* RF switch control */ +#ifdef HACKRF_ONE +static struct gpio_t gpio_hp = GPIO(2, 0); +static struct gpio_t gpio_lp = GPIO(2, 10); +static struct gpio_t gpio_tx_mix_bp = GPIO(2, 11); +static struct gpio_t gpio_no_mix_bypass = GPIO(1, 0); +static struct gpio_t gpio_rx_mix_bp = GPIO(2, 12); +static struct gpio_t gpio_tx_amp = GPIO(2, 15); +static struct gpio_t gpio_tx = GPIO(5, 15); +static struct gpio_t gpio_mix_bypass = GPIO(5, 16); +static struct gpio_t gpio_rx = GPIO(5, 5); +static struct gpio_t gpio_no_tx_amp_pwr = GPIO(3, 5); +static struct gpio_t gpio_amp_bypass = GPIO(0, 14); +static struct gpio_t gpio_rx_amp = GPIO(1, 11); +static struct gpio_t gpio_no_rx_amp_pwr = GPIO(1, 12); +#endif +#ifdef RAD1O +static struct gpio_t gpio_tx_rx_n = GPIO(1, 11); +static struct gpio_t gpio_tx_rx = GPIO(0, 14); +static struct gpio_t gpio_by_mix = GPIO(1, 12); +static struct gpio_t gpio_by_mix_n = GPIO(2, 10); +static struct gpio_t gpio_by_amp = GPIO(1, 0); +static struct gpio_t gpio_by_amp_n = GPIO(5, 5); +static struct gpio_t gpio_mixer_en = GPIO(5, 16); +static struct gpio_t gpio_low_high_filt = GPIO(2, 11); +static struct gpio_t gpio_low_high_filt_n = GPIO(2, 12); +static struct gpio_t gpio_tx_amp = GPIO(2, 15); +static struct gpio_t gpio_rx_lna = GPIO(5, 15); +#endif + +/* CPLD JTAG interface GPIO pins */ +static struct gpio_t gpio_cpld_tdo = GPIO(5, 18); +static struct gpio_t gpio_cpld_tck = GPIO(3, 0); +#if (defined HACKRF_ONE || defined RAD1O) +static struct gpio_t gpio_cpld_tms = GPIO(3, 4); +static struct gpio_t gpio_cpld_tdi = GPIO(3, 1); +#else +static struct gpio_t gpio_cpld_tms = GPIO(3, 1); +static struct gpio_t gpio_cpld_tdi = GPIO(3, 4); +#endif + +#ifdef HACKRF_ONE +static struct gpio_t gpio_cpld_pp_tms = GPIO(1, 1); +static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8); +#endif + +/* other CPLD interface GPIO pins */ +static struct gpio_t gpio_hw_sync_enable = GPIO(5, 12); +static struct gpio_t gpio_q_invert = GPIO(0, 13); + +/* HackRF One r9 */ +#ifdef HACKRF_ONE +static struct gpio_t gpio_h1r9_rx = GPIO(0, 7); +static struct gpio_t gpio_h1r9_1v8_enable = GPIO(2, 9); +static struct gpio_t gpio_h1r9_vaa_disable = GPIO(3, 6); +static struct gpio_t gpio_h1r9_hw_sync_enable = GPIO(5, 5); +#endif +// clang-format on + +i2c_bus_t i2c0 = { + .obj = (void*) I2C0_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + +i2c_bus_t i2c1 = { + .obj = (void*) I2C1_BASE, + .start = i2c_lpc_start, + .stop = i2c_lpc_stop, + .transfer = i2c_lpc_transfer, +}; + +// const i2c_lpc_config_t i2c_config_si5351c_slow_clock = { +// .duty_cycle_count = 15, +// }; + +const i2c_lpc_config_t i2c_config_si5351c_fast_clock = { + .duty_cycle_count = 255, +}; + +si5351c_driver_t clock_gen = { + .bus = &i2c0, + .i2c_address = 0x60, +}; + +const ssp_config_t ssp_config_max283x = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .data_bits = SSP_DATA_16BITS, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, + .gpio_select = &gpio_max283x_select, +}; + +const ssp_config_t ssp_config_max5864 = { + /* FIXME speed up once everything is working reliably */ + /* + // Freq About 0.0498MHz / 49.8KHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + const uint8_t serial_clock_rate = 32; + const uint8_t clock_prescale_rate = 128; + */ + // Freq About 4.857MHz => Freq = PCLK / (CPSDVSR * [SCR+1]) with PCLK=PLL1=204MHz + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 21, + .clock_prescale_rate = 2, + .gpio_select = &gpio_max5864_select, +}; + +spi_bus_t spi_bus_ssp1 = { + .obj = (void*) SSP1_BASE, + .config = &ssp_config_max5864, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + +max283x_driver_t max283x = {}; + +max5864_driver_t max5864 = { + .bus = &spi_bus_ssp1, + .target_init = max5864_target_init, +}; + +const ssp_config_t ssp_config_w25q80bv = { + .data_bits = SSP_DATA_8BITS, + .serial_clock_rate = 2, + .clock_prescale_rate = 2, + .gpio_select = &gpio_w25q80bv_select, +}; + +spi_bus_t spi_bus_ssp0 = { + .obj = (void*) SSP0_BASE, + .config = &ssp_config_w25q80bv, + .start = spi_ssp_start, + .stop = spi_ssp_stop, + .transfer = spi_ssp_transfer, + .transfer_gather = spi_ssp_transfer_gather, +}; + +w25q80bv_driver_t spi_flash = { + .bus = &spi_bus_ssp0, + .gpio_hold = &gpio_w25q80bv_hold, + .gpio_wp = &gpio_w25q80bv_wp, + .target_init = w25q80bv_target_init, +}; + +sgpio_config_t sgpio_config = { + .gpio_q_invert = &gpio_q_invert, + .gpio_hw_sync_enable = &gpio_hw_sync_enable, + .slice_mode_multislice = true, +}; + +rf_path_t rf_path = { + .switchctrl = 0, +#ifdef HACKRF_ONE + .gpio_hp = &gpio_hp, + .gpio_lp = &gpio_lp, + .gpio_tx_mix_bp = &gpio_tx_mix_bp, + .gpio_no_mix_bypass = &gpio_no_mix_bypass, + .gpio_rx_mix_bp = &gpio_rx_mix_bp, + .gpio_tx_amp = &gpio_tx_amp, + .gpio_tx = &gpio_tx, + .gpio_mix_bypass = &gpio_mix_bypass, + .gpio_rx = &gpio_rx, + .gpio_no_tx_amp_pwr = &gpio_no_tx_amp_pwr, + .gpio_amp_bypass = &gpio_amp_bypass, + .gpio_rx_amp = &gpio_rx_amp, + .gpio_no_rx_amp_pwr = &gpio_no_rx_amp_pwr, +#endif +#ifdef RAD1O + .gpio_tx_rx_n = &gpio_tx_rx_n, + .gpio_tx_rx = &gpio_tx_rx, + .gpio_by_mix = &gpio_by_mix, + .gpio_by_mix_n = &gpio_by_mix_n, + .gpio_by_amp = &gpio_by_amp, + .gpio_by_amp_n = &gpio_by_amp_n, + .gpio_mixer_en = &gpio_mixer_en, + .gpio_low_high_filt = &gpio_low_high_filt, + .gpio_low_high_filt_n = &gpio_low_high_filt_n, + .gpio_tx_amp = &gpio_tx_amp, + .gpio_rx_lna = &gpio_rx_lna, +#endif +}; + +jtag_gpio_t jtag_gpio_cpld = { + .gpio_tms = &gpio_cpld_tms, + .gpio_tck = &gpio_cpld_tck, + .gpio_tdi = &gpio_cpld_tdi, + .gpio_tdo = &gpio_cpld_tdo, +#ifdef HACKRF_ONE + .gpio_pp_tms = &gpio_cpld_pp_tms, + .gpio_pp_tdo = &gpio_cpld_pp_tdo, +#endif +}; + +jtag_t jtag_cpld = { + .gpio = &jtag_gpio_cpld, +}; + +void delay(uint32_t duration) +{ + uint32_t i; + + for (i = 0; i < duration; i++) { + __asm__("nop"); + } +} + +void delay_us_at_mhz(uint32_t us, uint32_t mhz) +{ + // The loop below takes 3 cycles per iteration. + uint32_t loop_iterations = (us * mhz) / 3; + asm volatile("start%=:\n" + " subs %[ITERATIONS], #1\n" // 1 cycle + " bpl start%=\n" // 2 cycles + : + : [ITERATIONS] "r"(loop_iterations)); +} + +/* GCD algo from wikipedia */ +/* http://en.wikipedia.org/wiki/Greatest_common_divisor */ +static uint32_t gcd(uint32_t u, uint32_t v) +{ + int s; + + if (!u || !v) { + return u | v; + } + + for (s = 0; !((u | v) & 1); s++) { + u >>= 1; + v >>= 1; + } + + while (!(u & 1)) { + u >>= 1; + } + + do { + while (!(v & 1)) { + v >>= 1; + } + + if (u > v) { + uint32_t t; + t = v; + v = u; + u = t; + } + + v = v - u; + } while (v); + + return u << s; +} + +bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom) +{ + const uint64_t VCO_FREQ = 800 * 1000 * 1000; /* 800 MHz */ + uint32_t MSx_P1, MSx_P2, MSx_P3; + uint32_t a, b, c; + uint32_t rem; + + hackrf_ui()->set_sample_rate(rate_num / 2); + + /* Find best config */ + a = (VCO_FREQ * rate_denom) / rate_num; + + rem = (VCO_FREQ * rate_denom) - (a * rate_num); + + if (!rem) { + /* Integer mode */ + b = 0; + c = 1; + } else { + /* Fractional */ + uint32_t g = gcd(rem, rate_num); + rem /= g; + rate_num /= g; + + if (rate_num < (1 << 20)) { + /* Perfect match */ + b = rem; + c = rate_num; + } else { + /* Approximate */ + c = (1 << 20) - 1; + b = ((uint64_t) c * (uint64_t) rem) / rate_num; + + g = gcd(b, c); + b /= g; + c /= g; + } + } + + bool streaming = sgpio_cpld_stream_is_enabled(&sgpio_config); + + if (streaming) { + sgpio_cpld_stream_disable(&sgpio_config); + } + + /* Can we enable integer mode ? */ + if (a & 0x1 || b) { + si5351c_set_int_mode(&clock_gen, 0, 0); + } else { + si5351c_set_int_mode(&clock_gen, 0, 1); + } + + /* Final MS values */ + MSx_P1 = 128 * a + (128 * b / c) - 512; + MSx_P2 = (128 * b) % c; + MSx_P3 = c; + + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* + * On HackRF One r9 all sample clocks are externally derived + * from MS1/CLK1 operating at twice the sample rate. + */ + si5351c_configure_multisynth(&clock_gen, 1, MSx_P1, MSx_P2, MSx_P3, 0); + } else { + /* + * On other platforms the clock generator produces three + * different sample clocks, all derived from multisynth 0. + */ + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1); + + /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ + si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter + + /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ + si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter + } + + if (streaming) { + sgpio_cpld_stream_enable(&sgpio_config); + } + + return true; +} + +bool sample_rate_set(const uint32_t sample_rate_hz) +{ + uint32_t p1 = 4608; + uint32_t p2 = 0; + uint32_t p3 = 0; + + switch (sample_rate_hz) { + case 8000000: + p1 = SI_INTDIV(50); // 800MHz / 50 = 16 MHz (SGPIO), 8 MHz (codec) + break; + + case 9216000: + // 43.40277777777778: a = 43; b = 29; c = 72 + p1 = 5043; + p2 = 40; + p3 = 72; + break; + + case 10000000: + p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec) + break; + + case 12288000: + // 32.552083333333336: a = 32; b = 159; c = 288 + p1 = 3654; + p2 = 192; + p3 = 288; + break; + + case 12500000: + p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec) + break; + + case 16000000: + p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec) + break; + + case 18432000: + // 21.70138888889: a = 21; b = 101; c = 144 + p1 = 2265; + p2 = 112; + p3 = 144; + break; + + case 20000000: + p1 = SI_INTDIV(20); // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec) + break; + + default: + return false; + } + + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* + * On HackRF One r9 all sample clocks are externally derived + * from MS1/CLK1 operating at twice the sample rate. + */ + si5351c_configure_multisynth(&clock_gen, 1, p1, p2, p3, 0); + } else { + /* + * On other platforms the clock generator produces three + * different sample clocks, all derived from multisynth 0. + */ + /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ + si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); + + /* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ + si5351c_configure_multisynth( + &clock_gen, + 1, + p1, + 0, + 1, + 0); //p1 doesn't matter + + /* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */ + si5351c_configure_multisynth( + &clock_gen, + 2, + p1, + 0, + 1, + 0); //p1 doesn't matter + } + + return true; +} + +bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) +{ + uint32_t bandwidth_hz_real; + bandwidth_hz_real = max283x_set_lpf_bandwidth(&max283x, bandwidth_hz); + + if (bandwidth_hz_real) { + hackrf_ui()->set_filter_bw(bandwidth_hz_real); + } + + return bandwidth_hz_real != 0; +} + +/* +Configure PLL1 (Main MCU Clock) to max speed (204MHz). +Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. +This function shall be called after cpu_clock_init(). +*/ +static void cpu_clock_pll1_max_speed(void) +{ + uint32_t reg_val; + + /* This function implements the sequence recommended in: + * UM10503 Rev 2.4 (Aug 2018), section 13.2.1.1, page 167. */ + + /* 1. Select the IRC as BASE_M4_CLK source. */ + reg_val = CGU_BASE_M4_CLK; + reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; + reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1); + CGU_BASE_M4_CLK = reg_val; + + /* 2. Enable the crystal oscillator. */ + CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_ENABLE_MASK; + + /* 3. Wait 250us. */ + delay_us_at_mhz(250, 12); + + /* 4. Set the AUTOBLOCK bit. */ + CGU_PLL1_CTRL |= CGU_PLL1_CTRL_AUTOBLOCK(1); + + /* 5. Reconfigure PLL1 to produce the final output frequency, with the + * crystal oscillator as clock source. */ + reg_val = CGU_PLL1_CTRL; + // clang-format off + reg_val &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | + CGU_PLL1_CTRL_PD_MASK | + CGU_PLL1_CTRL_FBSEL_MASK | + CGU_PLL1_CTRL_BYPASS_MASK | + CGU_PLL1_CTRL_DIRECT_MASK | + CGU_PLL1_CTRL_PSEL_MASK | + CGU_PLL1_CTRL_MSEL_MASK | + CGU_PLL1_CTRL_NSEL_MASK ); + /* Set PLL1 up to 12MHz * 17 = 204MHz. + * Direct mode: FCLKOUT = FCCO = M*(FCLKIN/N) */ + reg_val |= CGU_PLL1_CTRL_CLK_SEL(CGU_SRC_XTAL) | + CGU_PLL1_CTRL_PSEL(0) | + CGU_PLL1_CTRL_NSEL(0) | + CGU_PLL1_CTRL_MSEL(16) | + CGU_PLL1_CTRL_FBSEL(0) | + CGU_PLL1_CTRL_DIRECT(1); + // clang-format on + CGU_PLL1_CTRL = reg_val; + + /* 6. Wait for PLL1 to lock. */ + while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)) {} + + /* 7. Set the PLL1 P-divider to divide by 2 (DIRECT=0, PSEL=0). */ + CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_DIRECT_MASK; + + /* 8. Select PLL1 as BASE_M4_CLK source. */ + reg_val = CGU_BASE_M4_CLK; + reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; + reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_PLL1); + CGU_BASE_M4_CLK = reg_val; + + /* 9. Wait 50us. */ + delay_us_at_mhz(50, 102); + + /* 10. Set the PLL1 P-divider to direct output mode (DIRECT=1). */ + CGU_PLL1_CTRL |= CGU_PLL1_CTRL_DIRECT_MASK; +} + +/* clock startup for LPC4320 configure PLL1 to max speed (204MHz). +Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */ +void cpu_clock_init(void) +{ + /* use IRC as clock source for APB1 (including I2C0) */ + CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_IRC); + + /* use IRC as clock source for APB3 */ + CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_IRC); + + i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + + si5351c_init(&clock_gen); + si5351c_disable_all_outputs(&clock_gen); + si5351c_disable_oeb_pin_control(&clock_gen); + si5351c_power_down_all_clocks(&clock_gen); + si5351c_set_crystal_configuration(&clock_gen); + si5351c_enable_xo_and_ms_fanout(&clock_gen); + si5351c_configure_pll_sources(&clock_gen); + si5351c_configure_pll_multisynth(&clock_gen); + + /* + * Clocks on HackRF One r9: + * CLK0 -> MAX5864/CPLD/SGPIO (sample clocks) + * CLK1 -> RFFC5072/MAX2839 + * CLK2 -> External Clock Output/LPC43xx (power down at boot) + * + * Clocks on other platforms: + * CLK0 -> MAX5864/CPLD + * CLK1 -> CPLD + * CLK2 -> SGPIO + * CLK3 -> External Clock Output (power down at boot) + * CLK4 -> RFFC5072 (MAX2837 on rad1o) + * CLK5 -> MAX2837 (MAX2871 on rad1o) + * CLK6 -> none + * CLK7 -> LPC43xx (uses a 12MHz crystal by default) + */ + + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + /* MS0/CLK0 is the reference for both RFFC5071 and MAX2839. */ + si5351c_configure_multisynth( + &clock_gen, + 0, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + } else { + /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ + si5351c_configure_multisynth( + &clock_gen, + 4, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + /* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ + si5351c_configure_multisynth( + &clock_gen, + 5, + 20 * 128 - 512, + 0, + 1, + 0); /* 800/20 = 40MHz */ + } + + /* MS6/CLK6 is unused. */ + /* MS7/CLK7 is unused. */ + + /* Set to 10 MHz, the common rate between Jawbreaker and HackRF One. */ + sample_rate_set(10000000); + + si5351c_set_clock_source(&clock_gen, PLL_SOURCE_XTAL); + // soft reset + si5351c_reset_pll(&clock_gen); + si5351c_enable_clock_outputs(&clock_gen); + + //FIXME disable I2C + /* Kick I2C0 down to 400kHz when we switch over to APB1 clock = 204MHz */ + i2c_bus_start(clock_gen.bus, &i2c_config_si5351c_fast_clock); + + /* + * 12MHz clock is entering LPC XTAL1/OSC input now. + * On HackRF One and Jawbreaker, there is a 12 MHz crystal at the LPC. + * Set up PLL1 to run from XTAL1 input. + */ + + //FIXME a lot of the details here should be in a CGU driver + + /* set xtal oscillator to low frequency mode */ + CGU_XTAL_OSC_CTRL &= ~CGU_XTAL_OSC_CTRL_HF_MASK; + + cpu_clock_pll1_max_speed(); + + /* use XTAL_OSC as clock source for APB1 */ + CGU_BASE_APB1_CLK = + CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL); + + /* use XTAL_OSC as clock source for APB3 */ + CGU_BASE_APB3_CLK = + CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL); + + /* use XTAL_OSC as clock source for PLL0USB */ + CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_AUTOBLOCK(1) | + CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL); + while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {} + + /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */ + /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */ + CGU_PLL0USB_MDIV = 0x06167FFA; + CGU_PLL0USB_NP_DIV = 0x00302062; + CGU_PLL0USB_CTRL |= + (CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_DIRECTI(1) | + CGU_PLL0USB_CTRL_DIRECTO(1) | CGU_PLL0USB_CTRL_CLKEN(1)); + + /* power on PLL0USB and wait until stable */ + CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK; + while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {} + + /* use PLL0USB as clock source for USB0 */ + CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) | + CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB); + + /* Switch peripheral clock over to use PLL1 (204MHz) */ + CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) | + CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1); + + /* Switch APB1 clock over to use PLL1 (204MHz) */ + CGU_BASE_APB1_CLK = + CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1); + + /* Switch APB3 clock over to use PLL1 (204MHz) */ + CGU_BASE_APB3_CLK = + CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1); + + CGU_BASE_SSP0_CLK = + CGU_BASE_SSP0_CLK_AUTOBLOCK(1) | CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1); + + CGU_BASE_SSP1_CLK = + CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); + + // \/ breaks below + +#if (defined JAWBREAKER || defined HACKRF_ONE) + /* Disable unused clocks */ + /* Start with PLLs */ + CGU_PLL0AUDIO_CTRL = CGU_PLL0AUDIO_CTRL_PD(1); + + /* Dividers */ + CGU_IDIVA_CTRL = CGU_IDIVA_CTRL_PD(1); + CGU_IDIVB_CTRL = CGU_IDIVB_CTRL_PD(1); + CGU_IDIVC_CTRL = CGU_IDIVC_CTRL_PD(1); + CGU_IDIVD_CTRL = CGU_IDIVD_CTRL_PD(1); + CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1); + + /* Base clocks */ + CGU_BASE_SPIFI_CLK = CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */ + CGU_BASE_USB1_CLK = CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */ + CGU_BASE_PHY_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1); + CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_CLK_PD(1); + CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1); + CGU_BASE_VADC_CLK = CGU_BASE_VADC_CLK_PD(1); + //CGU_BASE_SDIO_CLK = CGU_BASE_SDIO_CLK_PD(1); // << BREAKS + CGU_BASE_UART0_CLK = CGU_BASE_UART0_CLK_PD(1); + CGU_BASE_UART1_CLK = CGU_BASE_UART1_CLK_PD(1); + CGU_BASE_UART2_CLK = CGU_BASE_UART2_CLK_PD(1); + CGU_BASE_UART3_CLK = CGU_BASE_UART3_CLK_PD(1); + CGU_BASE_OUT_CLK = CGU_BASE_OUT_CLK_PD(1); + CGU_BASE_AUDIO_CLK = CGU_BASE_AUDIO_CLK_PD(1); + CGU_BASE_CGU_OUT0_CLK = CGU_BASE_CGU_OUT0_CLK_PD(1); + CGU_BASE_CGU_OUT1_CLK = CGU_BASE_CGU_OUT1_CLK_PD(1); + +// /\ breaks above + + + /* Disable unused peripheral clocks */ + CCU1_CLK_APB1_CAN1_CFG = 0; + CCU1_CLK_APB1_I2S_CFG = 0; + CCU1_CLK_APB1_MOTOCONPWM_CFG = 0; + CCU1_CLK_APB3_ADC0_CFG = 0; + CCU1_CLK_APB3_ADC1_CFG = 0; + CCU1_CLK_APB3_CAN0_CFG = 0; + CCU1_CLK_APB3_DAC_CFG = 0; + //CCU1_CLK_M4_DMA_CFG = 0; + CCU1_CLK_M4_EMC_CFG = 0; + CCU1_CLK_M4_EMCDIV_CFG = 0; + CCU1_CLK_M4_ETHERNET_CFG = 0; + CCU1_CLK_M4_LCD_CFG = 0; + CCU1_CLK_M4_QEI_CFG = 0; + CCU1_CLK_M4_RITIMER_CFG = 0; + // CCU1_CLK_M4_SCT_CFG = 0; + //CCU1_CLK_M4_SDIO_CFG = 0; // << BREAKS + CCU1_CLK_M4_SPIFI_CFG = 0; + CCU1_CLK_M4_TIMER0_CFG = 0; + //CCU1_CLK_M4_TIMER1_CFG = 0; + //CCU1_CLK_M4_TIMER2_CFG = 0; + CCU1_CLK_M4_TIMER3_CFG = 0; + CCU1_CLK_M4_UART1_CFG = 0; + CCU1_CLK_M4_USART0_CFG = 0; + CCU1_CLK_M4_USART2_CFG = 0; + CCU1_CLK_M4_USART3_CFG = 0; + CCU1_CLK_M4_USB1_CFG = 0; + CCU1_CLK_M4_VADC_CFG = 0; + // CCU1_CLK_SPIFI_CFG = 0; + // CCU1_CLK_USB1_CFG = 0; + // CCU1_CLK_VADC_CFG = 0; + // CCU2_CLK_APB0_UART1_CFG = 0; + // CCU2_CLK_APB0_USART0_CFG = 0; + // CCU2_CLK_APB2_USART2_CFG = 0; + // CCU2_CLK_APB2_USART3_CFG = 0; + // CCU2_CLK_APLL_CFG = 0; + // CCU2_CLK_SDIO_CFG = 0; +#endif + + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + clkin_detect_init(); + } +} + +clock_source_t activate_best_clock_source(void) +{ +#ifdef HACKRF_ONE + /* Ensure PortaPack reference oscillator is off while checking for external clock input. */ + if (portapack_reference_oscillator && portapack()) { + portapack_reference_oscillator(false); + } +#endif + + clock_source_t source = CLOCK_SOURCE_HACKRF; + + /* Check for external clock input. */ + if (si5351c_clkin_signal_valid(&clock_gen)) { + source = CLOCK_SOURCE_EXTERNAL; + } else { +#ifdef HACKRF_ONE + /* Enable PortaPack reference oscillator (if present), and check for valid clock. */ + if (portapack_reference_oscillator && portapack()) { + portapack_reference_oscillator(true); + delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */ + if (si5351c_clkin_signal_valid(&clock_gen)) { + source = CLOCK_SOURCE_PORTAPACK; + } else { + portapack_reference_oscillator(false); + } + } +#endif + /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ + } + + si5351c_set_clock_source( + &clock_gen, + (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); + hackrf_ui()->set_clock_source(source); + return source; +} + +void ssp1_set_mode_max283x(void) +{ + spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); +} + +void ssp1_set_mode_max5864(void) +{ + spi_bus_start(max5864.bus, &ssp_config_max5864); +} + +void pin_setup(void) +{ + /* Configure all GPIO as Input (safe state) */ + //gpio_init(); + + /* TDI and TMS pull-ups are required in all JTAG-compliant devices. + * + * The HackRF CPLD is always present, so let the CPLD pull up its TDI and TMS. + * + * The PortaPack may not be present, so pull up the PortaPack TMS pin from the + * microcontroller. + * + * TCK is recommended to be held low, so use microcontroller pull-down. + * + * TDO is undriven except when in Shift-IR or Shift-DR phases. + * Use the microcontroller to pull down to keep from floating. + * + * LPC43xx pull-up and pull-down resistors are approximately 53K. + */ +#ifdef HACKRF_ONE + scu_pinmux(SCU_PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); +#endif + scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + + /* Configure SCU Pin Mux as GPIO */ + scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL); + scu_pinmux(SCU_PINMUX_LED2, SCU_GPIO_NOPULL); + scu_pinmux(SCU_PINMUX_LED3, SCU_GPIO_NOPULL); +#ifdef RAD1O + scu_pinmux(SCU_PINMUX_LED4, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION4); +#endif + + /* Configure USB indicators */ +#ifdef JAWBREAKER + scu_pinmux(SCU_PINMUX_USB_LED0, SCU_CONF_FUNCTION3); + scu_pinmux(SCU_PINMUX_USB_LED1, SCU_CONF_FUNCTION3); +#endif + + gpio_output(&gpio_led[0]); + gpio_output(&gpio_led[1]); + gpio_output(&gpio_led[2]); +#ifdef RAD1O + gpio_output(&gpio_led[3]); +#endif + + disable_1v8_power(); + if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#ifdef HACKRF_ONE + gpio_output(&gpio_h1r9_1v8_enable); + scu_pinmux(SCU_H1R9_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); +#endif + } else { + gpio_output(&gpio_1v8_enable); + scu_pinmux(SCU_PINMUX_EN1V8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); + } + +#ifdef HACKRF_ONE + /* Safe state: start with VAA turned off: */ + disable_rf_power(); + + /* Configure RF power supply (VAA) switch control signal as output */ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_output(&gpio_h1r9_vaa_disable); + } else { + gpio_output(&gpio_vaa_disable); + } +#endif + +#ifdef RAD1O + /* Safe state: start with VAA turned off: */ + disable_rf_power(); + + /* Configure RF power supply (VAA) switch control signal as output */ + gpio_output(&gpio_vaa_enable); + + /* Disable unused clock outputs. They generate noise. */ + scu_pinmux(CLK0, SCU_CLK_IN | SCU_CONF_FUNCTION7); + scu_pinmux(CLK2, SCU_CLK_IN | SCU_CONF_FUNCTION7); + + scu_pinmux(SCU_PINMUX_GPIO3_10, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + scu_pinmux(SCU_PINMUX_GPIO3_11, SCU_GPIO_PDN | SCU_CONF_FUNCTION0); + +#endif + + /* enable input on SCL and SDA pins */ + SCU_SFSI2C0 = SCU_I2C0_NOMINAL; + + spi_bus_start(&spi_bus_ssp1, &ssp_config_max283x); + + mixer_bus_setup(&mixer); + +#ifdef HACKRF_ONE + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + rf_path.gpio_rx = &gpio_h1r9_rx; + sgpio_config.gpio_hw_sync_enable = &gpio_h1r9_hw_sync_enable; + } +#endif + rf_path_pin_setup(&rf_path); + + /* Configure external clock in */ + scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); + + sgpio_configure_pin_functions(&sgpio_config); +} + +void enable_1v8_power(void) +{ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#ifdef HACKRF_ONE + gpio_set(&gpio_h1r9_1v8_enable); +#endif + } else { + gpio_set(&gpio_1v8_enable); + } +} + +void disable_1v8_power(void) +{ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { +#ifdef HACKRF_ONE + gpio_clear(&gpio_h1r9_1v8_enable); +#endif + } else { + gpio_clear(&gpio_1v8_enable); + } +} + +#ifdef HACKRF_ONE +void enable_rf_power(void) +{ + uint32_t i; + + /* many short pulses to avoid one big voltage glitch */ + for (i = 0; i < 1000; i++) { + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_set(&gpio_h1r9_vaa_disable); + gpio_clear(&gpio_h1r9_vaa_disable); + } else { + gpio_set(&gpio_vaa_disable); + gpio_clear(&gpio_vaa_disable); + } + } +} + +void disable_rf_power(void) +{ + if (detected_platform() == BOARD_ID_HACKRF1_R9) { + gpio_set(&gpio_h1r9_vaa_disable); + } else { + gpio_set(&gpio_vaa_disable); + } +} +#endif + +#ifdef RAD1O +void enable_rf_power(void) +{ + gpio_set(&gpio_vaa_enable); + + /* Let the voltage stabilize */ + delay(1000000); +} + +void disable_rf_power(void) +{ + gpio_clear(&gpio_vaa_enable); +} +#endif + +void led_on(const led_t led) +{ + gpio_set(&gpio_led[led]); +} + +void led_off(const led_t led) +{ + gpio_clear(&gpio_led[led]); +} + +void led_toggle(const led_t led) +{ + gpio_toggle(&gpio_led[led]); +} + +void set_leds(const uint8_t state) +{ + int num_leds = 3; +#ifdef RAD1O + num_leds = 4; +#endif + for (int i = 0; i < num_leds; i++) { + gpio_write(&gpio_led[i], ((state >> i) & 1) == 1); + } +} + +void hw_sync_enable(const hw_sync_mode_t hw_sync_mode) +{ + gpio_write(sgpio_config.gpio_hw_sync_enable, hw_sync_mode == 1); +} + +void halt_and_flash(const uint32_t duration) +{ + /* blink LED1, LED2, and LED3 */ + while (1) { + led_on(LED1); + led_on(LED2); + led_on(LED3); + delay(duration); + led_off(LED1); + led_off(LED2); + led_off(LED3); + delay(duration); + } +} diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp index 9dec3bbcc..04fb8ee05 100644 --- a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp @@ -27,7 +27,6 @@ #include "debug.hpp" #include "portapack_shared_memory.hpp" -#include "event_m4.hpp" extern "C" { void start_usb(void); @@ -40,34 +39,22 @@ CH_IRQ_HANDLER(Vector60) { } } +//uint8_t buf[512]; + int main() { - //EventDispatcher event_dispatcher { std::make_unique() }; - //HALT_UNTIL_DEBUGGING(); + sdcStart(&SDCD1, nullptr); + if (sdcConnect(&SDCD1) == CH_FAILED) chDbgPanic("no sd card #1"); + + // memset(&buf[0], 0, 512); + // if (sdcRead(&SDCD1, 0, &buf[0], 1) == CH_FAILED) chDbgPanic("no sd card #2"); - //LPC_CGU->PLL0USB_CTRL.PD = 1; - //LPC_CGU->PLL0USB_CTRL.AUTOBLOCK = 1; - //LPC_CGU->PLL0USB_CTRL.CLK_SEL = 0x06; -// - //while (LPC_CGU->PLL0USB_STAT.LOCK) {} - // - //LPC_CGU->PLL0USB_MDIV = 0x06167FFA; // 0x71A7FAA; // - //LPC_CGU->PLL0USB_NP_DIV = 0x00302062; -// - ////LPC_CGU->PLL0USB_CTRL.PD |= 1; - //LPC_CGU->PLL0USB_CTRL.DIRECTI = 1; - //LPC_CGU->PLL0USB_CTRL.DIRECTO = 1; - //LPC_CGU->PLL0USB_CTRL.CLKEN = 1; -// - //LPC_CGU->PLL0USB_CTRL.PD = 0; -// - //while (!(LPC_CGU->PLL0USB_STAT.LOCK)) {} - ////chThdSleepMilliseconds(800); -// - //LPC_CGU->BASE_USB0_CLK.AUTOBLOCK = 1; - //LPC_CGU->BASE_USB0_CLK.CLK_SEL = 0x07; start_usb(); + + // memset(&buf[0], 0, 512); + // if (sdcRead(&SDCD1, 0, &buf[0], 1) == CH_FAILED) chDbgPanic("no sd card #3"); + //event_dispatcher.run(); while (true) { usb_transfer(); diff --git a/firmware/baseband/sd_over_usb/scsi.c b/firmware/baseband/sd_over_usb/scsi.c index 18397ecdc..1150bda25 100644 --- a/firmware/baseband/sd_over_usb/scsi.c +++ b/firmware/baseband/sd_over_usb/scsi.c @@ -1,210 +1,125 @@ #include "scsi.h" - +#include "diskio.h" #define HALT_UNTIL_DEBUGGING() \ while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \ __asm__ __volatile__("bkpt 1") -typedef struct { - uint8_t peripheral; - uint8_t removable; - uint8_t version; - uint8_t response_data_format; - uint8_t additional_length; - uint8_t sccstp; - uint8_t bqueetc; - uint8_t cmdque; - uint8_t vendorID[8]; - uint8_t productID[16]; - uint8_t productRev[4]; -} scsi_inquiry_response_t; +volatile bool usb_bulk_block_send = false; -static const scsi_inquiry_response_t default_scsi_inquiry_response = { - 0x00, /* direct access block device */ - 0x80, /* removable */ - 0x04, /* SPC-2 */ - 0x02, /* response data format */ - 0x20, /* response has 0x20 + 4 bytes */ - 0x00, - 0x00, - 0x00, - "Mayhem", - "Mass Storage", - {'v','1','.','6'} -}; +void usb_bulk_block_cb(void* user_data, unsigned int bytes_transferred) { + usb_bulk_block_send = true; -typedef struct { - uint32_t signature; - uint32_t tag; - uint32_t data_residue; - uint8_t status; -} __attribute__((packed)) msd_csw_t; - -#define MSD_CBW_SIGNATURE 0x43425355 -#define MSD_CSW_SIGNATURE 0x53425355 - -// void handle_inquiry_4(void* user_data, unsigned int bytes_transferred) { -// HALT_UNTIL_DEBUGGING(); -// } - -// void handle_inquiry_3(void* user_data, unsigned int bytes_transferred) -// { -// //msd_cbw_t *msd_cbw_data = (msd_cbw_t *)user_data; - -// //HALT_UNTIL_DEBUGGING(); - - -// } - - -volatile bool inquiry_stage_one_send = false; -void inquiry_cb(void* user_data, unsigned int bytes_transferred) -{ - inquiry_stage_one_send = true; + (void)user_data; + (void)bytes_transferred; } -void handle_inquiry(msd_cbw_t *msd_cbw_data) { - inquiry_stage_one_send = false; - memcpy(&usb_bulk_buffer[0], &default_scsi_inquiry_response, sizeof(scsi_inquiry_response_t)); +void usb_send_bulk(void* const data, const uint32_t maximum_length) { + usb_bulk_block_send = false; + usb_transfer_schedule_block( &usb_endpoint_bulk_in, - &usb_bulk_buffer[0], - sizeof(scsi_inquiry_response_t), - inquiry_cb, - msd_cbw_data); + data, + maximum_length, + usb_bulk_block_cb, + NULL); - while (!inquiry_stage_one_send); + while (!usb_bulk_block_send); +} +void usb_send_csw(msd_cbw_t *msd_cbw_data, uint8_t status) { msd_csw_t csw = { .signature = MSD_CSW_SIGNATURE, .tag = msd_cbw_data->tag, .data_residue = 0, - .status = 0 + .status = status }; - memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0x4000], - sizeof(msd_csw_t), - NULL, - NULL); - + memcpy(&usb_bulk_buffer[0], &csw, sizeof(msd_csw_t)); + usb_send_bulk(&usb_bulk_buffer[0], sizeof(msd_csw_t)); } -typedef struct { - uint8_t header[4]; - uint8_t blocknum[4]; - uint8_t blocklen[4]; -} scsi_read_format_capacities_response_t; +uint8_t handle_inquiry(msd_cbw_t *msd_cbw_data) { + (void)msd_cbw_data; -volatile bool capacities_stage_one_send = false; -void capacities_cb(void* user_data, unsigned int bytes_transferred) -{ - capacities_stage_one_send = true; + scsi_inquiry_response_t ret = { + 0x00, /* direct access block device */ + 0x80, /* removable */ + 0x00, //0x04, /* SPC-2 */ + 0x00, //0x02, /* response data format */ + 0x20, /* response has 0x20 + 4 bytes */ + 0x00, + 0x00, + 0x00, + "Mayhem", + "Portapack MSD", + {'v','1','.','6'} + }; + + memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_inquiry_response_t)); + usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_inquiry_response_t)); + + return 0; } -void read_format_capacities(msd_cbw_t *msd_cbw_data) { +uint8_t handle_inquiry_serial_number(msd_cbw_t *msd_cbw_data) { + (void)msd_cbw_data; + + scsi_unit_serial_number_inquiry_response_t ret = { + .peripheral = 0x00, + .page_code = 0x80, + .reserved = 0, + .page_length = 0x08, + .serialNumber = "Mayhem" + }; + + memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_unit_serial_number_inquiry_response_t)); + usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_unit_serial_number_inquiry_response_t)); + + return 0; +} + + +uint8_t read_format_capacities(msd_cbw_t *msd_cbw_data) { uint16_t len = msd_cbw_data->cmd_data[7] << 8 | msd_cbw_data->cmd_data[8]; if (len != 0) { + size_t num_blocks = get_capacity(); + scsi_read_format_capacities_response_t ret = { .header = {0, 0, 0, 1 * 8 /* num_entries * 8 */}, - .blocknum = {0, 0, (1024 * 8) >> 8, 0}, // 32GB - .blocklen = {0b10 /* formated */, 0, (512) >> 8, 0} + .blocknum = {((num_blocks) >> 24)& 0xff, ((num_blocks) >> 16)& 0xff, ((num_blocks) >> 8)& 0xff, num_blocks & 0xff}, + .blocklen = {0b10 /* formated */, 0, (512) >> 8, 0}, + // .blocknum2 = {((num_blocks) >> 24)& 0xff, ((num_blocks) >> 16)& 0xff, ((num_blocks) >> 8)& 0xff, num_blocks & 0xff}, + // .blocklen2 = {0 /* formated */, 0, (512) >> 8, 0} }; - capacities_stage_one_send = false; memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_format_capacities_response_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0], - sizeof(scsi_inquiry_response_t), - capacities_cb, - msd_cbw_data); - - while (!capacities_stage_one_send); + usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_read_format_capacities_response_t)); } - - msd_csw_t csw = { - .signature = MSD_CSW_SIGNATURE, - .tag = msd_cbw_data->tag, - .data_residue = 0, - .status = 0 - }; - - memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0x4000], - sizeof(msd_csw_t), - NULL, - NULL); - + return 0; } -typedef struct { - uint32_t last_block_addr; - uint32_t block_size; -} scsi_read_capacity10_response_t; +uint8_t read_capacity10(msd_cbw_t *msd_cbw_data) { + (void)msd_cbw_data; -volatile bool capacity10_stage_one_send = false; -void capacity10_cb(void* user_data, unsigned int bytes_transferred) -{ - capacity10_stage_one_send = true; -} - -void read_capacity10(msd_cbw_t *msd_cbw_data) { - capacity10_stage_one_send = false; + size_t num_blocks = get_capacity(); scsi_read_capacity10_response_t ret = { - .last_block_addr = cpu_to_be32(8 * 1024 * 1024 - 1), + .last_block_addr = cpu_to_be32(num_blocks - 1), .block_size = cpu_to_be32(512) }; memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_capacity10_response_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0], - sizeof(scsi_read_capacity10_response_t), - capacity10_cb, - msd_cbw_data); - - while (!capacity10_stage_one_send); - - msd_csw_t csw = { - .signature = MSD_CSW_SIGNATURE, - .tag = msd_cbw_data->tag, - .data_residue = 0, - .status = 0 - }; - - memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0x4000], - sizeof(msd_csw_t), - NULL, - NULL); + usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_read_capacity10_response_t)); + return 0; } - -typedef struct { - uint8_t byte[18]; -} scsi_sense_response_t; - -volatile bool sense_stage_one_send = false; -void sense_cb(void* user_data, unsigned int bytes_transferred) -{ - sense_stage_one_send = true; -} - - -void request_sense(msd_cbw_t *msd_cbw_data) { - sense_stage_one_send = false; +uint8_t request_sense(msd_cbw_t *msd_cbw_data) { + (void)msd_cbw_data; scsi_sense_response_t ret = { .byte = { 0x70, 0, SCSI_SENSE_KEY_GOOD, 0, @@ -215,83 +130,28 @@ void request_sense(msd_cbw_t *msd_cbw_data) { }; memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_sense_response_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0], - sizeof(scsi_sense_response_t), - sense_cb, - msd_cbw_data); + usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_sense_response_t)); - while (!sense_stage_one_send); - - msd_csw_t csw = { - .signature = MSD_CSW_SIGNATURE, - .tag = msd_cbw_data->tag, - .data_residue = 0, - .status = 0 - }; - - memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0x4000], - sizeof(msd_csw_t), - NULL, - NULL); + return 0; } -typedef struct { - uint8_t byte[4]; -} scsi_mode_sense6_response_t; +uint8_t mode_sense6 (msd_cbw_t *msd_cbw_data) { + (void)msd_cbw_data; -volatile bool sense6_stage_one_send = false; -void sense6_cb(void* user_data, unsigned int bytes_transferred) -{ - sense6_stage_one_send = true; -} - -void mode_sense6 (msd_cbw_t *msd_cbw_data) { - sense6_stage_one_send = false; - - scsi_mode_sense6_response_t ret = { + scsi_mode_sense6_response_t ret = { .byte = { sizeof(scsi_mode_sense6_response_t) - 1, 0, - 0x01 << 7, // 0 for not write protected + 0, // 0x01 << 7, // 0 for not write protected 0 } }; memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_mode_sense6_response_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0], - sizeof(scsi_mode_sense6_response_t), - sense6_cb, - msd_cbw_data); + usb_send_bulk(&usb_bulk_buffer[0], sizeof(scsi_mode_sense6_response_t)); - while (!sense6_stage_one_send); - - msd_csw_t csw = { - .signature = MSD_CSW_SIGNATURE, - .tag = msd_cbw_data->tag, - .data_residue = 0, - .status = 0 - }; - - memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0x4000], - sizeof(msd_csw_t), - NULL, - NULL); + return 0; } -typedef struct { - uint32_t first_lba; - uint16_t blk_cnt; -} data_request_t; - static data_request_t decode_data_request(const uint8_t *cmd) { data_request_t req; @@ -307,122 +167,102 @@ static data_request_t decode_data_request(const uint8_t *cmd) { return req; } -volatile uint32_t read10_blocks_send = 0; -void read10_cb(void* user_data, unsigned int bytes_transferred) -{ - read10_blocks_send++; +uint8_t data_read10(msd_cbw_t *msd_cbw_data) { + data_request_t req = decode_data_request(msd_cbw_data->cmd_data); + + for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) { + read_block(req.first_lba + block_index, &usb_bulk_buffer[0], 1 /* n blocks */); + usb_send_bulk(&usb_bulk_buffer[0], 512); + } + + return 0; } +volatile uint32_t write10_blocks_send = 0; +void write10_cb(void* user_data, unsigned int bytes_transferred) +{ + write10_blocks_send++; + + (void)user_data; + (void)bytes_transferred; +} -void data_read10(msd_cbw_t *msd_cbw_data) { - read10_blocks_send = 0; +uint8_t data_write10(msd_cbw_t *msd_cbw_data) { + write10_blocks_send = 0; data_request_t req = decode_data_request(msd_cbw_data->cmd_data); for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) { - memset(&usb_bulk_buffer[0], 0, 512); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, + &usb_endpoint_bulk_out, &usb_bulk_buffer[0], 512, - read10_cb, + write10_cb, msd_cbw_data); - while (read10_blocks_send <= block_index); + while (write10_blocks_send <= block_index); + + //TODO: write to SD } - msd_csw_t csw = { - .signature = MSD_CSW_SIGNATURE, - .tag = msd_cbw_data->tag, - .data_residue = 0, - .status = 0 - }; - - memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0x4000], - sizeof(msd_csw_t), - NULL, - NULL); -} - - - - -void test_unit_ready(msd_cbw_t *msd_cbw_data) { - msd_csw_t csw = { - .signature = MSD_CSW_SIGNATURE, - .tag = msd_cbw_data->tag, - .data_residue = 0, - .status = 0 - }; - - memcpy(&usb_bulk_buffer[0x4000], &csw, sizeof(msd_csw_t)); - usb_transfer_schedule_block( - &usb_endpoint_bulk_in, - &usb_bulk_buffer[0x4000], - sizeof(msd_csw_t), - NULL, - NULL); + return 0; } void scsi_command(msd_cbw_t *msd_cbw_data) { + uint8_t status = 1; - switch (msd_cbw_data->cmd_data[0]) { - case SCSI_CMD_INQUIRY: - handle_inquiry(msd_cbw_data); + switch (msd_cbw_data->cmd_data[0]) { + case SCSI_CMD_INQUIRY: + //status = handle_inquiry(msd_cbw_data); + if ((msd_cbw_data->cmd_data[1] & 0b1) && msd_cbw_data->cmd_data[2] == 0x80) { + status = handle_inquiry_serial_number(msd_cbw_data); + } + else if ((msd_cbw_data->cmd_data[1] & 0b11) || msd_cbw_data->cmd_data[2] != 0) { + //TODO: implement sense + status = 1; + } + else { + status = handle_inquiry(msd_cbw_data); + } + break; - break; + case SCSI_CMD_REQUEST_SENSE: + status = request_sense(msd_cbw_data); + break; - case SCSI_CMD_REQUEST_SENSE: - request_sense(msd_cbw_data); - break; + case SCSI_CMD_READ_CAPACITY_10: + status = read_capacity10(msd_cbw_data); + break; - case SCSI_CMD_READ_CAPACITY_10: - read_capacity10(msd_cbw_data); - break; + case SCSI_CMD_READ_10: + status = data_read10(msd_cbw_data); + break; - case SCSI_CMD_READ_10: - data_read10(msd_cbw_data); - break; + case SCSI_CMD_WRITE_10: + status = data_write10(msd_cbw_data); + break; - /* - case SCSI_CMD_WRITE_10: - ret = data_read_write10(scsip, cmd); - break; -*/ - case SCSI_CMD_TEST_UNIT_READY: - test_unit_ready(msd_cbw_data); - break; + case SCSI_CMD_TEST_UNIT_READY: + status = 0; + break; - case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - test_unit_ready(msd_cbw_data); - // ret = cmd_ignored(scsip, cmd); - break; - - case SCSI_CMD_MODE_SENSE_6: - mode_sense6(msd_cbw_data); - break; - - case SCSI_CMD_READ_FORMAT_CAPACITIES: - read_format_capacities(msd_cbw_data); - break; - - case SCSI_CMD_VERIFY_10: - test_unit_ready(msd_cbw_data); - break; -/* - default: - ret = cmd_unhandled(scsip, cmd); - break; - */ - } - -// if (ret == SCSI_SUCCESS) -// set_sense_ok(scsip); + case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + status = 0; + break; + case SCSI_CMD_MODE_SENSE_6: + status = mode_sense6(msd_cbw_data); + break; + + case SCSI_CMD_READ_FORMAT_CAPACITIES: + status = read_format_capacities(msd_cbw_data); + break; + + case SCSI_CMD_VERIFY_10: + status = 0; + break; + } + usb_send_csw(msd_cbw_data, status); } \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/scsi.h b/firmware/baseband/sd_over_usb/scsi.h index 85dedd1a2..26ab04f67 100644 --- a/firmware/baseband/sd_over_usb/scsi.h +++ b/firmware/baseband/sd_over_usb/scsi.h @@ -13,6 +13,9 @@ #include "hackrf_core.h" #include "usb_bulk_buffer.h" +#define MSD_CBW_SIGNATURE 0x43425355 +#define MSD_CSW_SIGNATURE 0x53425355 + #define SCSI_CMD_TEST_UNIT_READY 0x00 #define SCSI_CMD_REQUEST_SENSE 0x03 #define SCSI_CMD_INQUIRY 0x12 @@ -71,6 +74,67 @@ typedef struct { uint8_t cmd_data[16]; } __attribute__((packed)) msd_cbw_t; +typedef struct { + uint8_t peripheral; + uint8_t removable; + uint8_t version; + uint8_t response_data_format; + uint8_t additional_length; + uint8_t sccstp; + uint8_t bqueetc; + uint8_t cmdque; + uint8_t vendorID[8]; + uint8_t productID[16]; + uint8_t productRev[4]; +} scsi_inquiry_response_t; + +typedef struct { + uint32_t signature; + uint32_t tag; + uint32_t data_residue; + uint8_t status; +} __attribute__((packed)) msd_csw_t; + +typedef struct { + uint8_t header[4]; + uint8_t blocknum[4]; + uint8_t blocklen[4]; +} scsi_read_format_capacities_response_t; + +typedef struct { + uint8_t header[4]; + uint8_t blocknum[4]; + uint8_t blocklen[4]; + uint8_t blocknum2[4]; + uint8_t blocklen2[4]; +} scsi_read_format_capacities_double_response_t; + +typedef struct { + uint32_t last_block_addr; + uint32_t block_size; +} scsi_read_capacity10_response_t; + +typedef struct { + uint8_t byte[18]; +} scsi_sense_response_t; + +typedef struct { + uint8_t byte[4]; +} scsi_mode_sense6_response_t; + +typedef struct { + uint32_t first_lba; + uint16_t blk_cnt; +} data_request_t; + +typedef struct { + uint8_t peripheral; + uint8_t page_code; + uint8_t reserved; + uint8_t page_length; + uint8_t serialNumber[8]; +} scsi_unit_serial_number_inquiry_response_t; + static inline uint16_t bswap_16(const uint16_t x) __attribute__ ((warn_unused_result)) __attribute__ ((const)) diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.c b/firmware/baseband/sd_over_usb/sd_over_usb.c index 5557d0ac7..64bd3c50d 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.c +++ b/firmware/baseband/sd_over_usb/sd_over_usb.c @@ -94,16 +94,16 @@ usb_request_status_t usb_vendor_request( { usb_request_status_t status = USB_REQUEST_STATUS_STALL; - volatile uint_fast8_t address = endpoint->address; + // volatile uint_fast8_t address = endpoint->address; volatile uint8_t request = endpoint->setup.request; - volatile uint32_t b = 0; + // volatile uint32_t b = 0; if (request == 25) { // unknown code return report_magic_scsi(endpoint, stage); } - b = request + (address << 16); - HALT_UNTIL_DEBUGGING(); + // b = request + (address << 16); + // HALT_UNTIL_DEBUGGING(); return status; @@ -115,16 +115,15 @@ usb_request_status_t usb_class_request( { usb_request_status_t status = USB_REQUEST_STATUS_STALL; - volatile uint_fast8_t address = endpoint->address; volatile uint8_t request = endpoint->setup.request; - volatile uint32_t b = 0; + // volatile uint32_t b = 0; if (request == 0xFE) { return report_max_lun(endpoint, stage); } - b = request + (address << 16); - HALT_UNTIL_DEBUGGING(); + // b = request + (address << 16); + // HALT_UNTIL_DEBUGGING(); // if (address == 0x80) { @@ -149,7 +148,7 @@ usb_request_status_t usb_class_request( // HALT_UNTIL_DEBUGGING(); - return status + b; + return status; } const usb_request_handlers_t usb_request_handlers = { @@ -168,7 +167,7 @@ void usb_configuration_changed(usb_device_t* const device) void start_usb(void) { detect_hardware_platform(); pin_setup(); - cpu_clock_init(); + cpu_clock_init(); // required usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); From bb90fdc5fc75d83bdf88ee7ac6a780c56c2d528a Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 1 Apr 2023 17:39:08 +0200 Subject: [PATCH 06/11] Implemented write --- firmware/baseband/sd_over_usb/diskio.c | 4 ++ firmware/baseband/sd_over_usb/diskio.h | 1 + .../baseband/sd_over_usb/proc_sd_over_usb.cpp | 12 +---- firmware/baseband/sd_over_usb/scsi.c | 46 ++++++++----------- 4 files changed, 27 insertions(+), 36 deletions(-) diff --git a/firmware/baseband/sd_over_usb/diskio.c b/firmware/baseband/sd_over_usb/diskio.c index 2fcbcfd99..2417e4a2f 100644 --- a/firmware/baseband/sd_over_usb/diskio.c +++ b/firmware/baseband/sd_over_usb/diskio.c @@ -10,3 +10,7 @@ uint32_t get_capacity(void) { bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n) { return sdcRead(&SDCD1, startblk, buf, n); } + +bool_t write_block(uint32_t startblk, uint8_t *buf, uint32_t n) { + return sdcWrite(&SDCD1, startblk, buf, n); +} diff --git a/firmware/baseband/sd_over_usb/diskio.h b/firmware/baseband/sd_over_usb/diskio.h index 5bfe9b308..7b0cd0643 100644 --- a/firmware/baseband/sd_over_usb/diskio.h +++ b/firmware/baseband/sd_over_usb/diskio.h @@ -6,5 +6,6 @@ uint32_t get_capacity(void); bool_t read_block(uint32_t startblk, uint8_t *buf, uint32_t n); +bool_t write_block(uint32_t startblk, uint8_t *buf, uint32_t n); #endif /* __DISKIO_H__ */ \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp index 04fb8ee05..fa0c3c316 100644 --- a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp @@ -39,26 +39,18 @@ CH_IRQ_HANDLER(Vector60) { } } -//uint8_t buf[512]; - int main() { sdcStart(&SDCD1, nullptr); if (sdcConnect(&SDCD1) == CH_FAILED) chDbgPanic("no sd card #1"); - // memset(&buf[0], 0, 512); - // if (sdcRead(&SDCD1, 0, &buf[0], 1) == CH_FAILED) chDbgPanic("no sd card #2"); - - start_usb(); - // memset(&buf[0], 0, 512); - // if (sdcRead(&SDCD1, 0, &buf[0], 1) == CH_FAILED) chDbgPanic("no sd card #3"); - - //event_dispatcher.run(); while (true) { usb_transfer(); } + stop_usb(); + return 0; } diff --git a/firmware/baseband/sd_over_usb/scsi.c b/firmware/baseband/sd_over_usb/scsi.c index 1150bda25..b9c907602 100644 --- a/firmware/baseband/sd_over_usb/scsi.c +++ b/firmware/baseband/sd_over_usb/scsi.c @@ -6,17 +6,17 @@ __asm__ __volatile__("bkpt 1") -volatile bool usb_bulk_block_send = false; +volatile bool usb_bulk_block_done = false; void usb_bulk_block_cb(void* user_data, unsigned int bytes_transferred) { - usb_bulk_block_send = true; + usb_bulk_block_done = true; (void)user_data; (void)bytes_transferred; } void usb_send_bulk(void* const data, const uint32_t maximum_length) { - usb_bulk_block_send = false; + usb_bulk_block_done = false; usb_transfer_schedule_block( &usb_endpoint_bulk_in, @@ -25,7 +25,20 @@ void usb_send_bulk(void* const data, const uint32_t maximum_length) { usb_bulk_block_cb, NULL); - while (!usb_bulk_block_send); + while (!usb_bulk_block_done); +} + +void usb_receive_bulk(void* const data, const uint32_t maximum_length) { + usb_bulk_block_done = false; + + usb_transfer_schedule_block( + &usb_endpoint_bulk_out, + data, + maximum_length, + usb_bulk_block_cb, + NULL); + + while (!usb_bulk_block_done); } void usb_send_csw(msd_cbw_t *msd_cbw_data, uint8_t status) { @@ -135,7 +148,7 @@ uint8_t request_sense(msd_cbw_t *msd_cbw_data) { return 0; } -uint8_t mode_sense6 (msd_cbw_t *msd_cbw_data) { +uint8_t mode_sense6(msd_cbw_t *msd_cbw_data) { (void)msd_cbw_data; scsi_mode_sense6_response_t ret = { @@ -178,31 +191,12 @@ uint8_t data_read10(msd_cbw_t *msd_cbw_data) { return 0; } -volatile uint32_t write10_blocks_send = 0; -void write10_cb(void* user_data, unsigned int bytes_transferred) -{ - write10_blocks_send++; - - (void)user_data; - (void)bytes_transferred; -} - uint8_t data_write10(msd_cbw_t *msd_cbw_data) { - write10_blocks_send = 0; - data_request_t req = decode_data_request(msd_cbw_data->cmd_data); for (size_t block_index = 0; block_index < req.blk_cnt; block_index++) { - usb_transfer_schedule_block( - &usb_endpoint_bulk_out, - &usb_bulk_buffer[0], - 512, - write10_cb, - msd_cbw_data); - - while (write10_blocks_send <= block_index); - - //TODO: write to SD + usb_receive_bulk(&usb_bulk_buffer[0], 512); + write_block(req.first_lba + block_index, &usb_bulk_buffer[0], 1 /* n blocks */); } return 0; From 893df7272f373376986dbf1ca6116768de87d42c Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 1 Apr 2023 18:36:57 +0200 Subject: [PATCH 07/11] refactoring --- firmware/application/apps/ui_sd_over_usb.cpp | 30 +- firmware/application/apps/ui_sd_over_usb.hpp | 9 +- firmware/application/portapack.cpp | 8 +- firmware/application/portapack.hpp | 2 +- firmware/baseband/CMakeLists.txt | 6 +- .../baseband/sd_over_usb/proc_sd_over_usb.cpp | 6 - firmware/baseband/sd_over_usb/scsi.c | 11 +- firmware/baseband/sd_over_usb/scsi.h | 12 +- firmware/baseband/sd_over_usb/sd_over_usb.c | 139 +--- firmware/baseband/sd_over_usb/sd_over_usb.h | 4 +- firmware/baseband/sd_over_usb/usb.c | 676 ------------------ firmware/baseband/sd_over_usb/usb_device.c | 56 -- firmware/baseband/sd_over_usb/usb_device.h | 31 - firmware/baseband/sd_over_usb/usb_endpoint.c | 70 -- firmware/baseband/sd_over_usb/usb_endpoint.h | 42 -- 15 files changed, 40 insertions(+), 1062 deletions(-) delete mode 100644 firmware/baseband/sd_over_usb/usb.c delete mode 100644 firmware/baseband/sd_over_usb/usb_device.c delete mode 100644 firmware/baseband/sd_over_usb/usb_device.h delete mode 100644 firmware/baseband/sd_over_usb/usb_endpoint.c delete mode 100644 firmware/baseband/sd_over_usb/usb_endpoint.h diff --git a/firmware/application/apps/ui_sd_over_usb.cpp b/firmware/application/apps/ui_sd_over_usb.cpp index 068579d62..0bc3095b1 100644 --- a/firmware/application/apps/ui_sd_over_usb.cpp +++ b/firmware/application/apps/ui_sd_over_usb.cpp @@ -26,34 +26,24 @@ namespace ui { SdOverUsbView::SdOverUsbView(NavigationView& nav) : nav_ (nav) { - - sdcDisconnect(&SDCD1); - sdcStop(&SDCD1); - - portapack::shutdown(); - m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, false); - //m4_init(portapack::spi_flash::image_tag_hackrf, portapack::memory::map::m4_code_hackrf, true); - m0_halt(); /* will not return*/ - //baseband::run_image(); - - add_children({ &labels, - &button_close + &button_run }); - button_close.on_select = [this](Button&) { - nav_.pop(); + button_run.on_select = [this](Button&) { + sdcDisconnect(&SDCD1); + sdcStop(&SDCD1); + + portapack::shutdown(true); + m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, false); + m0_halt(); + /* will not return*/ }; - -} - -SdOverUsbView::~SdOverUsbView() { - baseband::shutdown(); } void SdOverUsbView::focus() { - button_close.focus(); + button_run.focus(); } } /* namespace ui */ diff --git a/firmware/application/apps/ui_sd_over_usb.hpp b/firmware/application/apps/ui_sd_over_usb.hpp index ff8fc89dc..e00868052 100644 --- a/firmware/application/apps/ui_sd_over_usb.hpp +++ b/firmware/application/apps/ui_sd_over_usb.hpp @@ -37,7 +37,6 @@ namespace ui { class SdOverUsbView : public View { public: SdOverUsbView(NavigationView& nav); - ~SdOverUsbView(); void focus() override; @@ -47,15 +46,13 @@ private: NavigationView& nav_; Labels labels { - { { 4, 4 }, "Use USB", Color::white() } + { { 40, 4 }, "This will provide access\nto the SD card over USB.", Color::white() } }; - Button button_close { + Button button_run { { 2 * 8, 15 * 16, 12 * 8, 3 * 16 }, - "Close" + "Run" }; - - }; } /* namespace ui */ diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index edf064e10..6a7f3376a 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -515,11 +515,13 @@ bool init() { return true; } -void shutdown() { +void shutdown(const bool leave_screen_on) { gpdma::controller.disable(); - backlight()->off(); - display.shutdown(); + if (leave_screen_on) { + backlight()->off(); + display.shutdown(); + } radio::disable(); audio::shutdown(); diff --git a/firmware/application/portapack.hpp b/firmware/application/portapack.hpp index a34d93a6e..3fbc4b8d8 100644 --- a/firmware/application/portapack.hpp +++ b/firmware/application/portapack.hpp @@ -63,7 +63,7 @@ void set_antenna_bias(const bool v); bool get_antenna_bias(); bool init(); -void shutdown(); +void shutdown(const bool leave_screen_on = false); Backlight* backlight(); diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 1deaa6b4a..3bce25c6c 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -529,12 +529,12 @@ set(MODE_CPPSRC sd_over_usb/diskio.c sd_over_usb/sd_over_usb.c sd_over_usb/usb_descriptor.c - sd_over_usb/usb_device.c - sd_over_usb/usb_endpoint.c - sd_over_usb/usb.c sd_over_usb/hackrf_core.c + ${HACKRF_PATH}/firmware/common/usb.c ${HACKRF_PATH}/firmware/common/usb_queue.c + ${HACKRF_PATH}/firmware/hackrf_usb/usb_device.c + ${HACKRF_PATH}/firmware/hackrf_usb/usb_endpoint.c ${HACKRF_PATH}/firmware/common/usb_request.c ${HACKRF_PATH}/firmware/common/usb_standard_request.c ${HACKRF_PATH}/firmware/common/platform_detect.c diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp index fa0c3c316..8a6dcfb99 100644 --- a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp @@ -24,13 +24,10 @@ #include "hal.h" #include "proc_sd_over_usb.hpp" - -#include "debug.hpp" #include "portapack_shared_memory.hpp" extern "C" { void start_usb(void); -void stop_usb(void); void irq_usb(void); void usb_transfer(void); @@ -40,7 +37,6 @@ CH_IRQ_HANDLER(Vector60) { } int main() { - sdcStart(&SDCD1, nullptr); if (sdcConnect(&SDCD1) == CH_FAILED) chDbgPanic("no sd card #1"); @@ -50,7 +46,5 @@ int main() { usb_transfer(); } - stop_usb(); - return 0; } diff --git a/firmware/baseband/sd_over_usb/scsi.c b/firmware/baseband/sd_over_usb/scsi.c index b9c907602..f3e037872 100644 --- a/firmware/baseband/sd_over_usb/scsi.c +++ b/firmware/baseband/sd_over_usb/scsi.c @@ -1,11 +1,6 @@ #include "scsi.h" #include "diskio.h" -#define HALT_UNTIL_DEBUGGING() \ - while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \ - __asm__ __volatile__("bkpt 1") - - volatile bool usb_bulk_block_done = false; void usb_bulk_block_cb(void* user_data, unsigned int bytes_transferred) { @@ -104,8 +99,6 @@ uint8_t read_format_capacities(msd_cbw_t *msd_cbw_data) { .header = {0, 0, 0, 1 * 8 /* num_entries * 8 */}, .blocknum = {((num_blocks) >> 24)& 0xff, ((num_blocks) >> 16)& 0xff, ((num_blocks) >> 8)& 0xff, num_blocks & 0xff}, .blocklen = {0b10 /* formated */, 0, (512) >> 8, 0}, - // .blocknum2 = {((num_blocks) >> 24)& 0xff, ((num_blocks) >> 16)& 0xff, ((num_blocks) >> 8)& 0xff, num_blocks & 0xff}, - // .blocklen2 = {0 /* formated */, 0, (512) >> 8, 0} }; memcpy(&usb_bulk_buffer[0], &ret, sizeof(scsi_read_format_capacities_response_t)); @@ -155,7 +148,7 @@ uint8_t mode_sense6(msd_cbw_t *msd_cbw_data) { .byte = { sizeof(scsi_mode_sense6_response_t) - 1, 0, - 0, // 0x01 << 7, // 0 for not write protected + 0, 0 } }; @@ -166,7 +159,6 @@ uint8_t mode_sense6(msd_cbw_t *msd_cbw_data) { } static data_request_t decode_data_request(const uint8_t *cmd) { - data_request_t req; uint32_t lba; uint16_t blk; @@ -207,7 +199,6 @@ void scsi_command(msd_cbw_t *msd_cbw_data) { switch (msd_cbw_data->cmd_data[0]) { case SCSI_CMD_INQUIRY: - //status = handle_inquiry(msd_cbw_data); if ((msd_cbw_data->cmd_data[1] & 0b1) && msd_cbw_data->cmd_data[2] == 0x80) { status = handle_inquiry_serial_number(msd_cbw_data); } diff --git a/firmware/baseband/sd_over_usb/scsi.h b/firmware/baseband/sd_over_usb/scsi.h index 26ab04f67..7c74ca140 100644 --- a/firmware/baseband/sd_over_usb/scsi.h +++ b/firmware/baseband/sd_over_usb/scsi.h @@ -5,8 +5,8 @@ #include #include #include -#include "usb_device.h" -#include "usb_endpoint.h" +#include +#include #include #include #include "platform_detect.h" @@ -101,14 +101,6 @@ typedef struct { uint8_t blocklen[4]; } scsi_read_format_capacities_response_t; -typedef struct { - uint8_t header[4]; - uint8_t blocknum[4]; - uint8_t blocklen[4]; - uint8_t blocknum2[4]; - uint8_t blocklen2[4]; -} scsi_read_format_capacities_double_response_t; - typedef struct { uint32_t last_block_addr; uint32_t block_size; diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.c b/firmware/baseband/sd_over_usb/sd_over_usb.c index 64bd3c50d..1d720d984 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.c +++ b/firmware/baseband/sd_over_usb/sd_over_usb.c @@ -1,14 +1,6 @@ #include "sd_over_usb.h" #include "scsi.h" -//extern usb_request_handlers_t usb_request_handlers; -#define HALT_UNTIL_DEBUGGING() \ - while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \ - __asm__ __volatile__("bkpt 1") - -// uint8_t usb_buffer[USB_TRANSFER_SIZE]; - - bool scsi_running = false; usb_request_status_t report_max_lun( @@ -26,140 +18,33 @@ usb_request_status_t report_max_lun( usb_transfer_schedule_ack(endpoint->out); - /* start loop here?*/ scsi_running = true; - // Host to Device. receive inquiry LUN - return USB_REQUEST_STATUS_OK; } - else if (stage == USB_TRANSFER_STAGE_DATA) { - return USB_REQUEST_STATUS_OK; - } - else if (stage == USB_TRANSFER_STAGE_STATUS) { - // response here? - return USB_REQUEST_STATUS_OK; - } -} - - -usb_request_status_t report_magic_scsi( - usb_endpoint_t* const endpoint, - const usb_transfer_stage_t stage) -{ - - // return USB_REQUEST_STATUS_OK; - - - // if (endpoint->address != 0x02) { - // HALT_UNTIL_DEBUGGING(); - // return USB_REQUEST_STATUS_OK; - // } - - if (stage == USB_TRANSFER_STAGE_SETUP) { - return USB_REQUEST_STATUS_OK; - // usb_bulk_buffer[0] = 0x55; - // usb_bulk_buffer[1] = 0x55; - // usb_bulk_buffer[2] = 0x55; - // usb_bulk_buffer[3] = 0x55; - // usb_bulk_buffer[4] = 0; - - // usb_transfer_schedule_block( - // &usb_endpoint_bulk_out, - // &usb_bulk_buffer[0x0000], - // 5, - // NULL, - // NULL); - - // usb_transfer_schedule_ack(endpoint->out); - - - - } - else if (stage == USB_TRANSFER_STAGE_DATA) { - HALT_UNTIL_DEBUGGING(); - } - else if (stage == USB_TRANSFER_STAGE_STATUS) { - HALT_UNTIL_DEBUGGING(); - } - return USB_REQUEST_STATUS_OK; - - - (void)(endpoint); - (void)(stage); + return USB_REQUEST_STATUS_OK; } -usb_request_status_t usb_vendor_request( - usb_endpoint_t* const endpoint, - const usb_transfer_stage_t stage) -{ - usb_request_status_t status = USB_REQUEST_STATUS_STALL; - - // volatile uint_fast8_t address = endpoint->address; - volatile uint8_t request = endpoint->setup.request; - // volatile uint32_t b = 0; - - if (request == 25) { // unknown code - return report_magic_scsi(endpoint, stage); - } - - // b = request + (address << 16); - // HALT_UNTIL_DEBUGGING(); - - - return status; -} - -usb_request_status_t usb_class_request( - usb_endpoint_t* const endpoint, - const usb_transfer_stage_t stage) -{ +usb_request_status_t usb_class_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { usb_request_status_t status = USB_REQUEST_STATUS_STALL; volatile uint8_t request = endpoint->setup.request; - // volatile uint32_t b = 0; - if (request == 0xFE) { + if (request == 0xFE) return report_max_lun(endpoint, stage); - } - // b = request + (address << 16); - // HALT_UNTIL_DEBUGGING(); - - // if (address == 0x80) { - - // HALT_UNTIL_DEBUGGING(); - // return USB_REQUEST_STATUS_OK; - // } - - // else if (address == 0x00) { - // if (request == 0xFE) { - // return USB_REQUEST_STATUS_OK; // ??????????????????? - // } - // b = request + (address << 16); - // HALT_UNTIL_DEBUGGING(); - // } - - // else if (address == 0x02) { - // if (request == 0xFE) { - // return USB_REQUEST_STATUS_OK; // ??????????????????? - // } - // //return USB_REQUEST_STATUS_OK; - // } - - - // HALT_UNTIL_DEBUGGING(); return status; } const usb_request_handlers_t usb_request_handlers = { .standard = usb_standard_request, .class = usb_class_request, - .vendor = usb_vendor_request, + .vendor = 0, .reserved = 0 }; -void usb_configuration_changed(usb_device_t* const device) -{ +void usb_configuration_changed(usb_device_t* const device) { + (void)device; + usb_endpoint_init(&usb_endpoint_bulk_in); usb_endpoint_init(&usb_endpoint_bulk_out); } @@ -167,7 +52,7 @@ void usb_configuration_changed(usb_device_t* const device) void start_usb(void) { detect_hardware_platform(); pin_setup(); - cpu_clock_init(); // required + cpu_clock_init(); usb_set_configuration_changed_cb(usb_configuration_changed); usb_peripheral_reset(); @@ -198,6 +83,9 @@ void irq_usb(void) { volatile bool transfer_complete = false; void scsi_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred) { + (void)user_data; + (void)bytes_transferred; + transfer_complete = true; } @@ -206,18 +94,17 @@ void usb_transfer(void) { transfer_complete = false; usb_transfer_schedule_block( &usb_endpoint_bulk_out, - &usb_bulk_buffer[0], + &usb_bulk_buffer[0x4000], USB_TRANSFER_SIZE, scsi_bulk_transfer_complete, NULL); while (!transfer_complete); - msd_cbw_t *msd_cbw_data = (msd_cbw_t *) &usb_bulk_buffer[0]; + msd_cbw_t *msd_cbw_data = (msd_cbw_t *) &usb_bulk_buffer[0x4000]; if (msd_cbw_data->signature == MSD_CBW_SIGNATURE){ scsi_command(msd_cbw_data); } - } } \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.h b/firmware/baseband/sd_over_usb/sd_over_usb.h index 536ac3814..1d1622c26 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.h +++ b/firmware/baseband/sd_over_usb/sd_over_usb.h @@ -27,8 +27,8 @@ #include #include #include -#include "usb_device.h" -#include "usb_endpoint.h" +#include +#include #include #include #include "platform_detect.h" diff --git a/firmware/baseband/sd_over_usb/usb.c b/firmware/baseband/sd_over_usb/usb.c deleted file mode 100644 index fd212f311..000000000 --- a/firmware/baseband/sd_over_usb/usb.c +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright 2012-2022 Great Scott Gadgets - * Copyright 2012 Jared Boone - * - * This file is part of HackRF. - * - * This program 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 2, or (at your option) - * any later version. - * - * This program 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 this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include -#include - -#include -#include "usb_type.h" -#include "usb_queue.h" -#include "usb_standard_request.h" - -#include -#include -#include -#include - -#define HALT_UNTIL_DEBUGGING() \ - while (!((*(volatile uint32_t *)0xE000EDF0) & (1 << 0))) {} \ - __asm__ __volatile__("bkpt 1") - - -usb_device_t* usb_device_usb0 = 0; - -usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048); - -#define USB_QH_INDEX(endpoint_address) \ - (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) - -usb_queue_head_t* usb_queue_head(const uint_fast8_t endpoint_address) -{ - return &usb_qh[USB_QH_INDEX(endpoint_address)]; -} - -usb_endpoint_t* usb_endpoint_from_address(const uint_fast8_t endpoint_address) -{ - return (usb_endpoint_t*) usb_queue_head(endpoint_address)->_reserved_0; -} - -static uint_fast8_t usb_endpoint_address( - const usb_transfer_direction_t direction, - const uint_fast8_t number) -{ - return ((direction == USB_TRANSFER_DIRECTION_IN) ? 0x80 : 0x00) + number; -} - -static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address) -{ - return (endpoint_address & 0x80) ? true : false; -} - -static uint_fast8_t usb_endpoint_number(const uint_fast8_t endpoint_address) -{ - return (endpoint_address & 0xF); -} - -void usb_peripheral_reset() -{ - RESET_CTRL0 = RESET_CTRL0_USB0_RST; - RESET_CTRL0 = 0; - - while ((RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0) {} -} - -void usb_phy_enable() -{ - CREG_CREG0 &= ~CREG_CREG0_USB0PHY; -} - -static void usb_clear_pending_interrupts(const uint32_t mask) -{ - USB0_ENDPTNAK = mask; - USB0_ENDPTNAKEN = mask; - USB0_USBSTS_D = mask; - USB0_ENDPTSETUPSTAT = USB0_ENDPTSETUPSTAT & mask; - USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE & mask; -} - -static void usb_clear_all_pending_interrupts() -{ - usb_clear_pending_interrupts(0xFFFFFFFF); -} - -static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) -{ - // Wait until controller has parsed new transfer descriptors and prepared - // receive buffers. - while (USB0_ENDPTPRIME & mask) {} -} - -static void usb_flush_endpoints(const uint32_t mask) -{ - // Clear any primed buffers. If a packet is in progress, that transfer - // will continue until completion. - USB0_ENDPTFLUSH = mask; -} - -static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask) -{ - // Wait until controller has flushed all endpoints / cleared any primed - // buffers. - while (USB0_ENDPTFLUSH & mask) {} -} - -static void usb_flush_primed_endpoints(const uint32_t mask) -{ - usb_wait_for_endpoint_priming_to_finish(mask); - usb_flush_endpoints(mask); - usb_wait_for_endpoint_flushing_to_finish(mask); -} - -static void usb_flush_all_primed_endpoints() -{ - usb_flush_primed_endpoints(0xFFFFFFFF); -} - -static void usb_endpoint_set_type( - const usb_endpoint_t* const endpoint, - const usb_transfer_type_t transfer_type) -{ - // NOTE: UM10503 section 23.6.24 "Endpoint 1 to 5 control registers" says - // that the disabled side of an endpoint must be set to a non-control type - // (e.g. bulk, interrupt, or iso). - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - USB0_ENDPTCTRL(endpoint_number) = - (USB0_ENDPTCTRL(endpoint_number) & - ~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK)) | - (USB0_ENDPTCTRL_TXT1_0(transfer_type) | - USB0_ENDPTCTRL_RXT(transfer_type)); -} - -static void usb_endpoint_enable(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - USB0_ENDPTCTRL(endpoint_number) |= - (USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR); - } else { - USB0_ENDPTCTRL(endpoint_number) |= - (USB0_ENDPTCTRL_RXE | USB0_ENDPTCTRL_RXR); - } -} - -static void usb_endpoint_clear_pending_interrupts(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - usb_clear_pending_interrupts( - USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number)); - } else { - usb_clear_pending_interrupts( - USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number)); - } -} - -void usb_endpoint_disable(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_TXE); - } else { - USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE); - } - usb_queue_flush_endpoint(endpoint); - usb_endpoint_clear_pending_interrupts(endpoint); - usb_endpoint_flush(endpoint); -} - -void usb_endpoint_prime( - const usb_endpoint_t* const endpoint, - usb_transfer_descriptor_t* const first_td) -{ - usb_queue_head_t* const qh = usb_queue_head(endpoint->address); - - qh->next_dtd_pointer = first_td; - qh->total_bytes &= - ~(USB_TD_DTD_TOKEN_STATUS_ACTIVE | USB_TD_DTD_TOKEN_STATUS_HALTED); - - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - USB0_ENDPTPRIME = USB0_ENDPTPRIME_PETB(1 << endpoint_number); - } else { - USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number); - } -} - -static bool usb_endpoint_is_priming(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number); - } else { - return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number); - } -} - -// Schedule an already filled-in transfer descriptor for execution on -// the given endpoint, waiting until the endpoint has finished. -void usb_endpoint_schedule_wait( - const usb_endpoint_t* const endpoint, - usb_transfer_descriptor_t* const td) -{ - // Ensure that endpoint is ready to be primed. - // It may have been flushed due to an aborted transaction. - // TODO: This should be preceded by a flush? - while (usb_endpoint_is_ready(endpoint)) {} - - td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; - - usb_endpoint_prime(endpoint, td); -} - -// Schedule an already filled-in transfer descriptor for execution on -// the given endpoint, appending to the end of the endpoint's queue if -// there are pending TDs. Note that this requires that one knows the -// tail of the endpoint's TD queue. Moreover, the user is responsible -// for setting the TERMINATE bit of next_dtd_pointer if needed. -void usb_endpoint_schedule_append( - const usb_endpoint_t* const endpoint, - usb_transfer_descriptor_t* const tail_td, - usb_transfer_descriptor_t* const new_td) -{ - bool done; - - tail_td->next_dtd_pointer = new_td; - - if (usb_endpoint_is_priming(endpoint)) { - return; - } - - do { - USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW; - done = usb_endpoint_is_ready(endpoint); - } while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW)); - - USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW; - if (!done) { - usb_endpoint_prime(endpoint, new_td); - } -} - -void usb_endpoint_flush(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - usb_queue_flush_endpoint(endpoint); - if (usb_endpoint_is_in(endpoint->address)) { - usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FETB(1 << endpoint_number)); - } else { - usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FERB(1 << endpoint_number)); - } -} - -/* -static bool usb_endpoint_is_flushing( - const usb_endpoint_t* const endpoint -) { - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if( usb_endpoint_is_in(endpoint->address) ) { - return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FETB(1 << endpoint_number); - } else { - return USB0_ENDPTFLUSH & USB0_ENDPTFLUSH_FERB(1 << endpoint_number); - } -} -*/ -bool usb_endpoint_is_ready(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ETBR(1 << endpoint_number); - } else { - return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ERBR(1 << endpoint_number); - } -} - -bool usb_endpoint_is_complete(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number); - } else { - return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number); - } -} - -void usb_endpoint_stall(const usb_endpoint_t* const endpoint) -{ - // Endpoint is to be stalled as a pair -- both OUT and IN. - // See UM10503 section 23.10.5.2 "Stalling" - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXS | USB0_ENDPTCTRL_TXS); - - // TODO: Also need to reset data toggle in both directions? -} - -void usb_endpoint_reset_data_toggle(const usb_endpoint_t* const endpoint) -{ - const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); - if (usb_endpoint_is_in(endpoint->address)) { - USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_TXR; - } else { - USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_RXR; - } -} - -static void usb_controller_run() -{ - USB0_USBCMD_D |= USB0_USBCMD_D_RS; -} - -static void usb_controller_stop() -{ - USB0_USBCMD_D &= ~USB0_USBCMD_D_RS; -} - -static uint_fast8_t usb_controller_is_resetting() -{ - return (USB0_USBCMD_D & USB0_USBCMD_D_RST) != 0; -} - -static void usb_controller_set_device_mode() -{ - // Set USB0 peripheral mode - USB0_USBMODE_D = USB0_USBMODE_D_CM1_0(2); - - // Set device-related OTG flags - // OTG termination: controls pull-down on USB_DM - USB0_OTGSC = USB0_OTGSC_OT; -} - -usb_speed_t usb_speed(const usb_device_t* const device) -{ - if (device == usb_device_usb0) { - switch (USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK) { - case USB0_PORTSC1_D_PSPD(0): - return USB_SPEED_FULL; - - case USB0_PORTSC1_D_PSPD(2): - return USB_SPEED_HIGH; - - default: - // TODO: What to do/return here? Is this even possible? - return USB_SPEED_FULL; - } - } else { - // TODO: This should not be possible with a more class-like - // implementation. - return USB_SPEED_FULL; - } -} - -static void usb_clear_status(const uint32_t status) -{ - USB0_USBSTS_D = status; -} - -static uint32_t usb_get_status() -{ - // Mask status flags with enabled flag interrupts. - const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D; - - // Clear flags that were just read, leaving alone any flags that - // were just set (after the read). It's important to read and - // reset flags atomically! :-) - usb_clear_status(status); - - return status; -} - -static void usb_clear_endpoint_setup_status(const uint32_t endpoint_setup_status) -{ - USB0_ENDPTSETUPSTAT = endpoint_setup_status; -} - -static uint32_t usb_get_endpoint_setup_status() -{ - return USB0_ENDPTSETUPSTAT; -} - -static void usb_clear_endpoint_complete(const uint32_t endpoint_complete) -{ - USB0_ENDPTCOMPLETE = endpoint_complete; -} - -static uint32_t usb_get_endpoint_complete() -{ - return USB0_ENDPTCOMPLETE; -} - -static void usb_disable_all_endpoints() -{ - // Endpoint 0 is always enabled. TODO: So why set ENDPTCTRL0? - USB0_ENDPTCTRL0 &= ~(USB0_ENDPTCTRL0_RXE | USB0_ENDPTCTRL0_TXE); - USB0_ENDPTCTRL1 &= ~(USB0_ENDPTCTRL1_RXE | USB0_ENDPTCTRL1_TXE); - USB0_ENDPTCTRL2 &= ~(USB0_ENDPTCTRL2_RXE | USB0_ENDPTCTRL2_TXE); - USB0_ENDPTCTRL3 &= ~(USB0_ENDPTCTRL3_RXE | USB0_ENDPTCTRL3_TXE); - USB0_ENDPTCTRL4 &= ~(USB0_ENDPTCTRL4_RXE | USB0_ENDPTCTRL4_TXE); - USB0_ENDPTCTRL5 &= ~(USB0_ENDPTCTRL5_RXE | USB0_ENDPTCTRL5_TXE); -} - -void usb_set_address_immediate( - const usb_device_t* const device, - const uint_fast8_t address) -{ - if (device == usb_device_usb0) { - USB0_DEVICEADDR = USB0_DEVICEADDR_USBADR(address); - } -} - -void usb_set_address_deferred(const usb_device_t* const device, const uint_fast8_t address) -{ - if (device == usb_device_usb0) { - USB0_DEVICEADDR = - USB0_DEVICEADDR_USBADR(address) | USB0_DEVICEADDR_USBADRA; - } -} - -static void usb_reset_all_endpoints() -{ - usb_disable_all_endpoints(); - usb_clear_all_pending_interrupts(); - usb_flush_all_primed_endpoints(); -} - -static void usb_controller_reset() -{ - // TODO: Good to disable some USB interrupts to avoid priming new - // new endpoints before the controller is reset? - usb_reset_all_endpoints(); - usb_controller_stop(); - - // Reset controller. Resets internal pipelines, timers, counters, state - // machines to initial values. Not recommended when device is in attached - // state -- effect on attached host is undefined. Detach first by flushing - // all primed endpoints and stopping controller. - USB0_USBCMD_D = USB0_USBCMD_D_RST; - - while (usb_controller_is_resetting()) {} -} - -static void usb_bus_reset(usb_device_t* const device) -{ - // According to UM10503 v1.4 section 23.10.3 "Bus reset": - usb_reset_all_endpoints(); - usb_set_address_immediate(device, 0); - usb_set_configuration(device, 0); - - // TODO: Enable endpoint 0, which might not actually be necessary, - // as the datasheet claims it can't be disabled. - - //wait_ms(3); - // - //if( USB0_PORTSC1 & USB0_PORTSC1_PR ) { - // // Port still is in the reset state. - //} else { - // usb_hardware_reset(); - //} -} - -static void usb_interrupt_enable(usb_device_t* const device) -{ - if (device == usb_device_usb0) { - nvic_enable_irq(NVIC_USB0_IRQ); - } -} - -void usb_device_init(const uint_fast8_t device_ordinal, usb_device_t* const device) -{ - if (device_ordinal == 0) { - usb_device_usb0 = device; - - usb_phy_enable(); - usb_controller_reset(); - usb_controller_set_device_mode(); - - // Set interrupt threshold interval to 0 - USB0_USBCMD_D &= ~USB0_USBCMD_D_ITC_MASK; - - // Configure endpoint list address - USB0_ENDPOINTLISTADDR = (uint32_t) usb_qh; - - // Enable interrupts - USB0_USBINTR_D = USB0_USBINTR_D_UE | USB0_USBINTR_D_UEE | - USB0_USBINTR_D_PCE | - USB0_USBINTR_D_URE - //| USB0_USBINTR_D_SRE - | USB0_USBINTR_D_SLE - //| USB0_USBINTR_D_NAKE - ; - } -} - -void usb_run(usb_device_t* const device) -{ - usb_interrupt_enable(device); - usb_controller_run(device); -} - -static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src) -{ - dst->request_type = src[0]; - dst->request = src[1]; - dst->value_l = src[2]; - dst->value_h = src[3]; - dst->index_l = src[4]; - dst->index_h = src[5]; - dst->length_l = src[6]; - dst->length_h = src[7]; -} - -void usb_endpoint_init(const usb_endpoint_t* const endpoint) -{ - usb_endpoint_flush(endpoint); - - uint_fast16_t max_packet_size = endpoint->device->descriptor[7]; - usb_transfer_type_t transfer_type = USB_TRANSFER_TYPE_CONTROL; - const uint8_t* const endpoint_descriptor = usb_endpoint_descriptor(endpoint); - if (endpoint_descriptor) { - max_packet_size = - usb_endpoint_descriptor_max_packet_size(endpoint_descriptor); - transfer_type = - usb_endpoint_descriptor_transfer_type(endpoint_descriptor); - } - - // TODO: There are more capabilities to adjust based on the endpoint - // descriptor. - usb_queue_head_t* const qh = usb_queue_head(endpoint->address); - qh->capabilities = USB_QH_CAPABILITIES_MULT(0) | USB_QH_CAPABILITIES_ZLT | - USB_QH_CAPABILITIES_MPL(max_packet_size) | - ((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS : - 0); - qh->current_dtd_pointer = 0; - qh->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; - qh->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(0) | USB_TD_DTD_TOKEN_MULTO(0); - qh->buffer_pointer_page[0] = 0; - qh->buffer_pointer_page[1] = 0; - qh->buffer_pointer_page[2] = 0; - qh->buffer_pointer_page[3] = 0; - qh->buffer_pointer_page[4] = 0; - - // This is how we look up an endpoint structure from an endpoint address: - qh->_reserved_0 = (uint32_t) endpoint; - - // TODO: Should NAK be enabled? I'm kinda squishy on this... - //USB0_ENDPTNAKEN |= - // USB0_ENDPTNAKEN_EPRNE(1 << endpoint_out->number); - - usb_endpoint_set_type(endpoint, transfer_type); - - usb_endpoint_enable(endpoint); -} - -static void usb_check_for_setup_events() { - const uint32_t endptsetupstat = usb_get_endpoint_setup_status(); - if (endptsetupstat) { - for (uint_fast8_t i = 0; i < 6; i++) { - const uint32_t endptsetupstat_bit = USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i); - if (endptsetupstat & endptsetupstat_bit) { - usb_endpoint_t* const endpoint = usb_endpoint_from_address(usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)); - if (endpoint && endpoint->setup_complete) { - usb_queue_head_t *head = usb_queue_head(endpoint->address); - - //HALT_UNTIL_DEBUGGING(); - - copy_setup(&endpoint->setup, head->setup); - // TODO: Clean up this duplicated effort by providing - // a cleaner way to get the SETUP data. - copy_setup(&endpoint->in->setup, head->setup); - - usb_clear_endpoint_setup_status(endptsetupstat_bit); - endpoint->setup_complete(endpoint); - } else { - usb_clear_endpoint_setup_status(endptsetupstat_bit); - } - } - } - } -} - -static void usb_check_for_transfer_events() { - const uint32_t endptcomplete = usb_get_endpoint_complete(); - - if (endptcomplete) { - for (uint_fast8_t i = 0; i < 6; i++) { - const uint32_t endptcomplete_out_bit = USB0_ENDPTCOMPLETE_ERCE(1 << i); - - if (endptcomplete & endptcomplete_out_bit) { - usb_clear_endpoint_complete(endptcomplete_out_bit); - usb_endpoint_t* const endpoint = usb_endpoint_from_address(usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)); - if (endpoint && endpoint->transfer_complete) { - endpoint->transfer_complete(endpoint); - } - } - - const uint32_t endptcomplete_in_bit = USB0_ENDPTCOMPLETE_ETCE(1 << i); - - if (endptcomplete & endptcomplete_in_bit) { - usb_clear_endpoint_complete(endptcomplete_in_bit); - usb_endpoint_t* const endpoint = usb_endpoint_from_address(usb_endpoint_address(USB_TRANSFER_DIRECTION_IN, i)); - if (endpoint && endpoint->transfer_complete) { - endpoint->transfer_complete(endpoint); - } - } - } - } -} - -void usb0_isr() -{ - const uint32_t status = usb_get_status(); - - if (status == 0) { - // Nothing to do. - return; - } - - if (status & USB0_USBSTS_D_UI) { - // USB: - // - Completed transaction transfer descriptor has IOC set. - // - Short packet detected. - // - SETUP packet received. - - usb_check_for_setup_events(); - usb_check_for_transfer_events(); - - // TODO: Reset ignored ENDPTSETUPSTAT and ENDPTCOMPLETE flags? - } - - if (status & USB0_USBSTS_D_SRI) { - // Start Of Frame received. - } - - if (status & USB0_USBSTS_D_PCI) { - // Port change detect: - // Port controller entered full- or high-speed operational state. - } - - if (status & USB0_USBSTS_D_SLI) { - // Device controller suspend. - } - - if (status & USB0_USBSTS_D_URI) { - // USB reset received. - usb_bus_reset(usb_device_usb0); - } - - if (status & USB0_USBSTS_D_UEI) { - // USB error: - // Completion of a USB transaction resulted in an error condition. - // Set along with USBINT if the TD on which the error interrupt - // occurred also had its interrupt on complete (IOC) bit set. - // The device controller detects resume signalling only. - } - - if (status & USB0_USBSTS_D_NAKI) { - // Both the TX/RX endpoint NAK bit and corresponding TX/RX endpoint - // NAK enable bit are set. - } -} diff --git a/firmware/baseband/sd_over_usb/usb_device.c b/firmware/baseband/sd_over_usb/usb_device.c deleted file mode 100644 index b689ce9fe..000000000 --- a/firmware/baseband/sd_over_usb/usb_device.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012-2022 Great Scott Gadgets - * Copyright 2012 Jared Boone - * Copyright 2013 Benjamin Vernoux - * - * This file is part of HackRF. - * - * This program 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 2, or (at your option) - * any later version. - * - * This program 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 this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "usb_device.h" - -#include - -#include "usb_descriptor.h" - -usb_configuration_t usb_configuration_high_speed = { - .number = 1, - .speed = USB_SPEED_HIGH, - .descriptor = usb_descriptor_configuration_high_speed, -}; - -usb_configuration_t usb_configuration_full_speed = { - .number = 1, - .speed = USB_SPEED_FULL, - .descriptor = usb_descriptor_configuration_full_speed, -}; - -usb_configuration_t* usb_configurations[] = { - &usb_configuration_high_speed, - &usb_configuration_full_speed, - 0, -}; - -usb_device_t usb_device = { - .descriptor = usb_descriptor_device, - .descriptor_strings = usb_descriptor_strings, - .qualifier_descriptor = usb_descriptor_device_qualifier, - .configurations = &usb_configurations, - .configuration = 0, - .wcid_string_descriptor = wcid_string_descriptor, - .wcid_feature_descriptor = wcid_feature_descriptor, -}; diff --git a/firmware/baseband/sd_over_usb/usb_device.h b/firmware/baseband/sd_over_usb/usb_device.h deleted file mode 100644 index 05008dca1..000000000 --- a/firmware/baseband/sd_over_usb/usb_device.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2012-2013 Great Scott Gadgets - * Copyright 2012 Jared Boone - * Copyright 2013 Benjamin Vernoux - * - * This file is part of HackRF. - * - * This program 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 2, or (at your option) - * any later version. - * - * This program 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 this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __USB_DEVICE_H__ -#define __USB_DEVICE_H__ - -#include - -extern usb_device_t usb_device; - -#endif /* end of include guard: __USB_DEVICE_H__ */ diff --git a/firmware/baseband/sd_over_usb/usb_endpoint.c b/firmware/baseband/sd_over_usb/usb_endpoint.c deleted file mode 100644 index 028327087..000000000 --- a/firmware/baseband/sd_over_usb/usb_endpoint.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2012-2022 Great Scott Gadgets - * Copyright 2012 Jared Boone - * Copyright 2013 Benjamin Vernoux - * - * This file is part of HackRF. - * - * This program 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 2, or (at your option) - * any later version. - * - * This program 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 this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "usb_endpoint.h" - -#include - -#include "usb_device.h" - -usb_endpoint_t usb_endpoint_control_out = { - .address = 0x00, - .device = &usb_device, - .in = &usb_endpoint_control_in, - .out = &usb_endpoint_control_out, - .setup_complete = usb_setup_complete, - .transfer_complete = usb_control_out_complete, -}; -USB_DEFINE_QUEUE(usb_endpoint_control_out, 4); - -usb_endpoint_t usb_endpoint_control_in = { - .address = 0x80, - .device = &usb_device, - .in = &usb_endpoint_control_in, - .out = &usb_endpoint_control_out, - .setup_complete = 0, - .transfer_complete = usb_control_in_complete, -}; -static USB_DEFINE_QUEUE(usb_endpoint_control_in, 4); - -// NOTE: Endpoint number for IN and OUT are different. I wish I had some -// evidence that having BULK IN and OUT on separate endpoint numbers was -// actually a good idea. Seems like everybody does it that way, but why? - -usb_endpoint_t usb_endpoint_bulk_in = { - .address = 0x81, - .device = &usb_device, - .in = &usb_endpoint_bulk_in, - .out = 0, - .setup_complete = 0, - .transfer_complete = usb_queue_transfer_complete}; -static USB_DEFINE_QUEUE(usb_endpoint_bulk_in, 1); - -usb_endpoint_t usb_endpoint_bulk_out = { - .address = 0x02, - .device = &usb_device, - .in = 0, - .out = &usb_endpoint_bulk_out, - .setup_complete = 0, - .transfer_complete = usb_queue_transfer_complete}; -static USB_DEFINE_QUEUE(usb_endpoint_bulk_out, 1); diff --git a/firmware/baseband/sd_over_usb/usb_endpoint.h b/firmware/baseband/sd_over_usb/usb_endpoint.h deleted file mode 100644 index 7a594cd5a..000000000 --- a/firmware/baseband/sd_over_usb/usb_endpoint.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2012-2013 Great Scott Gadgets - * Copyright 2012 Jared Boone - * Copyright 2013 Benjamin Vernoux - * - * This file is part of HackRF. - * - * This program 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 2, or (at your option) - * any later version. - * - * This program 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 this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __USB_ENDPOINT_H__ -#define __USB_ENDPOINT_H__ - -#include -#include - -extern usb_endpoint_t usb_endpoint_control_out; -extern USB_DECLARE_QUEUE(usb_endpoint_control_out); - -extern usb_endpoint_t usb_endpoint_control_in; -extern USB_DECLARE_QUEUE(usb_endpoint_control_in); - -extern usb_endpoint_t usb_endpoint_bulk_in; -extern USB_DECLARE_QUEUE(usb_endpoint_bulk_in); - -extern usb_endpoint_t usb_endpoint_bulk_out; -extern USB_DECLARE_QUEUE(usb_endpoint_bulk_out); - -#endif /* end of include guard: __USB_ENDPOINT_H__ */ From 8d8d457da256688c18437cd7f89d19f2ff73da60 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 1 Apr 2023 18:57:53 +0200 Subject: [PATCH 08/11] refactoring --- firmware/baseband/CMakeLists.txt | 2 +- firmware/baseband/sd_over_usb/hackrf_core.c | 5 -- .../baseband/sd_over_usb/proc_sd_over_usb.cpp | 3 -- .../baseband/sd_over_usb/proc_sd_over_usb.hpp | 48 ------------------- firmware/baseband/sd_over_usb/scsi.h | 5 -- firmware/baseband/sd_over_usb/sd_over_usb.h | 1 - 6 files changed, 1 insertion(+), 63 deletions(-) delete mode 100644 firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 3bce25c6c..0d6e69474 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -187,7 +187,7 @@ set(AOPT) set(TOPT "-mthumb -DTHUMB") # Define C warning options here -set(CWARN "-Wall -Wextra -Wstrict-prototypes") +set(CWARN "-Wall -Wextra") # Define C++ warning options here set(CPPWARN "-Wall -Wextra") diff --git a/firmware/baseband/sd_over_usb/hackrf_core.c b/firmware/baseband/sd_over_usb/hackrf_core.c index 73d91a4b4..bf20577c4 100644 --- a/firmware/baseband/sd_over_usb/hackrf_core.c +++ b/firmware/baseband/sd_over_usb/hackrf_core.c @@ -744,8 +744,6 @@ void cpu_clock_init(void) CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); - // \/ breaks below - #if (defined JAWBREAKER || defined HACKRF_ONE) /* Disable unused clocks */ /* Start with PLLs */ @@ -775,9 +773,6 @@ void cpu_clock_init(void) CGU_BASE_CGU_OUT0_CLK = CGU_BASE_CGU_OUT0_CLK_PD(1); CGU_BASE_CGU_OUT1_CLK = CGU_BASE_CGU_OUT1_CLK_PD(1); -// /\ breaks above - - /* Disable unused peripheral clocks */ CCU1_CLK_APB1_CAN1_CFG = 0; CCU1_CLK_APB1_I2S_CFG = 0; diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp index 8a6dcfb99..3645804e4 100644 --- a/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp +++ b/firmware/baseband/sd_over_usb/proc_sd_over_usb.cpp @@ -23,9 +23,6 @@ #include "ch.h" #include "hal.h" -#include "proc_sd_over_usb.hpp" -#include "portapack_shared_memory.hpp" - extern "C" { void start_usb(void); void irq_usb(void); diff --git a/firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp b/firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp deleted file mode 100644 index 5aba4227d..000000000 --- a/firmware/baseband/sd_over_usb/proc_sd_over_usb.hpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. - * Copyright (C) 2023 Bernd Herzog - * - * This file is part of PortaPack. - * - * This program 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 2, or (at your option) - * any later version. - * - * This program 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 this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __UI_PROC_SD_OVER_USB_H__ -#define __UI_PROC_SD_OVER_USB_H__ - -#include "portapack_shared_memory.hpp" -#include "baseband_processor.hpp" -#include "baseband_thread.hpp" - - -class USBProcessor : public BasebandProcessor { -public: - void execute(const buffer_c8_t&) override {}; - - //void on_message(const Message* const p) override; - -private: - - - //bool configured { false }; - - //BasebandThread baseband_thread { 3072000, this, NORMALPRIO + 20, baseband::Direction::Transmit }; - - - //RequestSignalMessage sig_message { RequestSignalMessage::Signal::FillRequest }; -}; - -#endif /*__UI_PROC_SD_OVER_USB_H__*/ diff --git a/firmware/baseband/sd_over_usb/scsi.h b/firmware/baseband/sd_over_usb/scsi.h index 7c74ca140..ff399a3d0 100644 --- a/firmware/baseband/sd_over_usb/scsi.h +++ b/firmware/baseband/sd_over_usb/scsi.h @@ -133,7 +133,6 @@ static inline uint16_t bswap_16(const uint16_t x) __attribute__ ((always_inline)); static inline uint16_t bswap_16(const uint16_t x) { - uint8_t tmp; union { uint16_t x; uint8_t b[2]; } data; @@ -150,9 +149,7 @@ static inline uint32_t bswap_32(const uint32_t x) __attribute__ ((const)) __attribute__ ((always_inline)); - static inline uint32_t bswap_32(const uint32_t x) { - uint8_t tmp; union { uint32_t x; uint8_t b[4]; } data; @@ -173,8 +170,6 @@ static inline uint32_t bswap_32(const uint32_t x) { #define cpu_to_be16(x) bswap_16(x) #define cpu_to_be32(x) bswap_32(x) - - void scsi_command(msd_cbw_t *msd_cbw_data); #endif /* __SCSI_H__ */ \ No newline at end of file diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.h b/firmware/baseband/sd_over_usb/sd_over_usb.h index 1d1622c26..37e4e2296 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.h +++ b/firmware/baseband/sd_over_usb/sd_over_usb.h @@ -22,7 +22,6 @@ #ifndef __USB_SD_OVER_USB_H__ #define __USB_SD_OVER_USB_H__ - #include #include #include From 6fadd70c1daedd4997fdcf32def28e7556f20aea Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 1 Apr 2023 19:16:01 +0200 Subject: [PATCH 09/11] updated ui --- firmware/application/apps/ui_sd_over_usb.cpp | 13 +++++++++++++ firmware/application/apps/ui_sd_over_usb.hpp | 8 ++++++-- firmware/application/portapack.cpp | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/firmware/application/apps/ui_sd_over_usb.cpp b/firmware/application/apps/ui_sd_over_usb.cpp index 0bc3095b1..82da9d345 100644 --- a/firmware/application/apps/ui_sd_over_usb.cpp +++ b/firmware/application/apps/ui_sd_over_usb.cpp @@ -32,6 +32,19 @@ SdOverUsbView::SdOverUsbView(NavigationView& nav) : nav_ (nav) { }); button_run.on_select = [this](Button&) { + ui::Painter painter; + painter.fill_rectangle( + { 0, 0, portapack::display.width(), portapack::display.height() }, + ui::Color::black() + ); + + painter.draw_bitmap( + { portapack::display.width()/2-8, portapack::display.height()/2-8 }, + bitmap_icon_hackrf, + ui::Color::yellow(), + ui::Color::black() + ); + sdcDisconnect(&SDCD1); sdcStop(&SDCD1); diff --git a/firmware/application/apps/ui_sd_over_usb.hpp b/firmware/application/apps/ui_sd_over_usb.hpp index e00868052..99d31290c 100644 --- a/firmware/application/apps/ui_sd_over_usb.hpp +++ b/firmware/application/apps/ui_sd_over_usb.hpp @@ -46,11 +46,15 @@ private: NavigationView& nav_; Labels labels { - { { 40, 4 }, "This will provide access\nto the SD card over USB.", Color::white() } + { { 3 * 8, 2 * 16 }, "Click Run to start the", Color::white() }, + { { 3 * 8, 3 * 16 }, "USB Mass Storage Mode.", Color::white() }, + { { 3 * 8, 5 * 16 }, "It can take up to 20s", Color::white() }, + { { 3 * 8, 6 * 16 }, "for the drive to be.", Color::white() }, + { { 3 * 8, 7 * 16 }, "available.", Color::white() }, }; Button button_run { - { 2 * 8, 15 * 16, 12 * 8, 3 * 16 }, + { 9 * 8, 15 * 16, 12 * 8, 3 * 16 }, "Run" }; }; diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index 6a7f3376a..c72371715 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -518,7 +518,7 @@ bool init() { void shutdown(const bool leave_screen_on) { gpdma::controller.disable(); - if (leave_screen_on) { + if (!leave_screen_on) { backlight()->off(); display.shutdown(); } From a8f0c8eac9d7f00f79b16e18be15f1f9ac3a1fad Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 1 Apr 2023 19:24:13 +0200 Subject: [PATCH 10/11] refactoring --- firmware/baseband/sd_over_usb/diskio.c | 22 ++++++++++++++++++++ firmware/baseband/sd_over_usb/diskio.h | 22 ++++++++++++++++++++ firmware/baseband/sd_over_usb/scsi.c | 23 ++++++++++++++++++++- firmware/baseband/sd_over_usb/scsi.h | 22 ++++++++++++++++++++ firmware/baseband/sd_over_usb/sd_over_usb.c | 22 ++++++++++++++++++++ firmware/baseband/sd_over_usb/sd_over_usb.h | 5 +++-- 6 files changed, 113 insertions(+), 3 deletions(-) diff --git a/firmware/baseband/sd_over_usb/diskio.c b/firmware/baseband/sd_over_usb/diskio.c index 2417e4a2f..e3d5f8506 100644 --- a/firmware/baseband/sd_over_usb/diskio.c +++ b/firmware/baseband/sd_over_usb/diskio.c @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #include "diskio.h" #include "ch.h" diff --git a/firmware/baseband/sd_over_usb/diskio.h b/firmware/baseband/sd_over_usb/diskio.h index 7b0cd0643..2dde43e73 100644 --- a/firmware/baseband/sd_over_usb/diskio.h +++ b/firmware/baseband/sd_over_usb/diskio.h @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef __DISKIO_H__ #define __DISKIO_H__ diff --git a/firmware/baseband/sd_over_usb/scsi.c b/firmware/baseband/sd_over_usb/scsi.c index f3e037872..d5d8b386b 100644 --- a/firmware/baseband/sd_over_usb/scsi.c +++ b/firmware/baseband/sd_over_usb/scsi.c @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #include "scsi.h" #include "diskio.h" @@ -203,7 +225,6 @@ void scsi_command(msd_cbw_t *msd_cbw_data) { status = handle_inquiry_serial_number(msd_cbw_data); } else if ((msd_cbw_data->cmd_data[1] & 0b11) || msd_cbw_data->cmd_data[2] != 0) { - //TODO: implement sense status = 1; } else { diff --git a/firmware/baseband/sd_over_usb/scsi.h b/firmware/baseband/sd_over_usb/scsi.h index ff399a3d0..9381bdff3 100644 --- a/firmware/baseband/sd_over_usb/scsi.h +++ b/firmware/baseband/sd_over_usb/scsi.h @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #ifndef __SCSI_H__ #define __SCSI_H__ diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.c b/firmware/baseband/sd_over_usb/sd_over_usb.c index 1d720d984..e2863da5a 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.c +++ b/firmware/baseband/sd_over_usb/sd_over_usb.c @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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 this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + #include "sd_over_usb.h" #include "scsi.h" diff --git a/firmware/baseband/sd_over_usb/sd_over_usb.h b/firmware/baseband/sd_over_usb/sd_over_usb.h index 37e4e2296..b886c8665 100644 --- a/firmware/baseband/sd_over_usb/sd_over_usb.h +++ b/firmware/baseband/sd_over_usb/sd_over_usb.h @@ -1,7 +1,8 @@ /* - * Copyright 2023 Bernd Herzog + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog * - * This file is part of HackRF. + * This file is part of PortaPack. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 04392752d10d216ca45e036f3caa9627f83ddebb Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 1 Apr 2023 19:38:38 +0200 Subject: [PATCH 11/11] fixed spelling error --- firmware/application/apps/ui_sd_over_usb.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/apps/ui_sd_over_usb.hpp b/firmware/application/apps/ui_sd_over_usb.hpp index 99d31290c..9df6421ac 100644 --- a/firmware/application/apps/ui_sd_over_usb.hpp +++ b/firmware/application/apps/ui_sd_over_usb.hpp @@ -49,7 +49,7 @@ private: { { 3 * 8, 2 * 16 }, "Click Run to start the", Color::white() }, { { 3 * 8, 3 * 16 }, "USB Mass Storage Mode.", Color::white() }, { { 3 * 8, 5 * 16 }, "It can take up to 20s", Color::white() }, - { { 3 * 8, 6 * 16 }, "for the drive to be.", Color::white() }, + { { 3 * 8, 6 * 16 }, "for the drive to be", Color::white() }, { { 3 * 8, 7 * 16 }, "available.", Color::white() }, };