18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * This is free and unencumbered software released into the public domain.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Anyone is free to copy, modify, publish, use, compile, sell, or
58c2ecf20Sopenharmony_ci * distribute this software, either in source code form or as a compiled
68c2ecf20Sopenharmony_ci * binary, for any purpose, commercial or non-commercial, and by any
78c2ecf20Sopenharmony_ci * means.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * In jurisdictions that recognize copyright laws, the author or authors
108c2ecf20Sopenharmony_ci * of this software dedicate any and all copyright interest in the
118c2ecf20Sopenharmony_ci * software to the public domain. We make this dedication for the benefit
128c2ecf20Sopenharmony_ci * of the public at large and to the detriment of our heirs and
138c2ecf20Sopenharmony_ci * successors. We intend this dedication to be an overt act of
148c2ecf20Sopenharmony_ci * relinquishment in perpetuity of all present and future rights to this
158c2ecf20Sopenharmony_ci * software under copyright law.
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
188c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
198c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
208c2ecf20Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
218c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
228c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
238c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
248c2ecf20Sopenharmony_ci *
258c2ecf20Sopenharmony_ci * For more information, please refer to <http://unlicense.org/>
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#include <libusb.h>
298c2ecf20Sopenharmony_ci#include <stdio.h>
308c2ecf20Sopenharmony_ci#include <string.h>
318c2ecf20Sopenharmony_ci#include <unistd.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define VENDOR	0x1d6b
348c2ecf20Sopenharmony_ci#define PRODUCT	0x0105
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define BUF_LEN		8192
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * struct test_state - describes test program state
408c2ecf20Sopenharmony_ci * @list: list of devices returned by libusb_get_device_list function
418c2ecf20Sopenharmony_ci * @found: pointer to struct describing tested device
428c2ecf20Sopenharmony_ci * @ctx: context, set to NULL
438c2ecf20Sopenharmony_ci * @handle: handle of tested device
448c2ecf20Sopenharmony_ci * @attached: indicates that device was attached to kernel, and has to be
458c2ecf20Sopenharmony_ci *            reattached at the end of test program
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistruct test_state {
498c2ecf20Sopenharmony_ci	libusb_device *found;
508c2ecf20Sopenharmony_ci	libusb_context *ctx;
518c2ecf20Sopenharmony_ci	libusb_device_handle *handle;
528c2ecf20Sopenharmony_ci	int attached;
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/*
568c2ecf20Sopenharmony_ci * test_init - initialize test program
578c2ecf20Sopenharmony_ci */
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ciint test_init(struct test_state *state)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	int i, ret;
628c2ecf20Sopenharmony_ci	ssize_t cnt;
638c2ecf20Sopenharmony_ci	libusb_device **list;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	state->found = NULL;
668c2ecf20Sopenharmony_ci	state->ctx = NULL;
678c2ecf20Sopenharmony_ci	state->handle = NULL;
688c2ecf20Sopenharmony_ci	state->attached = 0;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	ret = libusb_init(&state->ctx);
718c2ecf20Sopenharmony_ci	if (ret) {
728c2ecf20Sopenharmony_ci		printf("cannot init libusb: %s\n", libusb_error_name(ret));
738c2ecf20Sopenharmony_ci		return 1;
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	cnt = libusb_get_device_list(state->ctx, &list);
778c2ecf20Sopenharmony_ci	if (cnt <= 0) {
788c2ecf20Sopenharmony_ci		printf("no devices found\n");
798c2ecf20Sopenharmony_ci		goto error1;
808c2ecf20Sopenharmony_ci	}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	for (i = 0; i < cnt; ++i) {
838c2ecf20Sopenharmony_ci		libusb_device *dev = list[i];
848c2ecf20Sopenharmony_ci		struct libusb_device_descriptor desc;
858c2ecf20Sopenharmony_ci		ret = libusb_get_device_descriptor(dev, &desc);
868c2ecf20Sopenharmony_ci		if (ret) {
878c2ecf20Sopenharmony_ci			printf("unable to get device descriptor: %s\n",
888c2ecf20Sopenharmony_ci			       libusb_error_name(ret));
898c2ecf20Sopenharmony_ci			goto error2;
908c2ecf20Sopenharmony_ci		}
918c2ecf20Sopenharmony_ci		if (desc.idVendor == VENDOR && desc.idProduct == PRODUCT) {
928c2ecf20Sopenharmony_ci			state->found = dev;
938c2ecf20Sopenharmony_ci			break;
948c2ecf20Sopenharmony_ci		}
958c2ecf20Sopenharmony_ci	}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	if (!state->found) {
988c2ecf20Sopenharmony_ci		printf("no devices found\n");
998c2ecf20Sopenharmony_ci		goto error2;
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	ret = libusb_open(state->found, &state->handle);
1038c2ecf20Sopenharmony_ci	if (ret) {
1048c2ecf20Sopenharmony_ci		printf("cannot open device: %s\n", libusb_error_name(ret));
1058c2ecf20Sopenharmony_ci		goto error2;
1068c2ecf20Sopenharmony_ci	}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	if (libusb_claim_interface(state->handle, 0)) {
1098c2ecf20Sopenharmony_ci		ret = libusb_detach_kernel_driver(state->handle, 0);
1108c2ecf20Sopenharmony_ci		if (ret) {
1118c2ecf20Sopenharmony_ci			printf("unable to detach kernel driver: %s\n",
1128c2ecf20Sopenharmony_ci			       libusb_error_name(ret));
1138c2ecf20Sopenharmony_ci			goto error3;
1148c2ecf20Sopenharmony_ci		}
1158c2ecf20Sopenharmony_ci		state->attached = 1;
1168c2ecf20Sopenharmony_ci		ret = libusb_claim_interface(state->handle, 0);
1178c2ecf20Sopenharmony_ci		if (ret) {
1188c2ecf20Sopenharmony_ci			printf("cannot claim interface: %s\n",
1198c2ecf20Sopenharmony_ci			       libusb_error_name(ret));
1208c2ecf20Sopenharmony_ci			goto error4;
1218c2ecf20Sopenharmony_ci		}
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	return 0;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cierror4:
1278c2ecf20Sopenharmony_ci	if (state->attached == 1)
1288c2ecf20Sopenharmony_ci		libusb_attach_kernel_driver(state->handle, 0);
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cierror3:
1318c2ecf20Sopenharmony_ci	libusb_close(state->handle);
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cierror2:
1348c2ecf20Sopenharmony_ci	libusb_free_device_list(list, 1);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cierror1:
1378c2ecf20Sopenharmony_ci	libusb_exit(state->ctx);
1388c2ecf20Sopenharmony_ci	return 1;
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci/*
1428c2ecf20Sopenharmony_ci * test_exit - cleanup test program
1438c2ecf20Sopenharmony_ci */
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_civoid test_exit(struct test_state *state)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	libusb_release_interface(state->handle, 0);
1488c2ecf20Sopenharmony_ci	if (state->attached == 1)
1498c2ecf20Sopenharmony_ci		libusb_attach_kernel_driver(state->handle, 0);
1508c2ecf20Sopenharmony_ci	libusb_close(state->handle);
1518c2ecf20Sopenharmony_ci	libusb_exit(state->ctx);
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ciint main(void)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	struct test_state state;
1578c2ecf20Sopenharmony_ci	struct libusb_config_descriptor *conf;
1588c2ecf20Sopenharmony_ci	struct libusb_interface_descriptor const *iface;
1598c2ecf20Sopenharmony_ci	unsigned char addr;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	if (test_init(&state))
1628c2ecf20Sopenharmony_ci		return 1;
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	libusb_get_config_descriptor(state.found, 0, &conf);
1658c2ecf20Sopenharmony_ci	iface = &conf->interface[0].altsetting[0];
1668c2ecf20Sopenharmony_ci	addr = iface->endpoint[0].bEndpointAddress;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	while (1) {
1698c2ecf20Sopenharmony_ci		static unsigned char buffer[BUF_LEN];
1708c2ecf20Sopenharmony_ci		int bytes;
1718c2ecf20Sopenharmony_ci		libusb_bulk_transfer(state.handle, addr, buffer, BUF_LEN,
1728c2ecf20Sopenharmony_ci				     &bytes, 500);
1738c2ecf20Sopenharmony_ci	}
1748c2ecf20Sopenharmony_ci	test_exit(&state);
1758c2ecf20Sopenharmony_ci}
176