Skip to content

Commit b4666d1

Browse files
committed
Add tests for libusbp_write_pipe.
1 parent 1138584 commit b4666d1

File tree

4 files changed

+261
-7
lines changed

4 files changed

+261
-7
lines changed

test/CMakeLists.txt

-4
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ set(USE_TEST_DEVICE_B FALSE CACHE BOOL
2121

2222
file(GLOB test_sources *.cpp)
2323

24-
if (APPLE)
25-
set (link_flags "-framework CoreFoundation ${link_flags}")
26-
endif ()
27-
2824
add_executable(run_test ${test_sources})
2925

3026
set_target_properties(run_test PROPERTIES

test/device_test.cpp

+20-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ TEST_CASE("Test Device A", "[tda]")
210210
{
211211
// If this test fails, you should probably update
212212
// your Test Device A with the latest firmware.
213-
REQUIRE(device.get_revision() == 0x0006);
213+
REQUIRE(device.get_revision() == 0x0007);
214214
}
215215

216216
SECTION("device instance id")
@@ -230,3 +230,22 @@ TEST_CASE("Test Device A", "[tda]")
230230
}
231231
}
232232
#endif
233+
234+
#ifdef USE_TEST_DEVICE_B
235+
TEST_CASE("Test Device B", "[tdb]")
236+
{
237+
libusbp::device device = find_test_device_b();
238+
239+
SECTION("present")
240+
{
241+
REQUIRE(device);
242+
}
243+
244+
SECTION("revision code")
245+
{
246+
// If this test fails, you should probably update
247+
// your Test Device B with the latest firmware.
248+
REQUIRE(device.get_revision() == 0x0007);
249+
}
250+
}
251+
#endif

test/firmware/wixel/main.c

+77-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
#define ADC_DATA_ENDPOINT 2
3131
#define ADC_DATA_FIFO USBF2
3232
#define ADC_DATA_PACKET_SIZE 5
33+
#define CMD_ENDPOINT 3
34+
#define CMD_PACKET_SIZE 32
35+
#define CMD_FIFO USBF3
3336

3437
#ifdef COMPOSITE
3538
#define NATIVE_INTERFACE_1 1
@@ -120,7 +123,7 @@ USB_DESCRIPTOR_DEVICE CODE usbDeviceDescriptor =
120123
#else
121124
0xDA01, // Product ID: USB Test Device A
122125
#endif
123-
0x0006, // Device release number in BCD format
126+
0x0007, // Device release number in BCD format
124127
1, // Index of Manufacturer String Descriptor
125128
2, // Index of Product String Descriptor
126129
3, // Index of Serial Number String Descriptor
@@ -134,6 +137,8 @@ struct CONFIG1 {
134137
USB_DESCRIPTOR_CONFIGURATION configuration;
135138
USB_DESCRIPTOR_INTERFACE nativeInterface0;
136139
USB_DESCRIPTOR_ENDPOINT adcDataIn;
140+
USB_DESCRIPTOR_ENDPOINT cmdOut;
141+
USB_DESCRIPTOR_ENDPOINT cmdIn;
137142
USB_DESCRIPTOR_INTERFACE nativeInterface1;
138143
USB_DESCRIPTOR_INTERFACE_ASSOCIATION portFunction;
139144
USB_DESCRIPTOR_INTERFACE portCommunicationInterface;
@@ -160,7 +165,7 @@ struct CONFIG1 {
160165
USB_DESCRIPTOR_TYPE_INTERFACE,
161166
NATIVE_INTERFACE_0, // bInterfaceNumber
162167
0, // bAlternateSetting
163-
1, // bNumEndpoints
168+
3, // bNumEndpoints
164169
0xFF, // bInterfaceClass: Vendor Specific
165170
0x00, // bInterfaceSubClass
166171
0x00, // bInterfaceProtocol
@@ -176,6 +181,24 @@ struct CONFIG1 {
176181
1,
177182
},
178183

184+
{
185+
sizeof(USB_DESCRIPTOR_ENDPOINT),
186+
USB_DESCRIPTOR_TYPE_ENDPOINT,
187+
USB_ENDPOINT_ADDRESS_OUT | CMD_ENDPOINT,
188+
USB_TRANSFER_TYPE_BULK,
189+
CMD_PACKET_SIZE,
190+
0,
191+
},
192+
193+
{
194+
sizeof(USB_DESCRIPTOR_ENDPOINT),
195+
USB_DESCRIPTOR_TYPE_ENDPOINT,
196+
USB_ENDPOINT_ADDRESS_IN | CMD_ENDPOINT,
197+
USB_TRANSFER_TYPE_BULK,
198+
CMD_PACKET_SIZE,
199+
0,
200+
},
201+
179202
{
180203
sizeof(USB_DESCRIPTOR_INTERFACE),
181204
USB_DESCRIPTOR_TYPE_INTERFACE,
@@ -470,6 +493,8 @@ bool yellowOn = 0;
470493
void usbCallbackInitEndpoints()
471494
{
472495
usbInitEndpointIn(ADC_DATA_ENDPOINT, ADC_DATA_PACKET_SIZE);
496+
usbInitEndpointOut(CMD_ENDPOINT, CMD_PACKET_SIZE);
497+
usbInitEndpointIn(CMD_ENDPOINT, CMD_PACKET_SIZE);
473498
}
474499

475500
void usbCallbackSetupHandler()
@@ -638,6 +663,55 @@ void adcDataTx()
638663
}
639664
}
640665

666+
void cmdService()
667+
{
668+
uint8_t count, cmd, i;
669+
uint16_t delay;
670+
671+
if (usbDeviceState != USB_STATE_CONFIGURED) { return; }
672+
673+
USBINDEX = CMD_ENDPOINT;
674+
if (!(USBCSOL & USBCSOL_OUTPKT_RDY))
675+
{
676+
// No command packet available right now.
677+
return;
678+
}
679+
680+
count = USBCNTL;
681+
682+
if (count == 0)
683+
{
684+
// Empty packet
685+
dataBuffer[0] = 0x66;
686+
}
687+
688+
if (count >= 2)
689+
{
690+
cmd = CMD_FIFO;
691+
692+
// Command 0x92: Set a byte in dataBuffer
693+
if (cmd == 0x92)
694+
{
695+
dataBuffer[0] = CMD_FIFO;
696+
}
697+
698+
// Command 0xDE: Delay
699+
if (cmd == 0xDE)
700+
{
701+
delay = CMD_FIFO;
702+
delay += CMD_FIFO << 8;
703+
delayMs(delay);
704+
}
705+
}
706+
707+
for (i = 0; i < count; i++)
708+
{
709+
CMD_FIFO;
710+
}
711+
712+
USBCSOL &= ~USBCSOL_OUTPKT_RDY; // Done with this packet.
713+
}
714+
641715
void main()
642716
{
643717
uint8_t x = 0;
@@ -650,6 +724,7 @@ void main()
650724
usbShowStatusWithGreenLed();
651725
usbPoll();
652726
adcDataTx();
727+
cmdService();
653728
LED_YELLOW(yellowOn);
654729

655730
if (!isPinHigh(0))

test/write_pipe_test.cpp

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#include <test_helper.h>
2+
3+
#ifdef USE_TEST_DEVICE_A
4+
TEST_CASE("write_pipe parameter checking")
5+
{
6+
libusbp::device device = find_test_device_a();
7+
libusbp::generic_interface gi(device, 0, true);
8+
libusbp::generic_handle handle(gi);
9+
const uint8_t pipe = 0x03;
10+
size_t transferred = 0xFFFF;
11+
12+
SECTION("sets transferred to zero if possible")
13+
{
14+
size_t transferred = 1;
15+
libusbp::error error(libusbp_write_pipe(NULL,
16+
0, NULL, 0, &transferred));
17+
REQUIRE(transferred == 0);
18+
}
19+
20+
SECTION("requires the buffer to be non-NULL")
21+
{
22+
try
23+
{
24+
handle.write_pipe(pipe, NULL, 2, &transferred);
25+
REQUIRE(0);
26+
}
27+
catch(const libusbp::error & error)
28+
{
29+
REQUIRE(std::string(error.what()) ==
30+
"Failed to write to pipe. "
31+
"Buffer is null.");
32+
REQUIRE(transferred == 0);
33+
}
34+
}
35+
36+
SECTION("requires the direction bit to be correct")
37+
{
38+
try
39+
{
40+
uint8_t buffer[5];
41+
handle.write_pipe(0x83, buffer, sizeof(buffer), &transferred);
42+
REQUIRE(0);
43+
}
44+
catch (const libusbp::error & error)
45+
{
46+
REQUIRE(std::string(error.what()) ==
47+
"Failed to write to pipe. "
48+
"Invalid pipe ID 0x83.");
49+
REQUIRE(transferred == 0);
50+
}
51+
}
52+
53+
SECTION("checks the size")
54+
{
55+
uint8_t buffer[5];
56+
57+
#if defined(_WIN32)
58+
size_t too_large_size = (size_t)ULONG_MAX + 1;
59+
#elif defined(__linux__)
60+
size_t too_large_size = (size_t)UINT_MAX + 1;
61+
#elif defined(__APPLE__)
62+
size_t too_large_size = (size_t)UINT32_MAX + 1;
63+
#else
64+
#error add a case for this OS
65+
#endif
66+
67+
if (too_large_size == 0) { return; }
68+
69+
try
70+
{
71+
handle.write_pipe(pipe, buffer, too_large_size, NULL);
72+
REQUIRE(0);
73+
}
74+
catch (const libusbp::error & error)
75+
{
76+
REQUIRE(error.message() == "Failed to write to pipe. "
77+
"Transfer size is too large.");
78+
}
79+
}
80+
}
81+
82+
TEST_CASE("write_pipe (synchronous) on a bulk endpoint ", "[wpi]")
83+
{
84+
// We assume that if write_pipe works on a bulk endpoint, it will also
85+
// work on an interrupt endpoint because of the details of the underlying
86+
// APIs that libusbp uses.
87+
88+
libusbp::device device = find_test_device_a();
89+
libusbp::generic_interface gi(device, 0, true);
90+
libusbp::generic_handle handle(gi);
91+
const uint8_t pipe = 0x03;
92+
handle.set_timeout(pipe, 100);
93+
size_t transferred = 0xFFFF;
94+
95+
SECTION("can write one small packet")
96+
{
97+
uint8_t buffer[2] = { 0x92, 0x44 };
98+
handle.write_pipe(pipe, buffer, sizeof(buffer), &transferred);
99+
REQUIRE(transferred == sizeof(buffer));
100+
101+
// Read the data back.
102+
uint8_t buffer2[1];
103+
handle.control_transfer(0xC0, 0x91, 0, 1, buffer2, 1, &transferred);
104+
REQUIRE(transferred == 1);
105+
REQUIRE(buffer2[0] == 0x44);
106+
}
107+
108+
#ifndef _WIN32
109+
// TODO: get this to pass by using WinUSB's SHORT_PACKET_TERMINATE mode
110+
SECTION("sends zero-length packets")
111+
{
112+
uint8_t buffer[32] = { 0x92, 0x33 };
113+
handle.write_pipe(pipe, buffer, sizeof(buffer), NULL);
114+
115+
// Expect dataBuffer to contain 0x66 because of the ZLP.
116+
uint8_t buffer2[1];
117+
handle.control_transfer(0xC0, 0x91, 0, 1, buffer2, 1, &transferred);
118+
REQUIRE(transferred == 1);
119+
REQUIRE(buffer2[0] == 0x66);
120+
}
121+
#endif
122+
123+
SECTION("can write one small packet with null transferred pointer")
124+
{
125+
uint8_t buffer[2] = { 0x92, 0x55 };
126+
handle.write_pipe(pipe, buffer, sizeof(buffer), NULL);
127+
128+
// Read the data back.
129+
uint8_t buffer2[1];
130+
handle.control_transfer(0xC0, 0x91, 0, 1, buffer2, 1, &transferred);
131+
REQUIRE(transferred == 1);
132+
REQUIRE(buffer2[0] == 85);
133+
}
134+
135+
SECTION("can send zero-length trasnfers")
136+
{
137+
handle.write_pipe(pipe, NULL, 0, NULL);
138+
139+
// Expect dataBuffer to contain 0x66
140+
uint8_t buffer2[1];
141+
handle.control_transfer(0xC0, 0x91, 0, 1, buffer2, 1, &transferred);
142+
REQUIRE(transferred == 1);
143+
REQUIRE(buffer2[0] == 0x66);
144+
}
145+
146+
SECTION("can time out")
147+
{
148+
// First packet causes a 150 ms delay, so this transfer will timeout after
149+
// a partial data transfer. Need three packets because of double
150+
// buffering on the device.
151+
uint8_t buffer[32 * 3] = { 0xDE, 150, 0 };
152+
try
153+
{
154+
handle.write_pipe(pipe, buffer, sizeof(buffer), &transferred);
155+
REQUIRE(0);
156+
}
157+
catch (const libusbp::error & e)
158+
{
159+
REQUIRE(e.has_code(LIBUSBP_ERROR_TIMEOUT));
160+
REQUIRE(transferred == 64);
161+
}
162+
}
163+
}
164+
#endif

0 commit comments

Comments
 (0)