162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * This is free and unencumbered software released into the public domain. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Anyone is free to copy, modify, publish, use, compile, sell, or 562306a36Sopenharmony_ci * distribute this software, either in source code form or as a compiled 662306a36Sopenharmony_ci * binary, for any purpose, commercial or non-commercial, and by any 762306a36Sopenharmony_ci * means. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * In jurisdictions that recognize copyright laws, the author or authors 1062306a36Sopenharmony_ci * of this software dedicate any and all copyright interest in the 1162306a36Sopenharmony_ci * software to the public domain. We make this dedication for the benefit 1262306a36Sopenharmony_ci * of the public at large and to the detriment of our heirs and 1362306a36Sopenharmony_ci * successors. We intend this dedication to be an overt act of 1462306a36Sopenharmony_ci * relinquishment in perpetuity of all present and future rights to this 1562306a36Sopenharmony_ci * software under copyright law. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1862306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1962306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2062306a36Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2162306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2262306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2362306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * For more information, please refer to <http://unlicense.org/> 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <libusb.h> 2962306a36Sopenharmony_ci#include <stdio.h> 3062306a36Sopenharmony_ci#include <string.h> 3162306a36Sopenharmony_ci#include <unistd.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define VENDOR 0x1d6b 3462306a36Sopenharmony_ci#define PRODUCT 0x0105 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define BUF_LEN 8192 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* 3962306a36Sopenharmony_ci * struct test_state - describes test program state 4062306a36Sopenharmony_ci * @list: list of devices returned by libusb_get_device_list function 4162306a36Sopenharmony_ci * @found: pointer to struct describing tested device 4262306a36Sopenharmony_ci * @ctx: context, set to NULL 4362306a36Sopenharmony_ci * @handle: handle of tested device 4462306a36Sopenharmony_ci * @attached: indicates that device was attached to kernel, and has to be 4562306a36Sopenharmony_ci * reattached at the end of test program 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistruct test_state { 4962306a36Sopenharmony_ci libusb_device *found; 5062306a36Sopenharmony_ci libusb_context *ctx; 5162306a36Sopenharmony_ci libusb_device_handle *handle; 5262306a36Sopenharmony_ci int attached; 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* 5662306a36Sopenharmony_ci * test_init - initialize test program 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciint test_init(struct test_state *state) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci int i, ret; 6262306a36Sopenharmony_ci ssize_t cnt; 6362306a36Sopenharmony_ci libusb_device **list; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci state->found = NULL; 6662306a36Sopenharmony_ci state->ctx = NULL; 6762306a36Sopenharmony_ci state->handle = NULL; 6862306a36Sopenharmony_ci state->attached = 0; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci ret = libusb_init(&state->ctx); 7162306a36Sopenharmony_ci if (ret) { 7262306a36Sopenharmony_ci printf("cannot init libusb: %s\n", libusb_error_name(ret)); 7362306a36Sopenharmony_ci return 1; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci cnt = libusb_get_device_list(state->ctx, &list); 7762306a36Sopenharmony_ci if (cnt <= 0) { 7862306a36Sopenharmony_ci printf("no devices found\n"); 7962306a36Sopenharmony_ci goto error1; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci for (i = 0; i < cnt; ++i) { 8362306a36Sopenharmony_ci libusb_device *dev = list[i]; 8462306a36Sopenharmony_ci struct libusb_device_descriptor desc; 8562306a36Sopenharmony_ci ret = libusb_get_device_descriptor(dev, &desc); 8662306a36Sopenharmony_ci if (ret) { 8762306a36Sopenharmony_ci printf("unable to get device descriptor: %s\n", 8862306a36Sopenharmony_ci libusb_error_name(ret)); 8962306a36Sopenharmony_ci goto error2; 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci if (desc.idVendor == VENDOR && desc.idProduct == PRODUCT) { 9262306a36Sopenharmony_ci state->found = dev; 9362306a36Sopenharmony_ci break; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci if (!state->found) { 9862306a36Sopenharmony_ci printf("no devices found\n"); 9962306a36Sopenharmony_ci goto error2; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci ret = libusb_open(state->found, &state->handle); 10362306a36Sopenharmony_ci if (ret) { 10462306a36Sopenharmony_ci printf("cannot open device: %s\n", libusb_error_name(ret)); 10562306a36Sopenharmony_ci goto error2; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (libusb_claim_interface(state->handle, 0)) { 10962306a36Sopenharmony_ci ret = libusb_detach_kernel_driver(state->handle, 0); 11062306a36Sopenharmony_ci if (ret) { 11162306a36Sopenharmony_ci printf("unable to detach kernel driver: %s\n", 11262306a36Sopenharmony_ci libusb_error_name(ret)); 11362306a36Sopenharmony_ci goto error3; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci state->attached = 1; 11662306a36Sopenharmony_ci ret = libusb_claim_interface(state->handle, 0); 11762306a36Sopenharmony_ci if (ret) { 11862306a36Sopenharmony_ci printf("cannot claim interface: %s\n", 11962306a36Sopenharmony_ci libusb_error_name(ret)); 12062306a36Sopenharmony_ci goto error4; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci return 0; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cierror4: 12762306a36Sopenharmony_ci if (state->attached == 1) 12862306a36Sopenharmony_ci libusb_attach_kernel_driver(state->handle, 0); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cierror3: 13162306a36Sopenharmony_ci libusb_close(state->handle); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cierror2: 13462306a36Sopenharmony_ci libusb_free_device_list(list, 1); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cierror1: 13762306a36Sopenharmony_ci libusb_exit(state->ctx); 13862306a36Sopenharmony_ci return 1; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* 14262306a36Sopenharmony_ci * test_exit - cleanup test program 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_civoid test_exit(struct test_state *state) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci libusb_release_interface(state->handle, 0); 14862306a36Sopenharmony_ci if (state->attached == 1) 14962306a36Sopenharmony_ci libusb_attach_kernel_driver(state->handle, 0); 15062306a36Sopenharmony_ci libusb_close(state->handle); 15162306a36Sopenharmony_ci libusb_exit(state->ctx); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ciint main(void) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct test_state state; 15762306a36Sopenharmony_ci struct libusb_config_descriptor *conf; 15862306a36Sopenharmony_ci struct libusb_interface_descriptor const *iface; 15962306a36Sopenharmony_ci unsigned char in_addr, out_addr; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (test_init(&state)) 16262306a36Sopenharmony_ci return 1; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci libusb_get_config_descriptor(state.found, 0, &conf); 16562306a36Sopenharmony_ci iface = &conf->interface[0].altsetting[0]; 16662306a36Sopenharmony_ci in_addr = iface->endpoint[0].bEndpointAddress; 16762306a36Sopenharmony_ci out_addr = iface->endpoint[1].bEndpointAddress; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci while (1) { 17062306a36Sopenharmony_ci static unsigned char buffer[BUF_LEN]; 17162306a36Sopenharmony_ci int bytes; 17262306a36Sopenharmony_ci libusb_bulk_transfer(state.handle, in_addr, buffer, BUF_LEN, 17362306a36Sopenharmony_ci &bytes, 500); 17462306a36Sopenharmony_ci libusb_bulk_transfer(state.handle, out_addr, buffer, BUF_LEN, 17562306a36Sopenharmony_ci &bytes, 500); 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci test_exit(&state); 17862306a36Sopenharmony_ci} 179