/* M0 Core Manage USB */ int main(void) { iap_cmd_res_t iap_cmd_res; usb_descriptor_serial_number_t serial_number; airspy_usb_req_init(); 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); /* 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) { /* Only retrieve 2 last 32bits for Serial Number */ serial_number.sn_32b[0] = iap_cmd_res.status_res.iap_result[2]; serial_number.sn_32b[1] = iap_cmd_res.status_res.iap_result[3]; usb_descriptor_fill_string_serial_number(serial_number); } nvic_set_priority(NVIC_USB0_IRQ, 255); nvic_set_priority(NVIC_M4CORE_IRQ, 1); nvic_enable_irq(NVIC_M4CORE_IRQ); usb_run(&usb_device); while(true) { signal_wfe(); if( (get_usb_buffer_offset() >= 16384) && (phase == 1) ) { usb_transfer_schedule_block(&usb_endpoint_bulk_in, &usb_bulk_buffer[0x0000], 0x4000, NULL, NULL); phase = 0; } if( (get_usb_buffer_offset() < 16384) && (phase == 0) ) { usb_transfer_schedule_block(&usb_endpoint_bulk_in, &usb_bulk_buffer[0x4000], 0x4000, NULL, NULL); phase = 1; } } }
static void start_command_transfer() { usb_transfer_schedule_block(&usb_endpoint_bulk_cmd_out, command_buffer, sizeof(command_buffer), command_transfer_completed, NULL); }
usb_request_status_t usb_vendor_request_write_spiflash( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { uint32_t addr = 0; uint16_t len = 0; if (stage == USB_TRANSFER_STAGE_SETUP) { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) || ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else { usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, NULL, NULL); spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); w25q80bv_setup(&spi_flash); return USB_REQUEST_STATUS_OK; } } else if (stage == USB_TRANSFER_STAGE_DATA) { addr = (endpoint->setup.value << 16) | endpoint->setup.index; len = endpoint->setup.length; /* This check is redundant but makes me feel better. */ if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) || ((addr + len) > spi_flash.num_bytes)) { return USB_REQUEST_STATUS_STALL; } else { w25q80bv_program(&spi_flash, addr, len, &spiflash_buffer[0]); usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } } else { return USB_REQUEST_STATUS_OK; } }
usb_request_status_t usb_vendor_request_set_txvga_gain( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if( stage == USB_TRANSFER_STAGE_SETUP ) { const uint8_t value = max2837_set_txvga_gain(&max2837, endpoint->setup.index); endpoint->buffer[0] = value; if(value) hackrf_ui_setBBTXVGAGain(endpoint->setup.index); usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_OK; }
static usb_request_status_t usb_standard_request_get_status_setup( usb_endpoint_t* const endpoint ) { if( endpoint->setup.length == 2 ) { endpoint->buffer[0] = 0; endpoint->buffer[1] = 0; usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2, NULL, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } else { return USB_REQUEST_STATUS_STALL; } }
usb_request_status_t usb_vendor_request_spiflash_status( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { uint8_t data[2]; if (stage == USB_TRANSFER_STAGE_SETUP) { w25q80bv_get_full_status(&spi_flash, data); usb_transfer_schedule_block(endpoint->in, &data, 2, NULL, NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } else { return USB_REQUEST_STATUS_OK; } }
static usb_request_status_t usb_standard_request_get_configuration_setup( usb_endpoint_t* const endpoint ) { if( endpoint->setup.length == 1 ) { endpoint->buffer[0] = 0; if( endpoint->device->configuration ) { endpoint->buffer[0] = endpoint->device->configuration->number; } usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; } else { return USB_REQUEST_STATUS_STALL; } }
usb_request_status_t usb_vendor_request_set_freq_explicit( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { usb_transfer_schedule_block(endpoint->out, &explicit_params, sizeof(struct set_freq_explicit_params), NULL, NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { if (set_freq_explicit(explicit_params.if_freq_hz, explicit_params.lo_freq_hz, explicit_params.path)) { usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; } else { return USB_REQUEST_STATUS_OK; } }
static usb_request_status_t usb_send_descriptor( usb_endpoint_t* const endpoint, const uint8_t* const descriptor_data ) { const uint32_t setup_length = endpoint->setup.length; uint32_t descriptor_length = descriptor_data[0]; if( descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION ) { descriptor_length = (descriptor_data[3] << 8) | descriptor_data[2]; } // We cast the const away but this shouldn't be a problem as this is a write transfer usb_transfer_schedule_block( endpoint->in, (uint8_t* const) descriptor_data, (setup_length > descriptor_length) ? descriptor_length : setup_length, NULL, NULL ); usb_transfer_schedule_ack(endpoint->out); return USB_REQUEST_STATUS_OK; }
/* Set pin definitions, directions, etc */ usb_request_status_t usb_vendor_request_register_gpio( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { uint8_t in_count, i; if (stage == USB_TRANSFER_STAGE_SETUP) { usb_transfer_schedule_block(endpoint->out, &gpio_params, endpoint->setup.length/2, NULL, NULL); } else if (stage == USB_TRANSFER_STAGE_DATA) { in_count = endpoint->setup.value; for(i=0; i<in_count; i++) { GPIO_SET(gpio_in[gpio_in_count], (gpio_params[i]>>8)&0xFF, gpio_params[i]&0xFF); gpio_set(&gpio_in[gpio_in_count]); gpio_in_count++; } for(; i<endpoint->setup.length; i++) { GPIO_SET(gpio_out[gpio_out_count], (gpio_params[i]>>8)&0xFF, gpio_params[i]&0xFF); gpio_set(&gpio_out[gpio_out_count]); gpio_out_count++; } usb_transfer_schedule_ack(endpoint->in); }
usb_request_status_t usb_vendor_request_set_sample_rate_frac( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { usb_transfer_schedule_block(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t), NULL, NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { if( sample_rate_frac_set(set_sample_r_params.freq_hz * 2, set_sample_r_params.divider ) ) { usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; } else { return USB_REQUEST_STATUS_OK; } }
usb_request_status_t usb_vendor_request_set_freq( usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) { if (stage == USB_TRANSFER_STAGE_SETUP) { usb_transfer_schedule_block(endpoint->out, &set_freq_params, sizeof(set_freq_params_t), NULL, NULL); return USB_REQUEST_STATUS_OK; } else if (stage == USB_TRANSFER_STAGE_DATA) { const uint64_t freq = set_freq_params.freq_mhz * 1000000ULL + set_freq_params.freq_hz; if( set_freq(freq) ) { usb_transfer_schedule_ack(endpoint->in); return USB_REQUEST_STATUS_OK; } return USB_REQUEST_STATUS_STALL; } else { return USB_REQUEST_STATUS_OK; } }
void send_reply(void *data, uint16_t length) { usb_transfer_schedule_block(&usb_endpoint_bulk_cmd_in, data, length, reply_transfer_completed, NULL); }