📄 usbhost.c
字号:
{ int i; for (i = 0; i < USBTEST_MAX_CONCURRENT_TESTS; i++) { pool[i].running = 0; pool[i].test.fd = dup(usb_master_fd); if (0 != sem_init(&(pool[i].wakeup), 0, 0)) { fprintf(stderr, "usbhost: internal error, failed to initialize all semaphores.\n"); exit(EXIT_FAILURE); } if (0 != pthread_create(&(pool[i].thread), NULL, &pool_function, (void*) &(pool[i]))) { fprintf(stderr, "usbhost: internal error, failed to start all threads.\n"); exit(EXIT_FAILURE); } }}// Allocate a single entry in the thread pool.static UsbTest*pool_allocate(void){ UsbTest* result = (UsbTest*) 0; if (local_thread_count == USBTEST_MAX_CONCURRENT_TESTS) { fprintf(stderr, "usbhost: internal error, thread resource exhausted.\n"); exit(EXIT_FAILURE); } result = &(pool[local_thread_count].test); local_thread_count++; reset_usbtest(result); return result;}// Start all the threads that are supposed to be running tests.static voidpool_start(void){ int i; for (i = 0; i < local_thread_count; i++) { pool[i].running = 1; sem_post(&(pool[i].wakeup)); }}/*}}}*//*{{{ Tcl routines */// ----------------------------------------------------------------------------// Tcl routines to provide access to the USB device from inside Tcl// scripts, plus some general utilities. These routines deal mostly// with preparing a test run. The actual work is done in C: the// ioctl() operations are not readily accessible from Tcl, and// operations like filling in buffers and calculating checksums are// cpu-intensive./*{{{ pass/fail/abort */// ----------------------------------------------------------------------------// Some simple routines accessible from Tcl to get the target to report pass/fail or// to make the target abort.static inttcl_target_pass(ClientData clientData __attribute__ ((unused)), Tcl_Interp* interp, int argc, char** argv){ if (2 != argc) { Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_pass <message>\"", TCL_STATIC); return TCL_ERROR; } usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_PASS, 0, 0, strlen(argv[1]) + 1, argv[1]); usb_sync(usb_master_fd, -1); return TCL_OK;}static inttcl_target_fail(ClientData clientData __attribute__ ((unused)), Tcl_Interp* interp, int argc, char** argv){ if (2 != argc) { Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_fail <message>\"", TCL_STATIC); return TCL_ERROR; } usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_FAIL, 0, 0, strlen(argv[1]) + 1, argv[1]); usb_sync(usb_master_fd, -1); return TCL_OK;}// The next three routines cause the target to exit, so a usb_sync() is inappropriate.static inttcl_target_pass_exit(ClientData clientData __attribute__ ((unused)), Tcl_Interp* interp, int argc, char** argv){ if (2 != argc) { Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_pass_exit <message>\"", TCL_STATIC); return TCL_ERROR; } usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_PASS_EXIT, 0, 0, strlen(argv[1]) + 1, argv[1]); return TCL_OK;}static inttcl_target_fail_exit(ClientData clientData __attribute__ ((unused)), Tcl_Interp* interp, int argc, char** argv){ if (2 != argc) { Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_fail_exit <message>\"", TCL_STATIC); return TCL_ERROR; } usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_FAIL_EXIT, 0, 0, strlen(argv[1]) + 1, argv[1]); return TCL_OK;}static inttcl_target_abort(ClientData clientData __attribute__ ((unused)), Tcl_Interp* interp, int argc, char** argv __attribute__ ((unused)) ){ if (1 != argc) { Tcl_SetResult(interp, "wrong # args: should be \"usbtest::target_abort\"", TCL_STATIC); return TCL_ERROR; } usb_abort(usb_master_fd); return TCL_OK;}/*}}}*//*{{{ start bulk test */// ----------------------------------------------------------------------------// Start a bulk test. The real Tcl interface to this functionality is// implemented in Tcl: it takes care of figuring out sensible default// arguments, validating the data, etc. All that this code does is// allocate a thread and fill in the appropriate data, plus request// the target-side to do the same thing.static inttcl_test_bulk(ClientData clientData __attribute__ ((unused)), Tcl_Interp* interp, int argc, char** argv){ int i; int tmp; UsbTest* test; unsigned char request[USBTEST_MAX_CONTROL_DATA]; int request_index; // The data consists of 28 numbers for UsbTest_Bulk itself, and // another 10 numbers for the test data definition. if (39 != argc) { Tcl_SetResult(interp, "wrong # args: should be \"usbtest::_test_bulk <message>\"", TCL_STATIC); return TCL_ERROR; } for (i = 1; i < 39; i++) { int discard; if (TCL_OK != Tcl_GetInt(interp, argv[i], &discard)) { Tcl_SetResult(interp, "invalid argument: all arguments should be numbers", TCL_STATIC); return TCL_ERROR; } } test = pool_allocate(); Tcl_GetInt(interp, argv[1], &(test->test_params.bulk.number_packets)); Tcl_GetInt(interp, argv[2], &(test->test_params.bulk.endpoint)); test->which_test = (USB_DIR_IN == (test->test_params.bulk.endpoint & USB_ENDPOINT_DIR_MASK)) ? usbtest_bulk_in : usbtest_bulk_out; Tcl_GetInt(interp, argv[ 3], &(test->test_params.bulk.tx_size)); Tcl_GetInt(interp, argv[ 4], &(test->test_params.bulk.tx_size_min)); Tcl_GetInt(interp, argv[ 5], &(test->test_params.bulk.tx_size_max)); Tcl_GetInt(interp, argv[ 6], &(test->test_params.bulk.tx_size_multiplier)); Tcl_GetInt(interp, argv[ 7], &(test->test_params.bulk.tx_size_divisor)); Tcl_GetInt(interp, argv[ 8], &(test->test_params.bulk.tx_size_increment)); Tcl_GetInt(interp, argv[ 9], &(test->test_params.bulk.rx_size)); Tcl_GetInt(interp, argv[10], &(test->test_params.bulk.rx_size_min)); Tcl_GetInt(interp, argv[11], &(test->test_params.bulk.rx_size_max)); Tcl_GetInt(interp, argv[12], &(test->test_params.bulk.rx_size_multiplier)); Tcl_GetInt(interp, argv[13], &(test->test_params.bulk.rx_size_divisor)); Tcl_GetInt(interp, argv[14], &(test->test_params.bulk.rx_size_increment)); Tcl_GetInt(interp, argv[15], &(test->test_params.bulk.rx_padding)); Tcl_GetInt(interp, argv[16], &(test->test_params.bulk.tx_delay)); Tcl_GetInt(interp, argv[17], &(test->test_params.bulk.tx_delay_min)); Tcl_GetInt(interp, argv[18], &(test->test_params.bulk.tx_delay_max)); Tcl_GetInt(interp, argv[19], &(test->test_params.bulk.tx_delay_multiplier)); Tcl_GetInt(interp, argv[20], &(test->test_params.bulk.tx_delay_divisor)); Tcl_GetInt(interp, argv[21], &(test->test_params.bulk.tx_delay_increment)); Tcl_GetInt(interp, argv[22], &(test->test_params.bulk.rx_delay)); Tcl_GetInt(interp, argv[23], &(test->test_params.bulk.rx_delay_min)); Tcl_GetInt(interp, argv[24], &(test->test_params.bulk.rx_delay_max)); Tcl_GetInt(interp, argv[25], &(test->test_params.bulk.rx_delay_multiplier)); Tcl_GetInt(interp, argv[26], &(test->test_params.bulk.rx_delay_divisor)); Tcl_GetInt(interp, argv[27], &(test->test_params.bulk.rx_delay_increment)); Tcl_GetInt(interp, argv[28], &tmp); test->test_params.bulk.io_mechanism = (usb_io_mechanism) tmp; Tcl_GetInt(interp, argv[29], &tmp); test->test_params.bulk.data.format = (usbtestdata) tmp; Tcl_GetInt(interp, argv[30], &(test->test_params.bulk.data.seed)); Tcl_GetInt(interp, argv[31], &(test->test_params.bulk.data.multiplier)); Tcl_GetInt(interp, argv[32], &(test->test_params.bulk.data.increment)); Tcl_GetInt(interp, argv[33], &(test->test_params.bulk.data.transfer_seed_multiplier)); Tcl_GetInt(interp, argv[34], &(test->test_params.bulk.data.transfer_seed_increment)); Tcl_GetInt(interp, argv[35], &(test->test_params.bulk.data.transfer_multiplier_multiplier)); Tcl_GetInt(interp, argv[36], &(test->test_params.bulk.data.transfer_multiplier_increment)); Tcl_GetInt(interp, argv[37], &(test->test_params.bulk.data.transfer_increment_multiplier)); Tcl_GetInt(interp, argv[38], &(test->test_params.bulk.data.transfer_increment_increment)); VERBOSE(3, "Preparing USB bulk test on endpoint %d, direction %s, for %d packets\n", \ test->test_params.bulk.endpoint, \ (usbtest_bulk_in == test->which_test) ? "IN" : "OUT", \ test->test_params.bulk.number_packets); VERBOSE(3, " I/O mechanism is %s\n", \ (usb_io_mechanism_usb == test->test_params.bulk.io_mechanism) ? "low-level USB" : \ (usb_io_mechanism_dev == test->test_params.bulk.io_mechanism) ? "devtab" : "<invalid>"); VERBOSE(3, " Data format %s, data1 %d, data* %d, data+ %d, data1* %d, data1+ %d, data** %d, data*+ %d, data+* %d, data++ %d\n",\ (usbtestdata_none == test->test_params.bulk.data.format) ? "none" : \ (usbtestdata_bytefill == test->test_params.bulk.data.format) ? "bytefill" : \ (usbtestdata_wordfill == test->test_params.bulk.data.format) ? "wordfill" : \ (usbtestdata_byteseq == test->test_params.bulk.data.format) ? "byteseq" : \ (usbtestdata_wordseq == test->test_params.bulk.data.format) ? "wordseq" : "<invalid>", \ test->test_params.bulk.data.seed, \ test->test_params.bulk.data.multiplier, \ test->test_params.bulk.data.increment, \ test->test_params.bulk.data.transfer_seed_multiplier, \ test->test_params.bulk.data.transfer_seed_increment, \ test->test_params.bulk.data.transfer_multiplier_multiplier, \ test->test_params.bulk.data.transfer_multiplier_increment, \ test->test_params.bulk.data.transfer_increment_multiplier, \ test->test_params.bulk.data.transfer_increment_increment); VERBOSE(3, " txsize1 %d, txsize>= %d, txsize<= %d, txsize* %d, txsize/ %d, txsize+ %d\n", \ test->test_params.bulk.tx_size, test->test_params.bulk.tx_size_min, \ test->test_params.bulk.tx_size_max, test->test_params.bulk.tx_size_multiplier, \ test->test_params.bulk.tx_size_divisor, test->test_params.bulk.tx_size_increment); VERBOSE(3, " rxsize1 %d, rxsize>= %d, rxsize<= %d, rxsize* %d, rxsize/ %d, rxsize+ %d\n", \ test->test_params.bulk.rx_size, test->test_params.bulk.rx_size_min, \ test->test_params.bulk.rx_size_max, test->test_params.bulk.rx_size_multiplier, \ test->test_params.bulk.rx_size_divisor, test->test_params.bulk.rx_size_increment); VERBOSE(3, " txdelay1 %d, txdelay>= %d, txdelay<= %d, txdelay* %d, txdelay/ %d, txdelay+ %d\n", \ test->test_params.bulk.tx_delay, test->test_params.bulk.tx_delay_min, \ test->test_params.bulk.tx_delay_max, test->test_params.bulk.tx_delay_multiplier, \ test->test_params.bulk.tx_delay_divisor, test->test_params.bulk.tx_delay_increment); VERBOSE(3, " rxdelay1 %d, rxdelay>= %d, rxdelay<= %d, rxdelay* %d, rxdelay/ %d, rxdelay+ %d\n", \ test->test_params.bulk.rx_delay, test->test_params.bulk.rx_delay_min, \ test->test_params.bulk.rx_delay_max, test->test_params.bulk.rx_delay_multiplier, \ test->test_params.bulk.rx_delay_divisor, test->test_params.bulk.rx_delay_increment); // That is all the data converted from Tcl to C, and a local thread is set up to handle this // request. Also set up a thread on the target. request_index = 0; pack_usbtest_bulk(&(test->test_params.bulk), request, &request_index); usb_reliable_control_message(usb_master_fd, USB_TYPE_CLASS | USB_RECIP_DEVICE, USBTEST_TEST_BULK, 0, 0, request_index, request); remote_thread_count++; return TCL_OK;}/*}}}*//*{{{ start control-in test */// ----------------------------------------------------------------------------// Start a control-in test. The real Tcl interface to this// functionality is implemented in Tcl: it takes care of figuring out// sensible default arguments, validating the data, etc. All that this// code does is allocate a thread and fill in the appropriate data,// plus request the target-side to do the same thing.static inttcl_test_control_in(ClientData clientData __attribute__ ((unused)), Tcl_Interp* interp, int argc, char** argv){ int i; int tmp; UsbTest* test; unsigned char request[USBTEST_MAX_CONTROL_DATA]; int request_index; // The data consists of 6 numbers for UsbTest_ControlIn itself, and // another 10 numbers for the test data definition. if (17 != argc) { Tcl_SetResult(interp, "wrong # args: should be \"usbtest::_test_control_in <message>\"", TCL_STATIC); return TCL_ERROR; } for (i = 1; i < 17; i++) { int discard; if (TCL_OK != Tcl_GetInt(interp, argv[i], &discard)) { Tcl_SetResult(interp, "invalid argument: all arguments should be numbers", TCL_STATIC); return TCL_ERROR; } } test = pool_allocate(); test->which_test = usbtest_control_in; Tcl_GetInt(interp, argv[1], &(test->test_params.control_in.number_packets)); Tcl_GetInt(interp, argv[2], &(test->test_params.control_in.packet_size_initial)); Tcl_GetInt(interp, argv[3], &(test->test_params.control_in.packet_size_min)); Tcl_GetInt(interp, argv[4], &(test->test_params.control_in.packet_size_max)); Tcl_GetInt(interp, argv[5], &(test->test_params.control_in.packet_size_multiplier)); Tcl_GetInt(interp, argv[6], &(test->test_params.control_in.packet_size_increment)); Tcl_GetInt(interp, argv[7], &tmp); test->test_params.bulk.data.format = (usbtestdata) tmp; Tcl_GetInt(interp, argv[ 8], &(test->test_params.control_in.data.seed));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -