timestamp_query::timestamp_query(device const& dvc, dx12u::cmd_queue const& q, int gpu_ordinal, std::size_t max_num_query) : num_query(max_num_query) { if (!dvc.Get()) { throw error{ "null device" }; } std::uint32_t gpu_mask = gpu_ordinal < 0 ? 1 : (1u << static_cast<std::uint32_t>(gpu_ordinal)); // alloc query buffer size_t buf_aligned_sz = (num_query * sizeof(std::uint64_t) + 4095) & ~4095; // page aligned auto heap_read_back = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK, gpu_mask, gpu_mask); auto buffer_desc = CD3DX12_RESOURCE_DESC::Buffer(buf_aligned_sz); auto r = dvc->CreateCommittedResource(&heap_read_back, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&buffer)); dx12u::throw_if_error(r, "timestamp resource creation failure"); // query heap D3D12_QUERY_HEAP_DESC heap_desc{}; heap_desc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; heap_desc.Count = static_cast<std::uint32_t>(num_query); heap_desc.NodeMask = gpu_mask; r = dvc->CreateQueryHeap(&heap_desc, IID_PPV_ARGS(&qh)); dx12u::throw_if_error(r, "timestamp query heap creation failure"); // clock frequency dvc->SetStablePowerState(true); q.get_com_ptr()->GetTimestampFrequency(&clock_freq); }
ibuffer::ibuffer(const device &device, const vk::BufferUsageFlags flags, const void *data, const size_t size) : device_(device), size_(size) { handle_ = device.create_buffer( vk::BufferCreateInfo() .size(static_cast<vk::DeviceSize>(size)) .usage(flags)); gpumem_ = gpu_memory( device, device.get_buffer_memory_requirements(handle_), vk::MemoryPropertyFlagBits::eHostVisible, data); device.bind_buffer_memory(handle_, gpumem_.handle(), 0); }
device default_device() { static device dev; if (!dev.id()) { platform pl = default_platform(); std::vector<device> devices = pl.devices(device::accelerator); if (devices.size()) dev = devices[0]; else // no accelerators found, try all { std::vector<device> devices = pl.devices(device::all); if (devices.size()) dev = devices[0]; else OVXX_DO_THROW(std::runtime_error("No OpenCL devices found.")); } } return dev; }
descriptor_set_layout::descriptor_set_layout(const device &device, const vector<vk::DescriptorSetLayoutBinding> &bindings) : device_(device) { handle_ = device.create_descriptor_set_layout( vk::DescriptorSetLayoutCreateInfo() .bindingCount(static_cast<uint32_t>(bindings.size())) .pBindings(bindings.data())); }
context(device const &d, cl_context_properties *props = 0) { OVXX_PRECONDITION(d.id() != 0); cl_device_id id = d.id(); cl_int status; impl_ = clCreateContext(props, 1, &id, context::callback, this, &status); if (status < 0) OVXX_DO_THROW(exception("clCreateContext", status)); }
static boost::shared_ptr<parameter_cache> get_global_cache(const device &device) { // device name -> parameter cache typedef std::map<std::string, boost::shared_ptr<parameter_cache> > cache_map; BOOST_COMPUTE_DETAIL_GLOBAL_STATIC(cache_map, caches, ((std::less<std::string>()))); cache_map::iterator iter = caches.find(device.name()); if(iter == caches.end()){ boost::shared_ptr<parameter_cache> cache = boost::make_shared<parameter_cache>(device); caches.insert(iter, std::make_pair(device.name(), cache)); return cache; } else { return iter->second; } }
genericKeyboard(cpu* host, device* keyboardProvider=NULL) { this->host = host; this->keyboardProvider = keyboardProvider; host->addHardware(this); reset(); if (keyboardProvider == NULL) std::cout << "Warning: Keyboard has no display to attach to. Keyboard will still connect to dcpu16, but will be disabled." << std::endl; else keyboardProvider->registerKeyHandler(this); }
parameter_cache(const device &device) : m_dirty(false), m_device_name(device.name()) { #ifdef BOOST_COMPUTE_USE_OFFLINE_CACHE // get offline cache file name (e.g. /home/user/.boost_compute/tune/device.json) m_file_name = make_file_name(); // load parameters from offline cache file (if it exists) if(boost::filesystem::exists(m_file_name)){ read_from_disk(); } #endif // BOOST_COMPUTE_USE_OFFLINE_CACHE }
T get_work_group_info(const device &device, cl_kernel_work_group_info info) { T value; cl_int ret = clGetKernelWorkGroupInfo(m_kernel, device.id(), info, sizeof(T), &value, 0); if(ret != CL_SUCCESS){ BOOST_THROW_EXCEPTION(runtime_exception(ret)); } return value; }
descriptor_pool::descriptor_pool(const device &device) : device_(device) { vector<vk::DescriptorPoolSize> poolSizes = { vk::DescriptorPoolSize() .type(vk::DescriptorType::eUniformBuffer) .descriptorCount(1), vk::DescriptorPoolSize() .type(vk::DescriptorType::eCombinedImageSampler) .descriptorCount(1) }; handle_ = device.create_descriptor_pool( vk::DescriptorPoolCreateInfo() .poolSizeCount(static_cast<uint32_t>(poolSizes.size())) .pPoolSizes(poolSizes.data()) .maxSets(1)); }
void set_pu_control(device & device, int subdevice, rs_option option, int value) { auto handle = device.get_subdevice(subdevice).handle; int ct_unit = 0, pu_unit = 0; for(auto ct = uvc_get_input_terminals(handle); ct; ct = ct->next) ct_unit = ct->bTerminalID; // todo - Check supported caps for(auto pu = uvc_get_processing_units(handle); pu; pu = pu->next) pu_unit = pu->bUnitID; // todo - Check supported caps switch(option) { case RS_OPTION_COLOR_BACKLIGHT_COMPENSATION: return set_pu<uint16_t>(handle, subdevice, pu_unit, UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, value); case RS_OPTION_COLOR_BRIGHTNESS: return set_pu<int16_t>(handle, subdevice, pu_unit, UVC_PU_BRIGHTNESS_CONTROL, value); case RS_OPTION_COLOR_CONTRAST: return set_pu<uint16_t>(handle, subdevice, pu_unit, UVC_PU_CONTRAST_CONTROL, value); case RS_OPTION_COLOR_EXPOSURE: return set_pu<uint32_t>(handle, subdevice, ct_unit, UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, value); case RS_OPTION_COLOR_GAIN: return set_pu<uint16_t>(handle, subdevice, pu_unit, UVC_PU_GAIN_CONTROL, value); case RS_OPTION_COLOR_GAMMA: return set_pu<uint16_t>(handle, subdevice, pu_unit, UVC_PU_GAMMA_CONTROL, value); case RS_OPTION_COLOR_HUE: return; // set_pu<int16_t>(handle, subdevice, pu_unit, UVC_PU_HUE_CONTROL, value); // Causes LIBUSB_ERROR_PIPE, may be related to not being able to set UVC_PU_HUE_AUTO_CONTROL case RS_OPTION_COLOR_SATURATION: return set_pu<uint16_t>(handle, subdevice, pu_unit, UVC_PU_SATURATION_CONTROL, value); case RS_OPTION_COLOR_SHARPNESS: return set_pu<uint16_t>(handle, subdevice, pu_unit, UVC_PU_SHARPNESS_CONTROL, value); case RS_OPTION_COLOR_WHITE_BALANCE: return set_pu<uint16_t>(handle, subdevice, pu_unit, UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, value); case RS_OPTION_COLOR_ENABLE_AUTO_EXPOSURE: return set_pu<uint8_t>(handle, subdevice, ct_unit, UVC_CT_AE_MODE_CONTROL, value ? 2 : 1); // Modes - (1: manual) (2: auto) (4: shutter priority) (8: aperture priority) case RS_OPTION_COLOR_ENABLE_AUTO_WHITE_BALANCE: return set_pu<uint8_t>(handle, subdevice, pu_unit, UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, value); default: throw std::logic_error("invalid option"); } }
/** * Draw the enlarged schema. This methods can only * be called after the block have been placed */ void decorateSchema::draw(device& dev) { assert(placed()); fSchema->draw(dev); #if 0 // draw enlarge input wires for (unsigned int i=0; i<inputs(); i++) { point p = inputPoint(i); point q = fSchema->inputPoint(i); dev.trait(p.x, p.y, q.x, q.y); } // draw enlarge output wires for (unsigned int i=0; i<outputs(); i++) { point p = outputPoint(i); point q = fSchema->outputPoint(i); dev.trait(p.x, p.y, q.x, q.y); } #endif // define the coordinates of the frame double tw = (2+fText.size())*dLetter*0.75; double x0 = x() + fMargin/2; // left double y0 = y() + fMargin/2; // top double x1 = x() + width() - fMargin/2; // right double y1 = y() + height() - fMargin/2; // bottom //double tl = x0 + 2*dWire; // left of text zone double tl = x() + fMargin; // left of text zone double tr = min(tl+tw, x1); // right of text zone // draw the surronding frame dev.dasharray(x0, y0, x0, y1); // left line dev.dasharray(x0, y1, x1, y1); // bottom line dev.dasharray(x1, y1, x1, y0); // right line dev.dasharray(x0, y0, tl, y0); // top segment before text dev.dasharray(tr, y0, x1, y0); // top segment after text // draw the label dev.label(tl, y0, fText.c_str()); // }
void set_control(device & device, const extension_unit & xu, uint8_t ctrl, void * data, int len) { int status = uvc_set_ctrl(device.get_subdevice(xu.subdevice).handle, xu.unit, ctrl, data, len); if(status < 0) throw std::runtime_error(to_string() << "uvc_set_ctrl(...) returned " << libusb_error_name(status)); }
void set_subdevice_mode(device & device, int subdevice_index, int width, int height, uint32_t fourcc, int fps, std::function<void(const void * frame)> callback) { auto & sub = device.get_subdevice(subdevice_index); check("get_stream_ctrl_format_size", uvc_get_stream_ctrl_format_size(sub.handle, &sub.ctrl, reinterpret_cast<const big_endian<uint32_t> &>(fourcc), width, height, fps)); sub.callback = callback; }
text_2d::text_2d(device const& dev, std::size_t max_str_size, std::size_t max_num_str, std::size_t max_buffered_frame, bool enable_filtering) : max_word_sz(max_str_size), max_num_word(max_num_str) { assert(max_str_size > 0 && max_num_str > 0 && max_buffered_frame > 0); if (dev.Get() == nullptr) { throw error{ "null device" }; } words.resize(max_buffered_frame); size_t const num_cb = max_num_str * max_buffered_frame; size_t const num_tex = 1; // 1 text texture srd_heap = dx12u::descriptor_heap{ dev.Get(), D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, num_cb + num_tex }; auto cb_sz = get_cb_size(max_str_size); auto cb_total_sz = get_cb_size(max_str_size) * num_cb; // alloc and upload texture { auto font_data = load_font_texture(); gu::mip_lvl_texture_view mip_view{}; mip_view.width = global::font_texture_width; mip_view.height = global::font_texture_height; mip_view.pitch = mip_view.width; mip_view.slice_sz = font_data.size(); mip_view.data = font_data.data(); gu::texture_view tex_view{}; tex_view.bpp = 1; tex_view.num_lvl = 1; tex_view.mip = &mip_view; dx12u::cmd_queue q{ dev }; dx12u::cmd_allocator allocator{ dev }; dx12u::gfx_cmd_list cl = allocator.alloc(); auto tex = dx12u::make_texture(dev, cl, tex_view, false, false, DXGI_FORMAT_R8_UNORM); cl->Close(); q.push(cl); q.sync(); font_texture = tex.texture_rsrc; dev->CreateShaderResourceView(font_texture.Get(), &tex.srv_desc, srd_heap.get_cpu_handle(0)); } // alloc cb_mem { auto upload_heap = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); auto buffer_desc = CD3DX12_RESOURCE_DESC::Buffer(cb_total_sz); auto r = dev->CreateCommittedResource(&upload_heap, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&cb_mem)); dx12u::throw_if_error(r); for (size_t i = 0; i < num_cb; ++i) { // sh_mask_cb views D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {}; cbv_desc.SizeInBytes = static_cast<uint32_t>(cb_sz); cbv_desc.BufferLocation = cb_mem->GetGPUVirtualAddress() + i * cb_sz; dev->CreateConstantBufferView(&cbv_desc, srd_heap.get_cpu_handle(num_tex + i)); } r = cb_mem->Map(0, nullptr, reinterpret_cast<void**>(&cb_ptr)); dx12u::throw_if_error(r); assert(!!cb_ptr); memset(cb_ptr, 0, cb_total_sz); } // pso { // root signature auto filter = enable_filtering ? D3D12_FILTER_MIN_MAG_MIP_LINEAR : D3D12_FILTER_MIN_MAG_MIP_POINT; dx12u::descriptor_sig_list descriptor_table0{}; dx12u::descriptor_sig_list descriptor_table1{}; descriptor_table0.append(dx12u::descriptor_sig{ dx12u::descriptor_type::srv, 0, 0, dx12u::shader_mask::ps }); descriptor_table1.append(dx12u::descriptor_sig{ dx12u::descriptor_type::cbv, 0, 0, dx12u::shader_mask::vs }); dx12u::descriptor_sig_list dsl{}; dsl.append(descriptor_table0); // TODO move to root once the number of sgpr is definite dsl.append(descriptor_table1); dx12u::static_sampler_list sl = { dx12u::make_default_static_sampler(0, filter), }; rs = dx12u::make_root_signature(dev.Get(), dsl, sl); // shader preprocessor definitions auto const texture_char_w = static_cast<double>(global::font_texture_char_w) / static_cast<double>(global::font_texture_width); using macro = std::pair<std::string, std::string>; macro max_str_macro = macro{ "MAX_STR_SZ", std::to_string(max_str_size) }; macro char_w_macro = macro{ "CHAR_WIDTH", std::to_string(texture_char_w) }; D3D_SHADER_MACRO def[] = { max_str_macro.first.c_str(), max_str_macro.second.c_str(), char_w_macro.first.c_str(), char_w_macro.second.c_str(), nullptr, nullptr }; // shader blobs auto vs = dx12u::compile_from_file("../../framework/d3d12/shader/ui/text2d.hlsl", def, "vs_main", "vs_5_0"); auto ps = dx12u::compile_from_file("../../framework/d3d12/shader/ui/text2d.hlsl", def, "ps_main", "ps_5_0"); // pso pso = dx12u::pipeline_state_object{ dev, rs, vs, ps }; D3D12_BLEND_DESC bd = CD3DX12_BLEND_DESC(D3D12_DEFAULT); bd.RenderTarget[0].BlendEnable = true; bd.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; bd.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; pso.set_blend_states(bd); pso.set_depth_test(false); pso.commit(); } }
T get_build_info(cl_program_build_info info, const device &device) const { return detail::get_object_info<T>(clGetProgramBuildInfo, m_program, info, device.id()); }
bool btlelibscanfilter::process(device &dev, adv_fields &fields, int rssi) { return dev.advertisement_fields().is_service_advertiset(uuid(BTLE_SERVICE)); }
playback(device d) : playback(d.get()) {}
recorder(device d) : recorder(d.get()) {}
bool device::operator == (const device& other) const { return bda_ == other.addr(); }
bool can_access_peer(device const &other) { int result; CUDAPP_CALL_GUARDED(cuDeviceCanAccessPeer, (&result, handle(), other.handle())); return result; }
static void hpxcl_single_initialize( hpx::naming::id_type node_id, size_t vector_size) { // Query all devices on local node std::vector<device> devices = get_devices( node_id, CL_DEVICE_TYPE_GPU, "OpenCL 1.1" ).get(); /* // print devices hpx::cout << "Devices:" << hpx::endl; for(cl_uint i = 0; i < devices.size(); i++) { device cldevice = devices[i]; // Query name std::string device_name = device::device_info_to_string( cldevice.get_device_info(CL_DEVICE_NAME)); std::string device_vendor = device::device_info_to_string( cldevice.get_device_info(CL_DEVICE_VENDOR)); hpx::cout << i << ": " << device_name << " (" << device_vendor << ")" << hpx::endl; } // Lets you choose a device size_t device_num; hpx::cout << "Choose device: " << hpx::endl; std::cin >> device_num; if(device_num < 0 || device_num >= devices.size()) exit(0); // Select a device hpxcl_single_device = devices[device_num]; */ size_t device_id = 0; // print device hpx::cout << "Device:" << hpx::endl; { device cldevice = devices[device_id]; // Query name std::string device_name = device::device_info_to_string( cldevice.get_device_info(CL_DEVICE_NAME)); std::string device_vendor = device::device_info_to_string( cldevice.get_device_info(CL_DEVICE_VENDOR)); hpx::cout << " " << device_name << " (" << device_vendor << ")" << hpx::endl; } // Select a device hpxcl_single_device = devices[device_id]; // Create program hpxcl_single_program = hpxcl_single_device.create_program_with_source( gpu_code); // Build program hpxcl_single_program.build(); // Create kernels hpxcl_single_log_kernel = hpxcl_single_program.create_kernel("logn"); hpxcl_single_exp_kernel = hpxcl_single_program.create_kernel("expn"); hpxcl_single_mul_kernel = hpxcl_single_program.create_kernel("mul"); hpxcl_single_add_kernel = hpxcl_single_program.create_kernel("add"); hpxcl_single_dbl_kernel = hpxcl_single_program.create_kernel("dbl"); // Generate buffers hpxcl_single_buffer_a = hpxcl_single_device.create_buffer( CL_MEM_READ_ONLY, vector_size * sizeof(float)); hpxcl_single_buffer_b = hpxcl_single_device.create_buffer( CL_MEM_READ_ONLY, vector_size * sizeof(float)); hpxcl_single_buffer_c = hpxcl_single_device.create_buffer( CL_MEM_READ_ONLY, vector_size * sizeof(float)); hpxcl_single_buffer_m = hpxcl_single_device.create_buffer( CL_MEM_READ_WRITE, vector_size * sizeof(float)); hpxcl_single_buffer_n = hpxcl_single_device.create_buffer( CL_MEM_READ_WRITE, vector_size * sizeof(float)); hpxcl_single_buffer_o = hpxcl_single_device.create_buffer( CL_MEM_READ_WRITE, vector_size * sizeof(float)); hpxcl_single_buffer_p = hpxcl_single_device.create_buffer( CL_MEM_READ_WRITE, vector_size * sizeof(float)); hpxcl_single_buffer_z = hpxcl_single_device.create_buffer( CL_MEM_WRITE_ONLY, vector_size * sizeof(float)); // Initialize a list of future events for asynchronous set_arg calls std::vector<shared_future<void>> set_arg_futures; // set kernel args for exp set_arg_futures.push_back( hpxcl_single_exp_kernel.set_arg_async(0, hpxcl_single_buffer_m)); set_arg_futures.push_back( hpxcl_single_exp_kernel.set_arg_async(1, hpxcl_single_buffer_b)); // set kernel args for add set_arg_futures.push_back( hpxcl_single_add_kernel.set_arg_async(0, hpxcl_single_buffer_n)); set_arg_futures.push_back( hpxcl_single_add_kernel.set_arg_async(1, hpxcl_single_buffer_a)); set_arg_futures.push_back( hpxcl_single_add_kernel.set_arg_async(2, hpxcl_single_buffer_m)); // set kernel args for dbl set_arg_futures.push_back( hpxcl_single_dbl_kernel.set_arg_async(0, hpxcl_single_buffer_o)); set_arg_futures.push_back( hpxcl_single_dbl_kernel.set_arg_async(1, hpxcl_single_buffer_c)); // set kernel args for mul set_arg_futures.push_back( hpxcl_single_mul_kernel.set_arg_async(0, hpxcl_single_buffer_p)); set_arg_futures.push_back( hpxcl_single_mul_kernel.set_arg_async(1, hpxcl_single_buffer_n)); set_arg_futures.push_back( hpxcl_single_mul_kernel.set_arg_async(2, hpxcl_single_buffer_o)); // set kernel args for log set_arg_futures.push_back( hpxcl_single_log_kernel.set_arg_async(0, hpxcl_single_buffer_z)); set_arg_futures.push_back( hpxcl_single_log_kernel.set_arg_async(1, hpxcl_single_buffer_p)); // wait for function calls to trigger BOOST_FOREACH(shared_future<void> & future, set_arg_futures) { future.wait(); } }
static CUcontext create(device dev, unsigned flags) { CUcontext h = 0; cuda_check( cuCtxCreate(&h, flags, dev.raw()) ); return h; }
void bulk_transfer(device & device, unsigned char endpoint, void * data, int length, int *actual_length, unsigned int timeout) { int status = libusb_bulk_transfer(device.get_subdevice(0).handle->usb_devh, endpoint, (unsigned char *)data, length, actual_length, timeout); if(status < 0) throw std::runtime_error(to_string() << "libusb_bulk_transfer(...) returned " << libusb_error_name(status)); }
void print_device_info(device d) { cout << "Device id " << (cl_device_id)d << ": " << d.name() << endl; cout << " Compute units: " << d.compute_units() << endl; cout << " Max Sub-devices: " << d.max_subdevices() << endl; cout << " Address bits: " << d.address_bits() << endl; cout << " Global Cache Size: " << d.global_cache_size() << endl; cout << " Cacheline Size: " << d.global_cacheline_size() << endl; cout << " Global Memory Size: " << d.global_mem_size() << endl; cout << " Host-unified Memory: " << (d.host_unified_memory() ? "yes" : " no") << endl; cout << " Max Work Group Size: " << d.max_work_group_size() << endl; vector<size_t> s = d.max_work_item_dimensions(); cout << " Max Work Item Sizes: (" << s[0] << ", " << s[1] << ", " << s[2] << ")" << endl; cout << " Float Vector Width: " << d.native_float_vector_width() << endl; }
void seqSchema::drawInternalWires(device& dev) { assert (fSchema1->outputs() == fSchema2->inputs()); const int N = fSchema1->outputs(); double dx = 0; double mx = 0; int dir =-1; if (orientation() == kLeftRight) { // draw left right cables for (int i=0; i<N; i++) { point src = fSchema1->outputPoint(i); point dst = fSchema2->inputPoint(i); int d = direction(src,dst); if (d != dir) { // compute attributes of new direction switch (d) { case kUpDir : mx = 0; dx = dWire; break; case kDownDir : mx = fHorzGap; dx = -dWire; break; default : mx = 0; dx = 0; break; } dir = d; } else { // move in same direction mx = mx +dx; } if (src.y == dst.y) { // draw straight cable dev.trait(src.x, src.y, dst.x, dst.y); } else { // draw zizag cable dev.trait(src.x, src.y, src.x+mx, src.y); dev.trait(src.x+mx, src.y, src.x+mx, dst.y); dev.trait(src.x+mx, dst.y, dst.x, dst.y); } } } else { // draw right left cables for (int i=0; i<N; i++) { point src = fSchema1->outputPoint(i); point dst = fSchema2->inputPoint(i); int d = direction(src,dst); if (d != dir) { // compute attributes of new direction switch (d) { case kUpDir : mx = -fHorzGap; dx = dWire; break; case kDownDir : mx = 0; dx = -dWire; break; default : mx = 0; dx = 0; break; } dir = d; } else { // move in same direction mx = mx +dx; } if (src.y == dst.y) { // draw straight cable dev.trait(src.x, src.y, dst.x, dst.y); } else { // draw zizag cable dev.trait(src.x, src.y, src.x+mx, src.y); dev.trait(src.x+mx, src.y, src.x+mx, dst.y); dev.trait(src.x+mx, dst.y, dst.x, dst.y); } } } }
cl::queue::queue(const context &__context, const device &__device) throw(cl_exception) : queue(__context.id(),__device.id()) { }
void claim_interface(device & device, const guid & interface_guid, int interface_number) { int status = libusb_claim_interface(device.get_subdevice(0).handle->usb_devh, interface_number); if(status < 0) throw std::runtime_error(to_string() << "libusb_claim_interface(...) returned " << libusb_error_name(status)); device.claimed_interfaces.push_back(interface_number); }