/* * 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 #include #include #include "tuning.h" #include "usb.h" #include "usb_standard_request.h" #include #include "usb_descriptor.h" #include "usb_device.h" #include "usb_endpoint.h" #include "usb_api_board_info.h" #include "usb_api_cpld.h" #include "usb_api_register.h" #include "usb_api_spiflash.h" #include "usb_api_operacake.h" #include "operacake.h" #include "usb_api_sweep.h" #include "usb_api_transceiver.h" #include "usb_bulk_buffer.h" #include "hackrf-ui.h" static const usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, usb_vendor_request_write_max2837, usb_vendor_request_read_max2837, usb_vendor_request_write_si5351c, usb_vendor_request_read_si5351c, usb_vendor_request_set_sample_rate_frac, usb_vendor_request_set_baseband_filter_bandwidth, #ifdef RAD1O NULL, NULL, #else usb_vendor_request_write_rffc5071, usb_vendor_request_read_rffc5071, #endif usb_vendor_request_erase_spiflash, usb_vendor_request_write_spiflash, usb_vendor_request_read_spiflash, NULL, // used to be write_cpld usb_vendor_request_read_board_id, usb_vendor_request_read_version_string, usb_vendor_request_set_freq, usb_vendor_request_set_amp_enable, usb_vendor_request_read_partid_serialno, usb_vendor_request_set_lna_gain, usb_vendor_request_set_vga_gain, usb_vendor_request_set_txvga_gain, NULL, // was set_if_freq #ifdef HACKRF_ONE usb_vendor_request_set_antenna_enable, #else NULL, #endif usb_vendor_request_set_freq_explicit, usb_vendor_request_read_wcid, // USB_WCID_VENDOR_REQ usb_vendor_request_init_sweep, usb_vendor_request_operacake_get_boards, usb_vendor_request_operacake_set_ports, usb_vendor_request_set_hw_sync_mode, usb_vendor_request_reset }; 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 usb_configuration_changed( usb_device_t* const device ) { /* Reset transceiver to idle state until other commands are received */ set_transceiver_mode(TRANSCEIVER_MODE_OFF); if( device->configuration->number == 1 ) { // transceiver configuration cpu_clock_pll1_max_speed(); led_on(LED1); } else { /* Configuration number equal 0 means usb bus reset. */ cpu_clock_pll1_low_speed(); led_off(LED1); } } void usb_set_descriptor_by_serial_number(void) { iap_cmd_res_t iap_cmd_res; /* Read IAP Serial Number Identification */ iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO; iap_cmd_call(&iap_cmd_res); if (iap_cmd_res.status_res.status_ret == CMD_SUCCESS) { usb_descriptor_string_serial_number[0] = USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN; usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING; /* 32 characters of serial number, convert to UTF-16LE */ for (size_t i=0; i> 3] >> (28 - (i & 7) * 4)) & 0xf; const char c = (nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble); usb_descriptor_string_serial_number[2 + i * 2] = c; usb_descriptor_string_serial_number[3 + i * 2] = 0x00; } } else { usb_descriptor_string_serial_number[0] = 2; usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING; } } int main(void) { pin_setup(); enable_1v8_power(); #if (defined HACKRF_ONE || defined RAD1O) enable_rf_power(); delay(1000000); #endif cpu_clock_init(); usb_set_descriptor_by_serial_number(); usb_set_configuration_changed_cb(usb_configuration_changed); 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); hackrf_ui_init(); usb_run(&usb_device); rf_path_init(&rf_path); operacake_init(); unsigned int phase = 0; while(true) { // Check whether we need to initiate a CPLD update if (start_cpld_update) cpld_update(); // Check whether we need to initiate sweep mode if (start_sweep_mode) { start_sweep_mode = false; sweep_mode(); } start_streaming_on_hw_sync(); // Set up IN transfer of buffer 0. if ( usb_bulk_buffer_offset >= 16384 && phase == 1 && transceiver_mode() != TRANSCEIVER_MODE_OFF) { usb_transfer_schedule_block( (transceiver_mode() == TRANSCEIVER_MODE_RX) ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, &usb_bulk_buffer[0x0000], 0x4000, NULL, NULL ); phase = 0; } // Set up IN transfer of buffer 1. if ( usb_bulk_buffer_offset < 16384 && phase == 0 && transceiver_mode() != TRANSCEIVER_MODE_OFF) { usb_transfer_schedule_block( (transceiver_mode() == TRANSCEIVER_MODE_RX) ? &usb_endpoint_bulk_in : &usb_endpoint_bulk_out, &usb_bulk_buffer[0x4000], 0x4000, NULL, NULL ); phase = 1; } } return 0; }