1*86b64dcbSAndroid Build Coastguard Worker /*
2*86b64dcbSAndroid Build Coastguard Worker * libusb umockdev based tests
3*86b64dcbSAndroid Build Coastguard Worker *
4*86b64dcbSAndroid Build Coastguard Worker * Copyright (C) 2022 Benjamin Berg <[email protected]>
5*86b64dcbSAndroid Build Coastguard Worker *
6*86b64dcbSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
7*86b64dcbSAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
8*86b64dcbSAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
9*86b64dcbSAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
10*86b64dcbSAndroid Build Coastguard Worker *
11*86b64dcbSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
12*86b64dcbSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*86b64dcbSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14*86b64dcbSAndroid Build Coastguard Worker * Lesser General Public License for more details.
15*86b64dcbSAndroid Build Coastguard Worker *
16*86b64dcbSAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public License
17*86b64dcbSAndroid Build Coastguard Worker * along with this program; If not, see <http://www.gnu.org/licenses/>.
18*86b64dcbSAndroid Build Coastguard Worker */
19*86b64dcbSAndroid Build Coastguard Worker
20*86b64dcbSAndroid Build Coastguard Worker #include "config.h"
21*86b64dcbSAndroid Build Coastguard Worker #include <glib.h>
22*86b64dcbSAndroid Build Coastguard Worker #include <glib/gstdio.h>
23*86b64dcbSAndroid Build Coastguard Worker #include <unistd.h>
24*86b64dcbSAndroid Build Coastguard Worker #include <string.h>
25*86b64dcbSAndroid Build Coastguard Worker #include <errno.h>
26*86b64dcbSAndroid Build Coastguard Worker #include <linux/ioctl.h>
27*86b64dcbSAndroid Build Coastguard Worker #include <linux/usbdevice_fs.h>
28*86b64dcbSAndroid Build Coastguard Worker
29*86b64dcbSAndroid Build Coastguard Worker #include "libusb.h"
30*86b64dcbSAndroid Build Coastguard Worker
31*86b64dcbSAndroid Build Coastguard Worker #include "umockdev.h"
32*86b64dcbSAndroid Build Coastguard Worker
33*86b64dcbSAndroid Build Coastguard Worker #define UNUSED_DATA __attribute__ ((unused)) gconstpointer unused_data
34*86b64dcbSAndroid Build Coastguard Worker
35*86b64dcbSAndroid Build Coastguard Worker /* avoid leak reports inside assertions; leaking stuff on assertion failures does not matter in tests */
36*86b64dcbSAndroid Build Coastguard Worker #if !defined(__clang__) && __GNUC__ > 9
37*86b64dcbSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak"
38*86b64dcbSAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wanalyzer-file-leak"
39*86b64dcbSAndroid Build Coastguard Worker #endif
40*86b64dcbSAndroid Build Coastguard Worker
41*86b64dcbSAndroid Build Coastguard Worker typedef struct {
42*86b64dcbSAndroid Build Coastguard Worker pid_t thread;
43*86b64dcbSAndroid Build Coastguard Worker libusb_context *ctx;
44*86b64dcbSAndroid Build Coastguard Worker enum libusb_log_level level;
45*86b64dcbSAndroid Build Coastguard Worker char *str;
46*86b64dcbSAndroid Build Coastguard Worker } LogMessage;
47*86b64dcbSAndroid Build Coastguard Worker
48*86b64dcbSAndroid Build Coastguard Worker static void
log_message_free(LogMessage * msg)49*86b64dcbSAndroid Build Coastguard Worker log_message_free(LogMessage *msg)
50*86b64dcbSAndroid Build Coastguard Worker {
51*86b64dcbSAndroid Build Coastguard Worker g_free(msg->str);
52*86b64dcbSAndroid Build Coastguard Worker g_free(msg);
53*86b64dcbSAndroid Build Coastguard Worker }
54*86b64dcbSAndroid Build Coastguard Worker G_DEFINE_AUTOPTR_CLEANUP_FUNC(LogMessage, log_message_free)
55*86b64dcbSAndroid Build Coastguard Worker
56*86b64dcbSAndroid Build Coastguard Worker typedef struct _UsbChat UsbChat;
57*86b64dcbSAndroid Build Coastguard Worker
58*86b64dcbSAndroid Build Coastguard Worker struct _UsbChat {
59*86b64dcbSAndroid Build Coastguard Worker gboolean submit;
60*86b64dcbSAndroid Build Coastguard Worker gboolean reap;
61*86b64dcbSAndroid Build Coastguard Worker UsbChat *reaps;
62*86b64dcbSAndroid Build Coastguard Worker UsbChat *next;
63*86b64dcbSAndroid Build Coastguard Worker
64*86b64dcbSAndroid Build Coastguard Worker /* struct usbdevfs_urb */
65*86b64dcbSAndroid Build Coastguard Worker unsigned char type;
66*86b64dcbSAndroid Build Coastguard Worker unsigned char endpoint;
67*86b64dcbSAndroid Build Coastguard Worker int status;
68*86b64dcbSAndroid Build Coastguard Worker unsigned int flags;
69*86b64dcbSAndroid Build Coastguard Worker const unsigned char *buffer;
70*86b64dcbSAndroid Build Coastguard Worker int buffer_length;
71*86b64dcbSAndroid Build Coastguard Worker int actual_length;
72*86b64dcbSAndroid Build Coastguard Worker
73*86b64dcbSAndroid Build Coastguard Worker /* <submit urb> */
74*86b64dcbSAndroid Build Coastguard Worker UMockdevIoctlData *submit_urb;
75*86b64dcbSAndroid Build Coastguard Worker };
76*86b64dcbSAndroid Build Coastguard Worker
77*86b64dcbSAndroid Build Coastguard Worker typedef struct {
78*86b64dcbSAndroid Build Coastguard Worker UMockdevTestbed *testbed;
79*86b64dcbSAndroid Build Coastguard Worker UMockdevIoctlBase *handler;
80*86b64dcbSAndroid Build Coastguard Worker struct libusb_context *ctx;
81*86b64dcbSAndroid Build Coastguard Worker
82*86b64dcbSAndroid Build Coastguard Worker gchar *root_dir;
83*86b64dcbSAndroid Build Coastguard Worker gchar *sys_dir;
84*86b64dcbSAndroid Build Coastguard Worker
85*86b64dcbSAndroid Build Coastguard Worker gboolean libusb_log_silence;
86*86b64dcbSAndroid Build Coastguard Worker GList *libusb_log;
87*86b64dcbSAndroid Build Coastguard Worker
88*86b64dcbSAndroid Build Coastguard Worker UsbChat *chat;
89*86b64dcbSAndroid Build Coastguard Worker GList *flying_urbs;
90*86b64dcbSAndroid Build Coastguard Worker GList *discarded_urbs;
91*86b64dcbSAndroid Build Coastguard Worker
92*86b64dcbSAndroid Build Coastguard Worker /* GMutex confuses TSan unnecessarily */
93*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_t mutex;
94*86b64dcbSAndroid Build Coastguard Worker } UMockdevTestbedFixture;
95*86b64dcbSAndroid Build Coastguard Worker
96*86b64dcbSAndroid Build Coastguard Worker /* Global for log handler */
97*86b64dcbSAndroid Build Coastguard Worker static UMockdevTestbedFixture *cur_fixture = NULL;
98*86b64dcbSAndroid Build Coastguard Worker
99*86b64dcbSAndroid Build Coastguard Worker static void
log_handler(libusb_context * ctx,enum libusb_log_level level,const char * str)100*86b64dcbSAndroid Build Coastguard Worker log_handler(libusb_context *ctx, enum libusb_log_level level, const char *str)
101*86b64dcbSAndroid Build Coastguard Worker {
102*86b64dcbSAndroid Build Coastguard Worker /* May be called from different threads without synchronization! */
103*86b64dcbSAndroid Build Coastguard Worker LogMessage *msg;
104*86b64dcbSAndroid Build Coastguard Worker pid_t tid = gettid();
105*86b64dcbSAndroid Build Coastguard Worker
106*86b64dcbSAndroid Build Coastguard Worker g_assert (cur_fixture != NULL);
107*86b64dcbSAndroid Build Coastguard Worker g_assert(pthread_mutex_lock(&cur_fixture->mutex) == 0);
108*86b64dcbSAndroid Build Coastguard Worker
109*86b64dcbSAndroid Build Coastguard Worker msg = g_new0(LogMessage, 1);
110*86b64dcbSAndroid Build Coastguard Worker msg->ctx = ctx;
111*86b64dcbSAndroid Build Coastguard Worker msg->level = level;
112*86b64dcbSAndroid Build Coastguard Worker msg->str = g_strchomp (g_strdup(str));
113*86b64dcbSAndroid Build Coastguard Worker msg->thread = tid;
114*86b64dcbSAndroid Build Coastguard Worker
115*86b64dcbSAndroid Build Coastguard Worker if (!cur_fixture->libusb_log_silence)
116*86b64dcbSAndroid Build Coastguard Worker g_printerr("%s\n", msg->str);
117*86b64dcbSAndroid Build Coastguard Worker
118*86b64dcbSAndroid Build Coastguard Worker cur_fixture->libusb_log = g_list_append(cur_fixture->libusb_log, msg);
119*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_unlock(&cur_fixture->mutex);
120*86b64dcbSAndroid Build Coastguard Worker }
121*86b64dcbSAndroid Build Coastguard Worker
122*86b64dcbSAndroid Build Coastguard Worker static void
log_handler_null(libusb_context * ctx,enum libusb_log_level level,const char * str)123*86b64dcbSAndroid Build Coastguard Worker log_handler_null(libusb_context *ctx, enum libusb_log_level level, const char *str)
124*86b64dcbSAndroid Build Coastguard Worker {
125*86b64dcbSAndroid Build Coastguard Worker (void) ctx;
126*86b64dcbSAndroid Build Coastguard Worker (void) level;
127*86b64dcbSAndroid Build Coastguard Worker (void) str;
128*86b64dcbSAndroid Build Coastguard Worker }
129*86b64dcbSAndroid Build Coastguard Worker
130*86b64dcbSAndroid Build Coastguard Worker static void
clear_libusb_log(UMockdevTestbedFixture * fixture,enum libusb_log_level level)131*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(UMockdevTestbedFixture * fixture, enum libusb_log_level level)
132*86b64dcbSAndroid Build Coastguard Worker {
133*86b64dcbSAndroid Build Coastguard Worker g_assert(pthread_mutex_lock(&fixture->mutex) == 0);
134*86b64dcbSAndroid Build Coastguard Worker
135*86b64dcbSAndroid Build Coastguard Worker while (fixture->libusb_log) {
136*86b64dcbSAndroid Build Coastguard Worker LogMessage *msg = fixture->libusb_log->data;
137*86b64dcbSAndroid Build Coastguard Worker
138*86b64dcbSAndroid Build Coastguard Worker g_assert(msg->ctx == fixture->ctx);
139*86b64dcbSAndroid Build Coastguard Worker
140*86b64dcbSAndroid Build Coastguard Worker if (msg->level < level) {
141*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_unlock(&fixture->mutex);
142*86b64dcbSAndroid Build Coastguard Worker return;
143*86b64dcbSAndroid Build Coastguard Worker }
144*86b64dcbSAndroid Build Coastguard Worker
145*86b64dcbSAndroid Build Coastguard Worker fixture->libusb_log = g_list_delete_link(fixture->libusb_log, fixture->libusb_log);
146*86b64dcbSAndroid Build Coastguard Worker log_message_free(msg);
147*86b64dcbSAndroid Build Coastguard Worker }
148*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_unlock(&fixture->mutex);
149*86b64dcbSAndroid Build Coastguard Worker }
150*86b64dcbSAndroid Build Coastguard Worker
151*86b64dcbSAndroid Build Coastguard Worker static void
assert_libusb_log_msg(UMockdevTestbedFixture * fixture,enum libusb_log_level level,const char * re)152*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(UMockdevTestbedFixture * fixture, enum libusb_log_level level, const char *re)
153*86b64dcbSAndroid Build Coastguard Worker {
154*86b64dcbSAndroid Build Coastguard Worker g_assert(pthread_mutex_lock(&fixture->mutex) == 0);
155*86b64dcbSAndroid Build Coastguard Worker
156*86b64dcbSAndroid Build Coastguard Worker while (fixture->libusb_log) {
157*86b64dcbSAndroid Build Coastguard Worker g_autoptr(LogMessage) msg = NULL;
158*86b64dcbSAndroid Build Coastguard Worker
159*86b64dcbSAndroid Build Coastguard Worker if (fixture->libusb_log == NULL)
160*86b64dcbSAndroid Build Coastguard Worker g_error ("No level %d message found searching for %s", level, re);
161*86b64dcbSAndroid Build Coastguard Worker
162*86b64dcbSAndroid Build Coastguard Worker msg = fixture->libusb_log->data;
163*86b64dcbSAndroid Build Coastguard Worker fixture->libusb_log = g_list_delete_link(fixture->libusb_log, fixture->libusb_log);
164*86b64dcbSAndroid Build Coastguard Worker
165*86b64dcbSAndroid Build Coastguard Worker if (msg->ctx != fixture->ctx)
166*86b64dcbSAndroid Build Coastguard Worker g_error ("Saw unexpected message \"%s\" from context %p while %p was expected",
167*86b64dcbSAndroid Build Coastguard Worker msg->str, msg->ctx, fixture->ctx);
168*86b64dcbSAndroid Build Coastguard Worker
169*86b64dcbSAndroid Build Coastguard Worker if (msg->level == level && g_regex_match_simple(re, msg->str, 0, 0)) {
170*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_unlock(&fixture->mutex);
171*86b64dcbSAndroid Build Coastguard Worker return;
172*86b64dcbSAndroid Build Coastguard Worker }
173*86b64dcbSAndroid Build Coastguard Worker
174*86b64dcbSAndroid Build Coastguard Worker /* Allow skipping INFO and DEBUG messages */
175*86b64dcbSAndroid Build Coastguard Worker if (msg->level >= LIBUSB_LOG_LEVEL_INFO)
176*86b64dcbSAndroid Build Coastguard Worker continue;
177*86b64dcbSAndroid Build Coastguard Worker
178*86b64dcbSAndroid Build Coastguard Worker g_error ("Searched for \"%s\" (%d) but found \"%s\" (%d)", re, level, msg->str, msg->level);
179*86b64dcbSAndroid Build Coastguard Worker }
180*86b64dcbSAndroid Build Coastguard Worker
181*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_unlock(&fixture->mutex);
182*86b64dcbSAndroid Build Coastguard Worker g_error ("Searched for \"%s\" (%d) but no message matched", re, level);
183*86b64dcbSAndroid Build Coastguard Worker }
184*86b64dcbSAndroid Build Coastguard Worker
185*86b64dcbSAndroid Build Coastguard Worker static void
assert_libusb_no_log_msg(UMockdevTestbedFixture * fixture,enum libusb_log_level level,const char * re)186*86b64dcbSAndroid Build Coastguard Worker assert_libusb_no_log_msg(UMockdevTestbedFixture * fixture, enum libusb_log_level level, const char *re)
187*86b64dcbSAndroid Build Coastguard Worker {
188*86b64dcbSAndroid Build Coastguard Worker g_assert(pthread_mutex_lock(&fixture->mutex) == 0);
189*86b64dcbSAndroid Build Coastguard Worker
190*86b64dcbSAndroid Build Coastguard Worker while (fixture->libusb_log) {
191*86b64dcbSAndroid Build Coastguard Worker g_autoptr(LogMessage) msg = NULL;
192*86b64dcbSAndroid Build Coastguard Worker gboolean matching;
193*86b64dcbSAndroid Build Coastguard Worker
194*86b64dcbSAndroid Build Coastguard Worker msg = fixture->libusb_log->data;
195*86b64dcbSAndroid Build Coastguard Worker fixture->libusb_log = g_list_delete_link(fixture->libusb_log, fixture->libusb_log);
196*86b64dcbSAndroid Build Coastguard Worker
197*86b64dcbSAndroid Build Coastguard Worker g_assert(msg->ctx == fixture->ctx);
198*86b64dcbSAndroid Build Coastguard Worker
199*86b64dcbSAndroid Build Coastguard Worker matching = (msg->level == level && g_regex_match_simple(re, msg->str, 0, 0));
200*86b64dcbSAndroid Build Coastguard Worker
201*86b64dcbSAndroid Build Coastguard Worker /* Allow skipping INFO and DEBUG messages */
202*86b64dcbSAndroid Build Coastguard Worker if (!matching && msg->level >= LIBUSB_LOG_LEVEL_INFO)
203*86b64dcbSAndroid Build Coastguard Worker continue;
204*86b64dcbSAndroid Build Coastguard Worker
205*86b64dcbSAndroid Build Coastguard Worker g_error ("Asserting \"%s\" (%d) not logged and found \"%s\" (%d)", re, level, msg->str, msg->level);
206*86b64dcbSAndroid Build Coastguard Worker }
207*86b64dcbSAndroid Build Coastguard Worker
208*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_unlock(&fixture->mutex);
209*86b64dcbSAndroid Build Coastguard Worker }
210*86b64dcbSAndroid Build Coastguard Worker
211*86b64dcbSAndroid Build Coastguard Worker static void
dump_buffer(const unsigned char * buffer,int len)212*86b64dcbSAndroid Build Coastguard Worker dump_buffer(const unsigned char *buffer, int len)
213*86b64dcbSAndroid Build Coastguard Worker {
214*86b64dcbSAndroid Build Coastguard Worker g_autoptr(GString) line = NULL;
215*86b64dcbSAndroid Build Coastguard Worker
216*86b64dcbSAndroid Build Coastguard Worker line = g_string_new ("");
217*86b64dcbSAndroid Build Coastguard Worker for (gint i = 0; i < len; i++) {
218*86b64dcbSAndroid Build Coastguard Worker g_string_append_printf(line, "%02x ", buffer[i]);
219*86b64dcbSAndroid Build Coastguard Worker if ((i + 1) % 16 == 0) {
220*86b64dcbSAndroid Build Coastguard Worker g_printerr(" %s\n", line->str);
221*86b64dcbSAndroid Build Coastguard Worker g_string_set_size(line, 0);
222*86b64dcbSAndroid Build Coastguard Worker }
223*86b64dcbSAndroid Build Coastguard Worker }
224*86b64dcbSAndroid Build Coastguard Worker
225*86b64dcbSAndroid Build Coastguard Worker if (line->len)
226*86b64dcbSAndroid Build Coastguard Worker g_printerr(" %s\n", line->str);
227*86b64dcbSAndroid Build Coastguard Worker }
228*86b64dcbSAndroid Build Coastguard Worker
229*86b64dcbSAndroid Build Coastguard Worker static gint
cmp_ioctl_data_addr(const void * data,const void * addr)230*86b64dcbSAndroid Build Coastguard Worker cmp_ioctl_data_addr(const void *data, const void *addr)
231*86b64dcbSAndroid Build Coastguard Worker {
232*86b64dcbSAndroid Build Coastguard Worker return ((const UMockdevIoctlData*) data)->client_addr != (gulong) addr;
233*86b64dcbSAndroid Build Coastguard Worker }
234*86b64dcbSAndroid Build Coastguard Worker
235*86b64dcbSAndroid Build Coastguard Worker static gboolean
handle_ioctl_cb(UMockdevIoctlBase * handler,UMockdevIoctlClient * client,UMockdevTestbedFixture * fixture)236*86b64dcbSAndroid Build Coastguard Worker handle_ioctl_cb (UMockdevIoctlBase *handler, UMockdevIoctlClient *client, UMockdevTestbedFixture *fixture)
237*86b64dcbSAndroid Build Coastguard Worker {
238*86b64dcbSAndroid Build Coastguard Worker UMockdevIoctlData *ioctl_arg;
239*86b64dcbSAndroid Build Coastguard Worker long int request;
240*86b64dcbSAndroid Build Coastguard Worker struct usbdevfs_urb *urb;
241*86b64dcbSAndroid Build Coastguard Worker
242*86b64dcbSAndroid Build Coastguard Worker (void) handler;
243*86b64dcbSAndroid Build Coastguard Worker
244*86b64dcbSAndroid Build Coastguard Worker request = umockdev_ioctl_client_get_request (client);
245*86b64dcbSAndroid Build Coastguard Worker ioctl_arg = umockdev_ioctl_client_get_arg (client);
246*86b64dcbSAndroid Build Coastguard Worker
247*86b64dcbSAndroid Build Coastguard Worker /* NOTE: We share the address space, dereferencing pointers *will* work.
248*86b64dcbSAndroid Build Coastguard Worker * However, to make TSan work, we still stick to the API that resolves
249*86b64dcbSAndroid Build Coastguard Worker * the data into a local copy! */
250*86b64dcbSAndroid Build Coastguard Worker
251*86b64dcbSAndroid Build Coastguard Worker switch (request) {
252*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_GET_CAPABILITIES: {
253*86b64dcbSAndroid Build Coastguard Worker g_autoptr(UMockdevIoctlData) d = NULL;
254*86b64dcbSAndroid Build Coastguard Worker d = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(guint32), NULL);
255*86b64dcbSAndroid Build Coastguard Worker
256*86b64dcbSAndroid Build Coastguard Worker *(guint32*) d->data = USBDEVFS_CAP_BULK_SCATTER_GATHER |
257*86b64dcbSAndroid Build Coastguard Worker USBDEVFS_CAP_BULK_CONTINUATION |
258*86b64dcbSAndroid Build Coastguard Worker USBDEVFS_CAP_NO_PACKET_SIZE_LIM |
259*86b64dcbSAndroid Build Coastguard Worker USBDEVFS_CAP_REAP_AFTER_DISCONNECT |
260*86b64dcbSAndroid Build Coastguard Worker USBDEVFS_CAP_ZERO_PACKET;
261*86b64dcbSAndroid Build Coastguard Worker
262*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, 0, 0);
263*86b64dcbSAndroid Build Coastguard Worker return TRUE;
264*86b64dcbSAndroid Build Coastguard Worker }
265*86b64dcbSAndroid Build Coastguard Worker
266*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_CLAIMINTERFACE:
267*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_RELEASEINTERFACE:
268*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_CLEAR_HALT:
269*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_RESET:
270*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_RESETEP:
271*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, 0, 0);
272*86b64dcbSAndroid Build Coastguard Worker return TRUE;
273*86b64dcbSAndroid Build Coastguard Worker
274*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_SUBMITURB: {
275*86b64dcbSAndroid Build Coastguard Worker g_autoptr(UMockdevIoctlData) urb_buffer = NULL;
276*86b64dcbSAndroid Build Coastguard Worker g_autoptr(UMockdevIoctlData) urb_data = NULL;
277*86b64dcbSAndroid Build Coastguard Worker gsize buflen;
278*86b64dcbSAndroid Build Coastguard Worker
279*86b64dcbSAndroid Build Coastguard Worker if (!fixture->chat || !fixture->chat->submit)
280*86b64dcbSAndroid Build Coastguard Worker return FALSE;
281*86b64dcbSAndroid Build Coastguard Worker
282*86b64dcbSAndroid Build Coastguard Worker buflen = fixture->chat->buffer_length;
283*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->type == USBDEVFS_URB_TYPE_CONTROL)
284*86b64dcbSAndroid Build Coastguard Worker buflen = 8;
285*86b64dcbSAndroid Build Coastguard Worker
286*86b64dcbSAndroid Build Coastguard Worker urb_data = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(struct usbdevfs_urb), NULL);
287*86b64dcbSAndroid Build Coastguard Worker urb = (struct usbdevfs_urb*) urb_data->data;
288*86b64dcbSAndroid Build Coastguard Worker urb_buffer = umockdev_ioctl_data_resolve(urb_data, G_STRUCT_OFFSET(struct usbdevfs_urb, buffer), urb->buffer_length, NULL);
289*86b64dcbSAndroid Build Coastguard Worker
290*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->type == urb->type &&
291*86b64dcbSAndroid Build Coastguard Worker fixture->chat->endpoint == urb->endpoint &&
292*86b64dcbSAndroid Build Coastguard Worker fixture->chat->buffer_length == urb->buffer_length &&
293*86b64dcbSAndroid Build Coastguard Worker (fixture->chat->buffer == NULL || memcmp (fixture->chat->buffer, urb_buffer->data, buflen) == 0)) {
294*86b64dcbSAndroid Build Coastguard Worker fixture->flying_urbs = g_list_append (fixture->flying_urbs, umockdev_ioctl_data_ref(urb_data));
295*86b64dcbSAndroid Build Coastguard Worker
296*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->reaps)
297*86b64dcbSAndroid Build Coastguard Worker fixture->chat->reaps->submit_urb = urb_data;
298*86b64dcbSAndroid Build Coastguard Worker
299*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->status)
300*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, -1, -fixture->chat->status);
301*86b64dcbSAndroid Build Coastguard Worker else
302*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, 0, 0);
303*86b64dcbSAndroid Build Coastguard Worker
304*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->next)
305*86b64dcbSAndroid Build Coastguard Worker fixture->chat = fixture->chat->next;
306*86b64dcbSAndroid Build Coastguard Worker else
307*86b64dcbSAndroid Build Coastguard Worker fixture->chat += 1;
308*86b64dcbSAndroid Build Coastguard Worker return TRUE;
309*86b64dcbSAndroid Build Coastguard Worker }
310*86b64dcbSAndroid Build Coastguard Worker
311*86b64dcbSAndroid Build Coastguard Worker /* chat message didn't match, don't accept it */
312*86b64dcbSAndroid Build Coastguard Worker g_printerr("Could not process submit urb:\n");
313*86b64dcbSAndroid Build Coastguard Worker g_printerr(" t: %d, ep: %d, actual_length: %d, buffer_length: %d\n",
314*86b64dcbSAndroid Build Coastguard Worker urb->type, urb->endpoint, urb->actual_length, urb->buffer_length);
315*86b64dcbSAndroid Build Coastguard Worker if (urb->type == USBDEVFS_URB_TYPE_CONTROL || urb->endpoint & LIBUSB_ENDPOINT_IN)
316*86b64dcbSAndroid Build Coastguard Worker dump_buffer(urb->buffer, urb->buffer_length);
317*86b64dcbSAndroid Build Coastguard Worker g_printerr("Looking for:\n");
318*86b64dcbSAndroid Build Coastguard Worker g_printerr(" t: %d, ep: %d, actual_length: %d, buffer_length: %d\n",
319*86b64dcbSAndroid Build Coastguard Worker fixture->chat->type, fixture->chat->endpoint,
320*86b64dcbSAndroid Build Coastguard Worker fixture->chat->actual_length, fixture->chat->buffer_length);
321*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->buffer)
322*86b64dcbSAndroid Build Coastguard Worker dump_buffer(fixture->chat->buffer, buflen);
323*86b64dcbSAndroid Build Coastguard Worker
324*86b64dcbSAndroid Build Coastguard Worker return FALSE;
325*86b64dcbSAndroid Build Coastguard Worker }
326*86b64dcbSAndroid Build Coastguard Worker
327*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_REAPURB:
328*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_REAPURBNDELAY: {
329*86b64dcbSAndroid Build Coastguard Worker g_autoptr(UMockdevIoctlData) urb_ptr = NULL;
330*86b64dcbSAndroid Build Coastguard Worker g_autoptr(UMockdevIoctlData) urb_data = NULL;
331*86b64dcbSAndroid Build Coastguard Worker
332*86b64dcbSAndroid Build Coastguard Worker if (fixture->discarded_urbs) {
333*86b64dcbSAndroid Build Coastguard Worker urb_data = fixture->discarded_urbs->data;
334*86b64dcbSAndroid Build Coastguard Worker urb = (struct usbdevfs_urb*) urb_data->data;
335*86b64dcbSAndroid Build Coastguard Worker fixture->discarded_urbs = g_list_delete_link(fixture->discarded_urbs, fixture->discarded_urbs);
336*86b64dcbSAndroid Build Coastguard Worker urb->status = -ENOENT;
337*86b64dcbSAndroid Build Coastguard Worker
338*86b64dcbSAndroid Build Coastguard Worker urb_ptr = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(gpointer), NULL);
339*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_data_set_ptr(urb_ptr, 0, urb_data);
340*86b64dcbSAndroid Build Coastguard Worker
341*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, 0, 0);
342*86b64dcbSAndroid Build Coastguard Worker return TRUE;
343*86b64dcbSAndroid Build Coastguard Worker }
344*86b64dcbSAndroid Build Coastguard Worker
345*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat && fixture->chat->reap) {
346*86b64dcbSAndroid Build Coastguard Worker GList *l = g_list_find(fixture->flying_urbs, fixture->chat->submit_urb);
347*86b64dcbSAndroid Build Coastguard Worker
348*86b64dcbSAndroid Build Coastguard Worker if (l) {
349*86b64dcbSAndroid Build Coastguard Worker fixture->flying_urbs = g_list_remove_link(fixture->flying_urbs, fixture->flying_urbs);
350*86b64dcbSAndroid Build Coastguard Worker
351*86b64dcbSAndroid Build Coastguard Worker urb_data = fixture->chat->submit_urb;
352*86b64dcbSAndroid Build Coastguard Worker urb = (struct usbdevfs_urb*) urb_data->data;
353*86b64dcbSAndroid Build Coastguard Worker urb->actual_length = fixture->chat->actual_length;
354*86b64dcbSAndroid Build Coastguard Worker if (urb->type == USBDEVFS_URB_TYPE_CONTROL && urb->actual_length)
355*86b64dcbSAndroid Build Coastguard Worker urb->actual_length -= 8;
356*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->buffer)
357*86b64dcbSAndroid Build Coastguard Worker memcpy(urb->buffer, fixture->chat->buffer, fixture->chat->actual_length);
358*86b64dcbSAndroid Build Coastguard Worker urb->status = fixture->chat->status;
359*86b64dcbSAndroid Build Coastguard Worker
360*86b64dcbSAndroid Build Coastguard Worker urb_ptr = umockdev_ioctl_data_resolve(ioctl_arg, 0, sizeof(gpointer), NULL);
361*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_data_set_ptr(urb_ptr, 0, urb_data);
362*86b64dcbSAndroid Build Coastguard Worker if (fixture->chat->next)
363*86b64dcbSAndroid Build Coastguard Worker fixture->chat = fixture->chat->next;
364*86b64dcbSAndroid Build Coastguard Worker else
365*86b64dcbSAndroid Build Coastguard Worker fixture->chat += 1;
366*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, 0, 0);
367*86b64dcbSAndroid Build Coastguard Worker return TRUE;
368*86b64dcbSAndroid Build Coastguard Worker }
369*86b64dcbSAndroid Build Coastguard Worker }
370*86b64dcbSAndroid Build Coastguard Worker
371*86b64dcbSAndroid Build Coastguard Worker /* Nothing to reap */
372*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, -1, EAGAIN);
373*86b64dcbSAndroid Build Coastguard Worker return TRUE;
374*86b64dcbSAndroid Build Coastguard Worker }
375*86b64dcbSAndroid Build Coastguard Worker
376*86b64dcbSAndroid Build Coastguard Worker case USBDEVFS_DISCARDURB: {
377*86b64dcbSAndroid Build Coastguard Worker GList *l = g_list_find_custom(fixture->flying_urbs, *(void**) ioctl_arg->data, cmp_ioctl_data_addr);
378*86b64dcbSAndroid Build Coastguard Worker
379*86b64dcbSAndroid Build Coastguard Worker if (l) {
380*86b64dcbSAndroid Build Coastguard Worker fixture->discarded_urbs = g_list_append(fixture->discarded_urbs, l->data);
381*86b64dcbSAndroid Build Coastguard Worker fixture->flying_urbs = g_list_delete_link(fixture->flying_urbs, l);
382*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, 0, 0);
383*86b64dcbSAndroid Build Coastguard Worker } else {
384*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_client_complete(client, -1, EINVAL);
385*86b64dcbSAndroid Build Coastguard Worker }
386*86b64dcbSAndroid Build Coastguard Worker
387*86b64dcbSAndroid Build Coastguard Worker return TRUE;
388*86b64dcbSAndroid Build Coastguard Worker }
389*86b64dcbSAndroid Build Coastguard Worker
390*86b64dcbSAndroid Build Coastguard Worker default:
391*86b64dcbSAndroid Build Coastguard Worker return FALSE;
392*86b64dcbSAndroid Build Coastguard Worker }
393*86b64dcbSAndroid Build Coastguard Worker }
394*86b64dcbSAndroid Build Coastguard Worker
395*86b64dcbSAndroid Build Coastguard Worker static void
test_fixture_add_canon(UMockdevTestbedFixture * fixture)396*86b64dcbSAndroid Build Coastguard Worker test_fixture_add_canon(UMockdevTestbedFixture * fixture)
397*86b64dcbSAndroid Build Coastguard Worker {
398*86b64dcbSAndroid Build Coastguard Worker /* Setup first, so we can be sure libusb_open works when the add uevent
399*86b64dcbSAndroid Build Coastguard Worker * happens.
400*86b64dcbSAndroid Build Coastguard Worker */
401*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(umockdev_testbed_attach_ioctl(fixture->testbed, "/dev/bus/usb/001/001", fixture->handler, NULL), ==, 1);
402*86b64dcbSAndroid Build Coastguard Worker
403*86b64dcbSAndroid Build Coastguard Worker /* NOTE: add_device would not create a file, needed for device emulation */
404*86b64dcbSAndroid Build Coastguard Worker /* XXX: Racy, see https://github.com/martinpitt/umockdev/issues/173 */
405*86b64dcbSAndroid Build Coastguard Worker umockdev_testbed_add_from_string(fixture->testbed,
406*86b64dcbSAndroid Build Coastguard Worker "P: /devices/usb1\n"
407*86b64dcbSAndroid Build Coastguard Worker "N: bus/usb/001/001\n"
408*86b64dcbSAndroid Build Coastguard Worker "E: SUBSYSTEM=usb\n"
409*86b64dcbSAndroid Build Coastguard Worker "E: DRIVER=usb\n"
410*86b64dcbSAndroid Build Coastguard Worker "E: BUSNUM=001\n"
411*86b64dcbSAndroid Build Coastguard Worker "E: DEVNUM=001\n"
412*86b64dcbSAndroid Build Coastguard Worker "E: DEVNAME=/dev/bus/usb/001/001\n"
413*86b64dcbSAndroid Build Coastguard Worker "E: DEVTYPE=usb_device\n"
414*86b64dcbSAndroid Build Coastguard Worker "A: bConfigurationValue=1\\n\n"
415*86b64dcbSAndroid Build Coastguard Worker "A: busnum=1\\n\n"
416*86b64dcbSAndroid Build Coastguard Worker "A: devnum=1\\n\n"
417*86b64dcbSAndroid Build Coastguard Worker "A: bConfigurationValue=1\\n\n"
418*86b64dcbSAndroid Build Coastguard Worker "A: speed=480\\n\n"
419*86b64dcbSAndroid Build Coastguard Worker /* descriptor from a Canon PowerShot SX200; VID 04a9 PID 31c0 */
420*86b64dcbSAndroid Build Coastguard Worker "H: descriptors="
421*86b64dcbSAndroid Build Coastguard Worker "1201000200000040a904c03102000102"
422*86b64dcbSAndroid Build Coastguard Worker "030109022700010100c0010904000003"
423*86b64dcbSAndroid Build Coastguard Worker "06010100070581020002000705020200"
424*86b64dcbSAndroid Build Coastguard Worker "020007058303080009\n",
425*86b64dcbSAndroid Build Coastguard Worker NULL);
426*86b64dcbSAndroid Build Coastguard Worker }
427*86b64dcbSAndroid Build Coastguard Worker
428*86b64dcbSAndroid Build Coastguard Worker static void
test_fixture_setup_libusb(UMockdevTestbedFixture * fixture,int devcount)429*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_libusb(UMockdevTestbedFixture * fixture, int devcount)
430*86b64dcbSAndroid Build Coastguard Worker {
431*86b64dcbSAndroid Build Coastguard Worker libusb_device **devs = NULL;
432*86b64dcbSAndroid Build Coastguard Worker
433*86b64dcbSAndroid Build Coastguard Worker libusb_init_context(/*ctx=*/&fixture->ctx, /*options=*/NULL, /*num_options=*/0);
434*86b64dcbSAndroid Build Coastguard Worker
435*86b64dcbSAndroid Build Coastguard Worker /* Suppress global log messages completely
436*86b64dcbSAndroid Build Coastguard Worker * (though, in some tests it might be interesting to check there are no real ones).
437*86b64dcbSAndroid Build Coastguard Worker */
438*86b64dcbSAndroid Build Coastguard Worker libusb_set_log_cb (NULL, log_handler_null, LIBUSB_LOG_CB_GLOBAL);
439*86b64dcbSAndroid Build Coastguard Worker libusb_set_option (fixture->ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG);
440*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, devcount);
441*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
442*86b64dcbSAndroid Build Coastguard Worker libusb_set_log_cb (fixture->ctx, log_handler, LIBUSB_LOG_CB_CONTEXT);
443*86b64dcbSAndroid Build Coastguard Worker }
444*86b64dcbSAndroid Build Coastguard Worker
445*86b64dcbSAndroid Build Coastguard Worker static void
test_fixture_setup_common(UMockdevTestbedFixture * fixture)446*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_common(UMockdevTestbedFixture * fixture)
447*86b64dcbSAndroid Build Coastguard Worker {
448*86b64dcbSAndroid Build Coastguard Worker g_assert(cur_fixture == NULL);
449*86b64dcbSAndroid Build Coastguard Worker cur_fixture = fixture;
450*86b64dcbSAndroid Build Coastguard Worker
451*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_init(&fixture->mutex, NULL);
452*86b64dcbSAndroid Build Coastguard Worker
453*86b64dcbSAndroid Build Coastguard Worker fixture->testbed = umockdev_testbed_new();
454*86b64dcbSAndroid Build Coastguard Worker g_assert(fixture->testbed != NULL);
455*86b64dcbSAndroid Build Coastguard Worker fixture->root_dir = umockdev_testbed_get_root_dir(fixture->testbed);
456*86b64dcbSAndroid Build Coastguard Worker fixture->sys_dir = umockdev_testbed_get_sys_dir(fixture->testbed);
457*86b64dcbSAndroid Build Coastguard Worker
458*86b64dcbSAndroid Build Coastguard Worker fixture->handler = umockdev_ioctl_base_new();
459*86b64dcbSAndroid Build Coastguard Worker g_object_connect(fixture->handler, "signal-after::handle-ioctl", handle_ioctl_cb, fixture, NULL);
460*86b64dcbSAndroid Build Coastguard Worker }
461*86b64dcbSAndroid Build Coastguard Worker
462*86b64dcbSAndroid Build Coastguard Worker static void
test_fixture_setup_empty(UMockdevTestbedFixture * fixture,UNUSED_DATA)463*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_empty(UMockdevTestbedFixture * fixture, UNUSED_DATA)
464*86b64dcbSAndroid Build Coastguard Worker {
465*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_common(fixture);
466*86b64dcbSAndroid Build Coastguard Worker
467*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_libusb(fixture, 0);
468*86b64dcbSAndroid Build Coastguard Worker }
469*86b64dcbSAndroid Build Coastguard Worker
470*86b64dcbSAndroid Build Coastguard Worker static void
test_fixture_setup_with_canon(UMockdevTestbedFixture * fixture,UNUSED_DATA)471*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon(UMockdevTestbedFixture * fixture, UNUSED_DATA)
472*86b64dcbSAndroid Build Coastguard Worker {
473*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_common(fixture);
474*86b64dcbSAndroid Build Coastguard Worker
475*86b64dcbSAndroid Build Coastguard Worker test_fixture_add_canon(fixture);
476*86b64dcbSAndroid Build Coastguard Worker
477*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_libusb(fixture, 1);
478*86b64dcbSAndroid Build Coastguard Worker }
479*86b64dcbSAndroid Build Coastguard Worker
480*86b64dcbSAndroid Build Coastguard Worker static void
test_fixture_teardown(UMockdevTestbedFixture * fixture,UNUSED_DATA)481*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown(UMockdevTestbedFixture * fixture, UNUSED_DATA)
482*86b64dcbSAndroid Build Coastguard Worker {
483*86b64dcbSAndroid Build Coastguard Worker g_assert(cur_fixture == fixture);
484*86b64dcbSAndroid Build Coastguard Worker
485*86b64dcbSAndroid Build Coastguard Worker /* Abort if there are any warnings/errors in the log */
486*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
487*86b64dcbSAndroid Build Coastguard Worker
488*86b64dcbSAndroid Build Coastguard Worker if (fixture->ctx) {
489*86b64dcbSAndroid Build Coastguard Worker libusb_device **devs = NULL;
490*86b64dcbSAndroid Build Coastguard Worker int count = libusb_get_device_list(fixture->ctx, &devs);
491*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
492*86b64dcbSAndroid Build Coastguard Worker
493*86b64dcbSAndroid Build Coastguard Worker libusb_exit (fixture->ctx);
494*86b64dcbSAndroid Build Coastguard Worker
495*86b64dcbSAndroid Build Coastguard Worker /* libusb_exit should result in the correct number of devices being destroyed */
496*86b64dcbSAndroid Build Coastguard Worker for (int i = 0; i < count; i++)
497*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_unref_device");
498*86b64dcbSAndroid Build Coastguard Worker
499*86b64dcbSAndroid Build Coastguard Worker assert_libusb_no_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_unref_device");
500*86b64dcbSAndroid Build Coastguard Worker }
501*86b64dcbSAndroid Build Coastguard Worker libusb_set_log_cb (NULL, NULL, LIBUSB_LOG_CB_GLOBAL);
502*86b64dcbSAndroid Build Coastguard Worker cur_fixture = NULL;
503*86b64dcbSAndroid Build Coastguard Worker
504*86b64dcbSAndroid Build Coastguard Worker /* Abort if there are any warnings/errors in the log */
505*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
506*86b64dcbSAndroid Build Coastguard Worker fixture->ctx = NULL;
507*86b64dcbSAndroid Build Coastguard Worker g_assert_null(fixture->libusb_log);
508*86b64dcbSAndroid Build Coastguard Worker
509*86b64dcbSAndroid Build Coastguard Worker g_clear_object(&fixture->handler);
510*86b64dcbSAndroid Build Coastguard Worker g_clear_object(&fixture->testbed);
511*86b64dcbSAndroid Build Coastguard Worker
512*86b64dcbSAndroid Build Coastguard Worker /* verify that temp dir gets cleaned up properly */
513*86b64dcbSAndroid Build Coastguard Worker g_assert(!g_file_test(fixture->root_dir, G_FILE_TEST_EXISTS));
514*86b64dcbSAndroid Build Coastguard Worker g_free(fixture->root_dir);
515*86b64dcbSAndroid Build Coastguard Worker g_free(fixture->sys_dir);
516*86b64dcbSAndroid Build Coastguard Worker
517*86b64dcbSAndroid Build Coastguard Worker while (fixture->flying_urbs) {
518*86b64dcbSAndroid Build Coastguard Worker umockdev_ioctl_data_unref (fixture->flying_urbs->data);
519*86b64dcbSAndroid Build Coastguard Worker fixture->flying_urbs = g_list_delete_link (fixture->flying_urbs, fixture->flying_urbs);
520*86b64dcbSAndroid Build Coastguard Worker }
521*86b64dcbSAndroid Build Coastguard Worker
522*86b64dcbSAndroid Build Coastguard Worker pthread_mutex_destroy(&fixture->mutex);
523*86b64dcbSAndroid Build Coastguard Worker }
524*86b64dcbSAndroid Build Coastguard Worker
525*86b64dcbSAndroid Build Coastguard Worker static void
test_open_close(UMockdevTestbedFixture * fixture,UNUSED_DATA)526*86b64dcbSAndroid Build Coastguard Worker test_open_close(UMockdevTestbedFixture * fixture, UNUSED_DATA)
527*86b64dcbSAndroid Build Coastguard Worker {
528*86b64dcbSAndroid Build Coastguard Worker libusb_device **devs = NULL;
529*86b64dcbSAndroid Build Coastguard Worker struct libusb_device_descriptor desc;
530*86b64dcbSAndroid Build Coastguard Worker libusb_device_handle *handle = NULL;
531*86b64dcbSAndroid Build Coastguard Worker
532*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 1);
533*86b64dcbSAndroid Build Coastguard Worker /* The linux_enumerate_device may happen from a different thread */
534*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_get_device_list");
535*86b64dcbSAndroid Build Coastguard Worker /* We have exactly one device */
536*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_bus_number(devs[0]), ==, 1);
537*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_address(devs[0]), ==, 1);
538*86b64dcbSAndroid Build Coastguard Worker
539*86b64dcbSAndroid Build Coastguard Worker /* Get/Check descriptor */
540*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
541*86b64dcbSAndroid Build Coastguard Worker libusb_get_device_descriptor (devs[0], &desc);
542*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "libusb_get_device_descriptor");
543*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(desc.idVendor, ==, 0x04a9);
544*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(desc.idProduct, ==, 0x31c0);
545*86b64dcbSAndroid Build Coastguard Worker
546*86b64dcbSAndroid Build Coastguard Worker /* Open and close */
547*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_open(devs[0], &handle), ==, 0);
548*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "usbi_add_event_source");
549*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
550*86b64dcbSAndroid Build Coastguard Worker libusb_close(handle);
551*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "usbi_remove_event_source");
552*86b64dcbSAndroid Build Coastguard Worker
553*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
554*86b64dcbSAndroid Build Coastguard Worker
555*86b64dcbSAndroid Build Coastguard Worker /* Open and close using vid/pid */
556*86b64dcbSAndroid Build Coastguard Worker handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
557*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
558*86b64dcbSAndroid Build Coastguard Worker libusb_close(handle);
559*86b64dcbSAndroid Build Coastguard Worker }
560*86b64dcbSAndroid Build Coastguard Worker
561*86b64dcbSAndroid Build Coastguard Worker static void
test_implicit_default(UMockdevTestbedFixture * fixture,UNUSED_DATA)562*86b64dcbSAndroid Build Coastguard Worker test_implicit_default(UMockdevTestbedFixture * fixture, UNUSED_DATA)
563*86b64dcbSAndroid Build Coastguard Worker {
564*86b64dcbSAndroid Build Coastguard Worker libusb_device **devs = NULL;
565*86b64dcbSAndroid Build Coastguard Worker
566*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
567*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
568*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
569*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[usbi_get_context\\].*implicit default");
570*86b64dcbSAndroid Build Coastguard Worker
571*86b64dcbSAndroid Build Coastguard Worker /* Only warns once */
572*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
573*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
574*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_INFO);
575*86b64dcbSAndroid Build Coastguard Worker
576*86b64dcbSAndroid Build Coastguard Worker libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0);
577*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_list(NULL, &devs), ==, 1);
578*86b64dcbSAndroid Build Coastguard Worker libusb_exit(NULL);
579*86b64dcbSAndroid Build Coastguard Worker
580*86b64dcbSAndroid Build Coastguard Worker /* We free late, causing a warning from libusb_exit. However,
581*86b64dcbSAndroid Build Coastguard Worker * we never see this warning (i.e. test success) because it is on a
582*86b64dcbSAndroid Build Coastguard Worker * different context.
583*86b64dcbSAndroid Build Coastguard Worker */
584*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
585*86b64dcbSAndroid Build Coastguard Worker }
586*86b64dcbSAndroid Build Coastguard Worker
587*86b64dcbSAndroid Build Coastguard Worker static void
test_close_flying(UMockdevTestbedFixture * fixture,UNUSED_DATA)588*86b64dcbSAndroid Build Coastguard Worker test_close_flying(UMockdevTestbedFixture * fixture, UNUSED_DATA)
589*86b64dcbSAndroid Build Coastguard Worker {
590*86b64dcbSAndroid Build Coastguard Worker UsbChat chat[] = {
591*86b64dcbSAndroid Build Coastguard Worker {
592*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
593*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_BULK,
594*86b64dcbSAndroid Build Coastguard Worker .endpoint = LIBUSB_ENDPOINT_OUT,
595*86b64dcbSAndroid Build Coastguard Worker .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
596*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 4,
597*86b64dcbSAndroid Build Coastguard Worker },
598*86b64dcbSAndroid Build Coastguard Worker { .submit = FALSE }
599*86b64dcbSAndroid Build Coastguard Worker };
600*86b64dcbSAndroid Build Coastguard Worker libusb_device_handle *handle = NULL;
601*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer = NULL;
602*86b64dcbSAndroid Build Coastguard Worker
603*86b64dcbSAndroid Build Coastguard Worker fixture->chat = chat;
604*86b64dcbSAndroid Build Coastguard Worker
605*86b64dcbSAndroid Build Coastguard Worker /* Open */
606*86b64dcbSAndroid Build Coastguard Worker handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
607*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
608*86b64dcbSAndroid Build Coastguard Worker
609*86b64dcbSAndroid Build Coastguard Worker transfer = libusb_alloc_transfer(0);
610*86b64dcbSAndroid Build Coastguard Worker libusb_fill_bulk_transfer(transfer,
611*86b64dcbSAndroid Build Coastguard Worker handle,
612*86b64dcbSAndroid Build Coastguard Worker LIBUSB_ENDPOINT_OUT,
613*86b64dcbSAndroid Build Coastguard Worker (unsigned char*) chat[0].buffer,
614*86b64dcbSAndroid Build Coastguard Worker chat[0].buffer_length,
615*86b64dcbSAndroid Build Coastguard Worker NULL,
616*86b64dcbSAndroid Build Coastguard Worker NULL,
617*86b64dcbSAndroid Build Coastguard Worker 1);
618*86b64dcbSAndroid Build Coastguard Worker
619*86b64dcbSAndroid Build Coastguard Worker /* Submit */
620*86b64dcbSAndroid Build Coastguard Worker libusb_submit_transfer(transfer);
621*86b64dcbSAndroid Build Coastguard Worker
622*86b64dcbSAndroid Build Coastguard Worker /* Closing logs fat error (two lines) */
623*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
624*86b64dcbSAndroid Build Coastguard Worker libusb_close(handle);
625*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[do_close\\] .*connected as far as we know");
626*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[do_close\\] .*cancellation hasn't even been scheduled");
627*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "\\[do_close\\] Removed transfer");
628*86b64dcbSAndroid Build Coastguard Worker
629*86b64dcbSAndroid Build Coastguard Worker /* Free'ing the transfer works, and logs to the right context */
630*86b64dcbSAndroid Build Coastguard Worker libusb_free_transfer(transfer);
631*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "\\[libusb_free_transfer\\]");
632*86b64dcbSAndroid Build Coastguard Worker }
633*86b64dcbSAndroid Build Coastguard Worker
634*86b64dcbSAndroid Build Coastguard Worker static void
test_close_cancelled(UMockdevTestbedFixture * fixture,UNUSED_DATA)635*86b64dcbSAndroid Build Coastguard Worker test_close_cancelled(UMockdevTestbedFixture * fixture, UNUSED_DATA)
636*86b64dcbSAndroid Build Coastguard Worker {
637*86b64dcbSAndroid Build Coastguard Worker UsbChat chat[] = {
638*86b64dcbSAndroid Build Coastguard Worker {
639*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
640*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_BULK,
641*86b64dcbSAndroid Build Coastguard Worker .endpoint = LIBUSB_ENDPOINT_OUT,
642*86b64dcbSAndroid Build Coastguard Worker .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
643*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 4,
644*86b64dcbSAndroid Build Coastguard Worker },
645*86b64dcbSAndroid Build Coastguard Worker { .submit = FALSE }
646*86b64dcbSAndroid Build Coastguard Worker };
647*86b64dcbSAndroid Build Coastguard Worker libusb_device_handle *handle = NULL;
648*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer = NULL;
649*86b64dcbSAndroid Build Coastguard Worker
650*86b64dcbSAndroid Build Coastguard Worker fixture->chat = chat;
651*86b64dcbSAndroid Build Coastguard Worker
652*86b64dcbSAndroid Build Coastguard Worker /* Open */
653*86b64dcbSAndroid Build Coastguard Worker handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
654*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
655*86b64dcbSAndroid Build Coastguard Worker
656*86b64dcbSAndroid Build Coastguard Worker transfer = libusb_alloc_transfer(0);
657*86b64dcbSAndroid Build Coastguard Worker libusb_fill_bulk_transfer(transfer,
658*86b64dcbSAndroid Build Coastguard Worker handle,
659*86b64dcbSAndroid Build Coastguard Worker LIBUSB_ENDPOINT_OUT,
660*86b64dcbSAndroid Build Coastguard Worker (unsigned char*) chat[0].buffer,
661*86b64dcbSAndroid Build Coastguard Worker chat[0].buffer_length,
662*86b64dcbSAndroid Build Coastguard Worker NULL,
663*86b64dcbSAndroid Build Coastguard Worker NULL,
664*86b64dcbSAndroid Build Coastguard Worker 1);
665*86b64dcbSAndroid Build Coastguard Worker
666*86b64dcbSAndroid Build Coastguard Worker /* Submit */
667*86b64dcbSAndroid Build Coastguard Worker libusb_submit_transfer(transfer);
668*86b64dcbSAndroid Build Coastguard Worker libusb_cancel_transfer(transfer);
669*86b64dcbSAndroid Build Coastguard Worker
670*86b64dcbSAndroid Build Coastguard Worker /* Closing logs fat error (two lines) */
671*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
672*86b64dcbSAndroid Build Coastguard Worker libusb_close(handle);
673*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[do_close\\] .*connected as far as we know");
674*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_WARNING, "\\[do_close\\] .*cancellation.*hasn't completed");
675*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_DEBUG, "\\[do_close\\] Removed transfer");
676*86b64dcbSAndroid Build Coastguard Worker
677*86b64dcbSAndroid Build Coastguard Worker libusb_free_transfer(transfer);
678*86b64dcbSAndroid Build Coastguard Worker }
679*86b64dcbSAndroid Build Coastguard Worker
680*86b64dcbSAndroid Build Coastguard Worker static void
test_ctx_destroy(UMockdevTestbedFixture * fixture,UNUSED_DATA)681*86b64dcbSAndroid Build Coastguard Worker test_ctx_destroy(UMockdevTestbedFixture * fixture, UNUSED_DATA)
682*86b64dcbSAndroid Build Coastguard Worker {
683*86b64dcbSAndroid Build Coastguard Worker UsbChat chat[] = {
684*86b64dcbSAndroid Build Coastguard Worker {
685*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
686*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_BULK,
687*86b64dcbSAndroid Build Coastguard Worker .endpoint = LIBUSB_ENDPOINT_OUT,
688*86b64dcbSAndroid Build Coastguard Worker .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
689*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 4,
690*86b64dcbSAndroid Build Coastguard Worker },
691*86b64dcbSAndroid Build Coastguard Worker { .submit = FALSE }
692*86b64dcbSAndroid Build Coastguard Worker };
693*86b64dcbSAndroid Build Coastguard Worker libusb_device_handle *handle = NULL;
694*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer = NULL;
695*86b64dcbSAndroid Build Coastguard Worker
696*86b64dcbSAndroid Build Coastguard Worker fixture->chat = chat;
697*86b64dcbSAndroid Build Coastguard Worker
698*86b64dcbSAndroid Build Coastguard Worker /* Open */
699*86b64dcbSAndroid Build Coastguard Worker handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
700*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
701*86b64dcbSAndroid Build Coastguard Worker
702*86b64dcbSAndroid Build Coastguard Worker transfer = libusb_alloc_transfer(0);
703*86b64dcbSAndroid Build Coastguard Worker libusb_fill_bulk_transfer(transfer,
704*86b64dcbSAndroid Build Coastguard Worker handle,
705*86b64dcbSAndroid Build Coastguard Worker LIBUSB_ENDPOINT_OUT,
706*86b64dcbSAndroid Build Coastguard Worker (unsigned char*) chat[0].buffer,
707*86b64dcbSAndroid Build Coastguard Worker chat[0].buffer_length,
708*86b64dcbSAndroid Build Coastguard Worker NULL,
709*86b64dcbSAndroid Build Coastguard Worker NULL,
710*86b64dcbSAndroid Build Coastguard Worker 1);
711*86b64dcbSAndroid Build Coastguard Worker
712*86b64dcbSAndroid Build Coastguard Worker /* Submit */
713*86b64dcbSAndroid Build Coastguard Worker libusb_submit_transfer(transfer);
714*86b64dcbSAndroid Build Coastguard Worker
715*86b64dcbSAndroid Build Coastguard Worker /* Now we are evil and destroy the ctx! */
716*86b64dcbSAndroid Build Coastguard Worker libusb_exit(fixture->ctx);
717*86b64dcbSAndroid Build Coastguard Worker
718*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_WARNING, "\\[libusb_exit\\] device.*still referenced");
719*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_WARNING, "\\[libusb_exit\\] application left some devices open");
720*86b64dcbSAndroid Build Coastguard Worker
721*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
722*86b64dcbSAndroid Build Coastguard Worker fixture->ctx = NULL;
723*86b64dcbSAndroid Build Coastguard Worker
724*86b64dcbSAndroid Build Coastguard Worker /* XXX: Closing crashes the application as it unref's the NULL pointer */
725*86b64dcbSAndroid Build Coastguard Worker /* libusb_close(handle); */
726*86b64dcbSAndroid Build Coastguard Worker
727*86b64dcbSAndroid Build Coastguard Worker libusb_free_transfer(transfer);
728*86b64dcbSAndroid Build Coastguard Worker }
729*86b64dcbSAndroid Build Coastguard Worker
730*86b64dcbSAndroid Build Coastguard Worker static void
test_get_string_descriptor(UMockdevTestbedFixture * fixture,UNUSED_DATA)731*86b64dcbSAndroid Build Coastguard Worker test_get_string_descriptor(UMockdevTestbedFixture * fixture, UNUSED_DATA)
732*86b64dcbSAndroid Build Coastguard Worker {
733*86b64dcbSAndroid Build Coastguard Worker unsigned char data[255] = { 0, };
734*86b64dcbSAndroid Build Coastguard Worker libusb_device_handle *handle = NULL;
735*86b64dcbSAndroid Build Coastguard Worker UsbChat chat[] = {
736*86b64dcbSAndroid Build Coastguard Worker {
737*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
738*86b64dcbSAndroid Build Coastguard Worker .reaps = &chat[1],
739*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_CONTROL,
740*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 12, /* 8 byte out*/
741*86b64dcbSAndroid Build Coastguard Worker .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00",
742*86b64dcbSAndroid Build Coastguard Worker }, {
743*86b64dcbSAndroid Build Coastguard Worker /* String with content 0x0409 (en_US) */
744*86b64dcbSAndroid Build Coastguard Worker .reap = TRUE,
745*86b64dcbSAndroid Build Coastguard Worker .actual_length = 12,
746*86b64dcbSAndroid Build Coastguard Worker .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00\x04\x03\x09\x04",
747*86b64dcbSAndroid Build Coastguard Worker }, {
748*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
749*86b64dcbSAndroid Build Coastguard Worker .reaps = &chat[3],
750*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_CONTROL,
751*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 263, /* 8 byte out*/
752*86b64dcbSAndroid Build Coastguard Worker .buffer = (const unsigned char*) "\x80\x06\x01\x03\x09\x04\xff\x00",
753*86b64dcbSAndroid Build Coastguard Worker }, {
754*86b64dcbSAndroid Build Coastguard Worker /* 4 byte string, "ab" */
755*86b64dcbSAndroid Build Coastguard Worker .reap = TRUE,
756*86b64dcbSAndroid Build Coastguard Worker .actual_length = 14,
757*86b64dcbSAndroid Build Coastguard Worker .buffer = (const unsigned char*) "\x80\x06\x01\x03\x09\x04\xff\x00\x06\x03\x61\x00\x62\x00",
758*86b64dcbSAndroid Build Coastguard Worker }, {
759*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
760*86b64dcbSAndroid Build Coastguard Worker .reaps = &chat[5],
761*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_CONTROL,
762*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 12, /* 8 byte out*/
763*86b64dcbSAndroid Build Coastguard Worker .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00",
764*86b64dcbSAndroid Build Coastguard Worker }, {
765*86b64dcbSAndroid Build Coastguard Worker .reap = TRUE,
766*86b64dcbSAndroid Build Coastguard Worker .status = -ENOENT,
767*86b64dcbSAndroid Build Coastguard Worker }, {
768*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
769*86b64dcbSAndroid Build Coastguard Worker .status = -ENOENT,
770*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_CONTROL,
771*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 12, /* 8 byte out*/
772*86b64dcbSAndroid Build Coastguard Worker .buffer = (const unsigned char*) "\x80\x06\x00\x03\x00\x00\x04\x00",
773*86b64dcbSAndroid Build Coastguard Worker }, {
774*86b64dcbSAndroid Build Coastguard Worker .submit = FALSE,
775*86b64dcbSAndroid Build Coastguard Worker }
776*86b64dcbSAndroid Build Coastguard Worker };
777*86b64dcbSAndroid Build Coastguard Worker
778*86b64dcbSAndroid Build Coastguard Worker fixture->chat = chat;
779*86b64dcbSAndroid Build Coastguard Worker
780*86b64dcbSAndroid Build Coastguard Worker handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
781*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
782*86b64dcbSAndroid Build Coastguard Worker
783*86b64dcbSAndroid Build Coastguard Worker /* The chat allows us to fetch the descriptor */
784*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_string_descriptor_ascii(handle, 1, data, sizeof(data)), ==, 2);
785*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(memcmp(data, "ab", 2), ==, 0);
786*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
787*86b64dcbSAndroid Build Coastguard Worker
788*86b64dcbSAndroid Build Coastguard Worker /* Again, but the URB fails with ENOENT when reaping */
789*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_string_descriptor_ascii(handle, 1, data, sizeof(data)), ==, -1);
790*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
791*86b64dcbSAndroid Build Coastguard Worker
792*86b64dcbSAndroid Build Coastguard Worker /* Again, but the URB fails to submit with ENOENT */
793*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_string_descriptor_ascii(handle, 1, data, sizeof(data)), ==, -1);
794*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(fixture, LIBUSB_LOG_LEVEL_ERROR, "\\[submit_control_transfer\\] submiturb failed, errno=2");
795*86b64dcbSAndroid Build Coastguard Worker clear_libusb_log(fixture, LIBUSB_LOG_LEVEL_DEBUG);
796*86b64dcbSAndroid Build Coastguard Worker
797*86b64dcbSAndroid Build Coastguard Worker libusb_close(handle);
798*86b64dcbSAndroid Build Coastguard Worker }
799*86b64dcbSAndroid Build Coastguard Worker
800*86b64dcbSAndroid Build Coastguard Worker static void
transfer_cb_inc_user_data(struct libusb_transfer * transfer)801*86b64dcbSAndroid Build Coastguard Worker transfer_cb_inc_user_data(struct libusb_transfer *transfer)
802*86b64dcbSAndroid Build Coastguard Worker {
803*86b64dcbSAndroid Build Coastguard Worker *(int*)transfer->user_data += 1;
804*86b64dcbSAndroid Build Coastguard Worker }
805*86b64dcbSAndroid Build Coastguard Worker
806*86b64dcbSAndroid Build Coastguard Worker static void
test_timeout(UMockdevTestbedFixture * fixture,UNUSED_DATA)807*86b64dcbSAndroid Build Coastguard Worker test_timeout(UMockdevTestbedFixture * fixture, UNUSED_DATA)
808*86b64dcbSAndroid Build Coastguard Worker {
809*86b64dcbSAndroid Build Coastguard Worker UsbChat chat[] = {
810*86b64dcbSAndroid Build Coastguard Worker {
811*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
812*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_BULK,
813*86b64dcbSAndroid Build Coastguard Worker .endpoint = LIBUSB_ENDPOINT_OUT,
814*86b64dcbSAndroid Build Coastguard Worker .buffer = (unsigned char[]) { 0x01, 0x02, 0x03, 0x04 },
815*86b64dcbSAndroid Build Coastguard Worker .buffer_length = 4,
816*86b64dcbSAndroid Build Coastguard Worker },
817*86b64dcbSAndroid Build Coastguard Worker {
818*86b64dcbSAndroid Build Coastguard Worker .submit = FALSE,
819*86b64dcbSAndroid Build Coastguard Worker }
820*86b64dcbSAndroid Build Coastguard Worker };
821*86b64dcbSAndroid Build Coastguard Worker int completed = 0;
822*86b64dcbSAndroid Build Coastguard Worker libusb_device_handle *handle = NULL;
823*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer = NULL;
824*86b64dcbSAndroid Build Coastguard Worker
825*86b64dcbSAndroid Build Coastguard Worker fixture->chat = chat;
826*86b64dcbSAndroid Build Coastguard Worker
827*86b64dcbSAndroid Build Coastguard Worker handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
828*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
829*86b64dcbSAndroid Build Coastguard Worker
830*86b64dcbSAndroid Build Coastguard Worker transfer = libusb_alloc_transfer(0);
831*86b64dcbSAndroid Build Coastguard Worker libusb_fill_bulk_transfer(transfer,
832*86b64dcbSAndroid Build Coastguard Worker handle,
833*86b64dcbSAndroid Build Coastguard Worker LIBUSB_ENDPOINT_OUT,
834*86b64dcbSAndroid Build Coastguard Worker (unsigned char*) chat[0].buffer,
835*86b64dcbSAndroid Build Coastguard Worker chat[0].buffer_length,
836*86b64dcbSAndroid Build Coastguard Worker transfer_cb_inc_user_data,
837*86b64dcbSAndroid Build Coastguard Worker &completed,
838*86b64dcbSAndroid Build Coastguard Worker 10);
839*86b64dcbSAndroid Build Coastguard Worker
840*86b64dcbSAndroid Build Coastguard Worker libusb_submit_transfer(transfer);
841*86b64dcbSAndroid Build Coastguard Worker while (!completed) {
842*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_handle_events_completed(fixture->ctx, &completed), ==, 0);
843*86b64dcbSAndroid Build Coastguard Worker /* Silence after one iteration. */
844*86b64dcbSAndroid Build Coastguard Worker fixture->libusb_log_silence = TRUE;
845*86b64dcbSAndroid Build Coastguard Worker }
846*86b64dcbSAndroid Build Coastguard Worker fixture->libusb_log_silence = FALSE;
847*86b64dcbSAndroid Build Coastguard Worker
848*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(transfer->status, ==, LIBUSB_TRANSFER_TIMED_OUT);
849*86b64dcbSAndroid Build Coastguard Worker libusb_free_transfer(transfer);
850*86b64dcbSAndroid Build Coastguard Worker
851*86b64dcbSAndroid Build Coastguard Worker libusb_close(handle);
852*86b64dcbSAndroid Build Coastguard Worker }
853*86b64dcbSAndroid Build Coastguard Worker
854*86b64dcbSAndroid Build Coastguard Worker #define THREADED_SUBMIT_URB_SETS 64
855*86b64dcbSAndroid Build Coastguard Worker #define THREADED_SUBMIT_URB_IN_FLIGHT 64
856*86b64dcbSAndroid Build Coastguard Worker typedef struct {
857*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfers[THREADED_SUBMIT_URB_IN_FLIGHT * THREADED_SUBMIT_URB_SETS];
858*86b64dcbSAndroid Build Coastguard Worker int submitted;
859*86b64dcbSAndroid Build Coastguard Worker int completed;
860*86b64dcbSAndroid Build Coastguard Worker int done;
861*86b64dcbSAndroid Build Coastguard Worker UMockdevTestbedFixture *fixture;
862*86b64dcbSAndroid Build Coastguard Worker } TestThreadedSubmit;
863*86b64dcbSAndroid Build Coastguard Worker
864*86b64dcbSAndroid Build Coastguard Worker static gpointer
transfer_submit_all_retry(TestThreadedSubmit * data)865*86b64dcbSAndroid Build Coastguard Worker transfer_submit_all_retry(TestThreadedSubmit *data)
866*86b64dcbSAndroid Build Coastguard Worker {
867*86b64dcbSAndroid Build Coastguard Worker for (guint i = 0; i < G_N_ELEMENTS(data->transfers); i++) {
868*86b64dcbSAndroid Build Coastguard Worker while (libusb_submit_transfer(data->transfers[i]) < 0) {
869*86b64dcbSAndroid Build Coastguard Worker assert_libusb_log_msg(data->fixture, LIBUSB_LOG_LEVEL_ERROR, "submit_bulk_transfer");
870*86b64dcbSAndroid Build Coastguard Worker continue;
871*86b64dcbSAndroid Build Coastguard Worker }
872*86b64dcbSAndroid Build Coastguard Worker
873*86b64dcbSAndroid Build Coastguard Worker data->submitted += 1;
874*86b64dcbSAndroid Build Coastguard Worker }
875*86b64dcbSAndroid Build Coastguard Worker
876*86b64dcbSAndroid Build Coastguard Worker return NULL;
877*86b64dcbSAndroid Build Coastguard Worker }
878*86b64dcbSAndroid Build Coastguard Worker
879*86b64dcbSAndroid Build Coastguard Worker static void LIBUSB_CALL
test_threaded_submit_transfer_cb(struct libusb_transfer * transfer)880*86b64dcbSAndroid Build Coastguard Worker test_threaded_submit_transfer_cb(struct libusb_transfer *transfer)
881*86b64dcbSAndroid Build Coastguard Worker {
882*86b64dcbSAndroid Build Coastguard Worker TestThreadedSubmit *data = transfer->user_data;
883*86b64dcbSAndroid Build Coastguard Worker
884*86b64dcbSAndroid Build Coastguard Worker /* We should only be receiving packets in the main thread */
885*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint (getpid(), ==, gettid());
886*86b64dcbSAndroid Build Coastguard Worker
887*86b64dcbSAndroid Build Coastguard Worker /* Check that the transfer buffer has the expected value */
888*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint (*(int*)transfer->buffer, ==, data->completed);
889*86b64dcbSAndroid Build Coastguard Worker data->completed += 1;
890*86b64dcbSAndroid Build Coastguard Worker
891*86b64dcbSAndroid Build Coastguard Worker if (data->completed == G_N_ELEMENTS(data->transfers))
892*86b64dcbSAndroid Build Coastguard Worker data->done = TRUE;
893*86b64dcbSAndroid Build Coastguard Worker }
894*86b64dcbSAndroid Build Coastguard Worker
895*86b64dcbSAndroid Build Coastguard Worker static void
test_threaded_submit(UMockdevTestbedFixture * fixture,UNUSED_DATA)896*86b64dcbSAndroid Build Coastguard Worker test_threaded_submit(UMockdevTestbedFixture * fixture, UNUSED_DATA)
897*86b64dcbSAndroid Build Coastguard Worker {
898*86b64dcbSAndroid Build Coastguard Worker GThread *thread = NULL;
899*86b64dcbSAndroid Build Coastguard Worker TestThreadedSubmit data = { .fixture = fixture };
900*86b64dcbSAndroid Build Coastguard Worker UsbChat out_msg = {
901*86b64dcbSAndroid Build Coastguard Worker .submit = TRUE,
902*86b64dcbSAndroid Build Coastguard Worker .type = USBDEVFS_URB_TYPE_BULK,
903*86b64dcbSAndroid Build Coastguard Worker .endpoint = LIBUSB_ENDPOINT_IN,
904*86b64dcbSAndroid Build Coastguard Worker .buffer_length = sizeof(int),
905*86b64dcbSAndroid Build Coastguard Worker };
906*86b64dcbSAndroid Build Coastguard Worker UsbChat in_msg = {
907*86b64dcbSAndroid Build Coastguard Worker .reap = TRUE,
908*86b64dcbSAndroid Build Coastguard Worker .actual_length = 4,
909*86b64dcbSAndroid Build Coastguard Worker };
910*86b64dcbSAndroid Build Coastguard Worker UsbChat *c;
911*86b64dcbSAndroid Build Coastguard Worker libusb_device_handle *handle = NULL;
912*86b64dcbSAndroid Build Coastguard Worker int urb;
913*86b64dcbSAndroid Build Coastguard Worker
914*86b64dcbSAndroid Build Coastguard Worker handle = libusb_open_device_with_vid_pid(fixture->ctx, 0x04a9, 0x31c0);
915*86b64dcbSAndroid Build Coastguard Worker g_assert_nonnull(handle);
916*86b64dcbSAndroid Build Coastguard Worker
917*86b64dcbSAndroid Build Coastguard Worker fixture->libusb_log_silence = TRUE;
918*86b64dcbSAndroid Build Coastguard Worker
919*86b64dcbSAndroid Build Coastguard Worker c = fixture->chat = g_new0(UsbChat, G_N_ELEMENTS(data.transfers) * 2 + 1);
920*86b64dcbSAndroid Build Coastguard Worker urb = 0;
921*86b64dcbSAndroid Build Coastguard Worker for (int i = 0; i < THREADED_SUBMIT_URB_SETS; i++) {
922*86b64dcbSAndroid Build Coastguard Worker for (int j = 0; j < THREADED_SUBMIT_URB_IN_FLIGHT; j++) {
923*86b64dcbSAndroid Build Coastguard Worker c[i*2*THREADED_SUBMIT_URB_IN_FLIGHT + j] = out_msg;
924*86b64dcbSAndroid Build Coastguard Worker c[i*2*THREADED_SUBMIT_URB_IN_FLIGHT + j].reaps = &c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j];
925*86b64dcbSAndroid Build Coastguard Worker c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j] = in_msg;
926*86b64dcbSAndroid Build Coastguard Worker c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j].buffer = (unsigned char*) g_new0(int, 1);
927*86b64dcbSAndroid Build Coastguard Worker *(int*) c[(i*2+1)*THREADED_SUBMIT_URB_IN_FLIGHT + j].buffer = urb;
928*86b64dcbSAndroid Build Coastguard Worker
929*86b64dcbSAndroid Build Coastguard Worker data.transfers[urb] = libusb_alloc_transfer(0);
930*86b64dcbSAndroid Build Coastguard Worker libusb_fill_bulk_transfer(data.transfers[urb],
931*86b64dcbSAndroid Build Coastguard Worker handle,
932*86b64dcbSAndroid Build Coastguard Worker LIBUSB_ENDPOINT_IN,
933*86b64dcbSAndroid Build Coastguard Worker g_malloc(out_msg.buffer_length),
934*86b64dcbSAndroid Build Coastguard Worker out_msg.buffer_length,
935*86b64dcbSAndroid Build Coastguard Worker test_threaded_submit_transfer_cb,
936*86b64dcbSAndroid Build Coastguard Worker &data,
937*86b64dcbSAndroid Build Coastguard Worker G_MAXUINT);
938*86b64dcbSAndroid Build Coastguard Worker data.transfers[urb]->flags = LIBUSB_TRANSFER_FREE_BUFFER | LIBUSB_TRANSFER_FREE_TRANSFER;
939*86b64dcbSAndroid Build Coastguard Worker urb++;
940*86b64dcbSAndroid Build Coastguard Worker }
941*86b64dcbSAndroid Build Coastguard Worker }
942*86b64dcbSAndroid Build Coastguard Worker
943*86b64dcbSAndroid Build Coastguard Worker thread = g_thread_new("transfer all", (GThreadFunc) transfer_submit_all_retry, &data);
944*86b64dcbSAndroid Build Coastguard Worker
945*86b64dcbSAndroid Build Coastguard Worker while (!data.done)
946*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_handle_events_completed(fixture->ctx, &data.done), ==, 0);
947*86b64dcbSAndroid Build Coastguard Worker
948*86b64dcbSAndroid Build Coastguard Worker g_thread_join(thread);
949*86b64dcbSAndroid Build Coastguard Worker
950*86b64dcbSAndroid Build Coastguard Worker fixture->libusb_log_silence = FALSE;
951*86b64dcbSAndroid Build Coastguard Worker libusb_close(handle);
952*86b64dcbSAndroid Build Coastguard Worker
953*86b64dcbSAndroid Build Coastguard Worker for (int i = 0; i < 2 * THREADED_SUBMIT_URB_SETS * THREADED_SUBMIT_URB_SETS; i++)
954*86b64dcbSAndroid Build Coastguard Worker g_clear_pointer ((void**) &c->buffer, g_free);
955*86b64dcbSAndroid Build Coastguard Worker g_free (c);
956*86b64dcbSAndroid Build Coastguard Worker }
957*86b64dcbSAndroid Build Coastguard Worker
958*86b64dcbSAndroid Build Coastguard Worker static int LIBUSB_CALL
hotplug_count_arrival_cb(libusb_context * ctx,libusb_device * device,libusb_hotplug_event event,void * user_data)959*86b64dcbSAndroid Build Coastguard Worker hotplug_count_arrival_cb(libusb_context *ctx,
960*86b64dcbSAndroid Build Coastguard Worker libusb_device *device,
961*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_event event,
962*86b64dcbSAndroid Build Coastguard Worker void *user_data)
963*86b64dcbSAndroid Build Coastguard Worker {
964*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event, ==, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
965*86b64dcbSAndroid Build Coastguard Worker
966*86b64dcbSAndroid Build Coastguard Worker (void) ctx;
967*86b64dcbSAndroid Build Coastguard Worker (void) device;
968*86b64dcbSAndroid Build Coastguard Worker
969*86b64dcbSAndroid Build Coastguard Worker *(int*) user_data += 1;
970*86b64dcbSAndroid Build Coastguard Worker
971*86b64dcbSAndroid Build Coastguard Worker return 0;
972*86b64dcbSAndroid Build Coastguard Worker }
973*86b64dcbSAndroid Build Coastguard Worker
974*86b64dcbSAndroid Build Coastguard Worker #ifdef UMOCKDEV_HOTPLUG
975*86b64dcbSAndroid Build Coastguard Worker static int LIBUSB_CALL
hotplug_count_removal_cb(libusb_context * ctx,libusb_device * device,libusb_hotplug_event event,void * user_data)976*86b64dcbSAndroid Build Coastguard Worker hotplug_count_removal_cb(libusb_context *ctx,
977*86b64dcbSAndroid Build Coastguard Worker libusb_device *device,
978*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_event event,
979*86b64dcbSAndroid Build Coastguard Worker void *user_data)
980*86b64dcbSAndroid Build Coastguard Worker {
981*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event, ==, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);
982*86b64dcbSAndroid Build Coastguard Worker
983*86b64dcbSAndroid Build Coastguard Worker (void) ctx;
984*86b64dcbSAndroid Build Coastguard Worker (void) device;
985*86b64dcbSAndroid Build Coastguard Worker
986*86b64dcbSAndroid Build Coastguard Worker *(int*) user_data += 1;
987*86b64dcbSAndroid Build Coastguard Worker
988*86b64dcbSAndroid Build Coastguard Worker return 0;
989*86b64dcbSAndroid Build Coastguard Worker }
990*86b64dcbSAndroid Build Coastguard Worker #endif
991*86b64dcbSAndroid Build Coastguard Worker
992*86b64dcbSAndroid Build Coastguard Worker static void
test_hotplug_enumerate(UMockdevTestbedFixture * fixture,UNUSED_DATA)993*86b64dcbSAndroid Build Coastguard Worker test_hotplug_enumerate(UMockdevTestbedFixture * fixture, UNUSED_DATA)
994*86b64dcbSAndroid Build Coastguard Worker {
995*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_callback_handle handle_enumerate;
996*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_callback_handle handle_no_enumerate;
997*86b64dcbSAndroid Build Coastguard Worker int event_count_enumerate = 0;
998*86b64dcbSAndroid Build Coastguard Worker int event_count_no_enumerate = 0;
999*86b64dcbSAndroid Build Coastguard Worker struct timeval zero_tv = { 0 };
1000*86b64dcbSAndroid Build Coastguard Worker int r;
1001*86b64dcbSAndroid Build Coastguard Worker
1002*86b64dcbSAndroid Build Coastguard Worker r = libusb_hotplug_register_callback(fixture->ctx,
1003*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
1004*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_ENUMERATE,
1005*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1006*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1007*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1008*86b64dcbSAndroid Build Coastguard Worker hotplug_count_arrival_cb,
1009*86b64dcbSAndroid Build Coastguard Worker &event_count_enumerate,
1010*86b64dcbSAndroid Build Coastguard Worker &handle_enumerate);
1011*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(r, ==, 0);
1012*86b64dcbSAndroid Build Coastguard Worker
1013*86b64dcbSAndroid Build Coastguard Worker r = libusb_hotplug_register_callback(fixture->ctx,
1014*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
1015*86b64dcbSAndroid Build Coastguard Worker 0,
1016*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1017*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1018*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1019*86b64dcbSAndroid Build Coastguard Worker hotplug_count_arrival_cb,
1020*86b64dcbSAndroid Build Coastguard Worker &event_count_no_enumerate,
1021*86b64dcbSAndroid Build Coastguard Worker &handle_no_enumerate);
1022*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(r, ==, 0);
1023*86b64dcbSAndroid Build Coastguard Worker
1024*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_enumerate, ==, 1);
1025*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_no_enumerate, ==, 0);
1026*86b64dcbSAndroid Build Coastguard Worker
1027*86b64dcbSAndroid Build Coastguard Worker libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1028*86b64dcbSAndroid Build Coastguard Worker
1029*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_enumerate, ==, 1);
1030*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_no_enumerate, ==, 0);
1031*86b64dcbSAndroid Build Coastguard Worker
1032*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_deregister_callback(fixture->ctx, handle_enumerate);
1033*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_deregister_callback(fixture->ctx, handle_no_enumerate);
1034*86b64dcbSAndroid Build Coastguard Worker
1035*86b64dcbSAndroid Build Coastguard Worker libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1036*86b64dcbSAndroid Build Coastguard Worker
1037*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_enumerate, ==, 1);
1038*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_no_enumerate, ==, 0);
1039*86b64dcbSAndroid Build Coastguard Worker }
1040*86b64dcbSAndroid Build Coastguard Worker
1041*86b64dcbSAndroid Build Coastguard Worker static void
test_hotplug_add_remove(UMockdevTestbedFixture * fixture,UNUSED_DATA)1042*86b64dcbSAndroid Build Coastguard Worker test_hotplug_add_remove(UMockdevTestbedFixture * fixture, UNUSED_DATA)
1043*86b64dcbSAndroid Build Coastguard Worker {
1044*86b64dcbSAndroid Build Coastguard Worker #ifdef UMOCKDEV_HOTPLUG
1045*86b64dcbSAndroid Build Coastguard Worker libusb_device **devs = NULL;
1046*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_callback_handle handle_add;
1047*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_callback_handle handle_remove;
1048*86b64dcbSAndroid Build Coastguard Worker int event_count_add = 0;
1049*86b64dcbSAndroid Build Coastguard Worker int event_count_remove = 0;
1050*86b64dcbSAndroid Build Coastguard Worker struct timeval zero_tv = { 0 };
1051*86b64dcbSAndroid Build Coastguard Worker int r;
1052*86b64dcbSAndroid Build Coastguard Worker
1053*86b64dcbSAndroid Build Coastguard Worker r = libusb_hotplug_register_callback(fixture->ctx,
1054*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
1055*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_ENUMERATE,
1056*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1057*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1058*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1059*86b64dcbSAndroid Build Coastguard Worker hotplug_count_arrival_cb,
1060*86b64dcbSAndroid Build Coastguard Worker &event_count_add,
1061*86b64dcbSAndroid Build Coastguard Worker &handle_add);
1062*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(r, ==, 0);
1063*86b64dcbSAndroid Build Coastguard Worker
1064*86b64dcbSAndroid Build Coastguard Worker r = libusb_hotplug_register_callback(fixture->ctx,
1065*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
1066*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_ENUMERATE,
1067*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1068*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1069*86b64dcbSAndroid Build Coastguard Worker LIBUSB_HOTPLUG_MATCH_ANY,
1070*86b64dcbSAndroid Build Coastguard Worker hotplug_count_removal_cb,
1071*86b64dcbSAndroid Build Coastguard Worker &event_count_remove,
1072*86b64dcbSAndroid Build Coastguard Worker &handle_remove);
1073*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(r, ==, 0);
1074*86b64dcbSAndroid Build Coastguard Worker
1075*86b64dcbSAndroid Build Coastguard Worker /* No device, even going into the mainloop will not call cb. */
1076*86b64dcbSAndroid Build Coastguard Worker libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1077*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_add, ==, 0);
1078*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_remove, ==, 0);
1079*86b64dcbSAndroid Build Coastguard Worker
1080*86b64dcbSAndroid Build Coastguard Worker /* Add a device */
1081*86b64dcbSAndroid Build Coastguard Worker test_fixture_add_canon(fixture);
1082*86b64dcbSAndroid Build Coastguard Worker
1083*86b64dcbSAndroid Build Coastguard Worker /* Either the thread has picked it up already, or we do so now. */
1084*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 1);
1085*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
1086*86b64dcbSAndroid Build Coastguard Worker
1087*86b64dcbSAndroid Build Coastguard Worker /* The hotplug event is pending now, but has not yet fired. */
1088*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_add, ==, 0);
1089*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_remove, ==, 0);
1090*86b64dcbSAndroid Build Coastguard Worker
1091*86b64dcbSAndroid Build Coastguard Worker /* Fire hotplug event. */
1092*86b64dcbSAndroid Build Coastguard Worker libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1093*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_add, ==, 1);
1094*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_remove, ==, 0);
1095*86b64dcbSAndroid Build Coastguard Worker
1096*86b64dcbSAndroid Build Coastguard Worker umockdev_testbed_uevent(fixture->testbed, "/sys/devices/usb1", "remove");
1097*86b64dcbSAndroid Build Coastguard Worker //umockdev_testbed_remove_device(fixture->testbed, "/devices/usb1");
1098*86b64dcbSAndroid Build Coastguard Worker
1099*86b64dcbSAndroid Build Coastguard Worker /* Either the thread has picked it up already, or we do so now. */
1100*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(libusb_get_device_list(fixture->ctx, &devs), ==, 0);
1101*86b64dcbSAndroid Build Coastguard Worker libusb_free_device_list(devs, TRUE);
1102*86b64dcbSAndroid Build Coastguard Worker
1103*86b64dcbSAndroid Build Coastguard Worker /* The hotplug event is pending now, but has not yet fired. */
1104*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_add, ==, 1);
1105*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_remove, ==, 0);
1106*86b64dcbSAndroid Build Coastguard Worker
1107*86b64dcbSAndroid Build Coastguard Worker /* Fire hotplug event. */
1108*86b64dcbSAndroid Build Coastguard Worker libusb_handle_events_timeout(fixture->ctx, &zero_tv);
1109*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_add, ==, 1);
1110*86b64dcbSAndroid Build Coastguard Worker g_assert_cmpint(event_count_remove, ==, 1);
1111*86b64dcbSAndroid Build Coastguard Worker
1112*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_deregister_callback(fixture->ctx, handle_add);
1113*86b64dcbSAndroid Build Coastguard Worker libusb_hotplug_deregister_callback(fixture->ctx, handle_remove);
1114*86b64dcbSAndroid Build Coastguard Worker #else
1115*86b64dcbSAndroid Build Coastguard Worker (void) fixture;
1116*86b64dcbSAndroid Build Coastguard Worker g_test_skip("UMockdev is too old to test hotplug");
1117*86b64dcbSAndroid Build Coastguard Worker #endif
1118*86b64dcbSAndroid Build Coastguard Worker }
1119*86b64dcbSAndroid Build Coastguard Worker
1120*86b64dcbSAndroid Build Coastguard Worker int
main(int argc,char ** argv)1121*86b64dcbSAndroid Build Coastguard Worker main(int argc, char **argv)
1122*86b64dcbSAndroid Build Coastguard Worker {
1123*86b64dcbSAndroid Build Coastguard Worker g_test_init(&argc, &argv, NULL);
1124*86b64dcbSAndroid Build Coastguard Worker
1125*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/open-close", UMockdevTestbedFixture, NULL,
1126*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1127*86b64dcbSAndroid Build Coastguard Worker test_open_close,
1128*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1129*86b64dcbSAndroid Build Coastguard Worker
1130*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/implicit-default", UMockdevTestbedFixture, NULL,
1131*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1132*86b64dcbSAndroid Build Coastguard Worker test_implicit_default,
1133*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1134*86b64dcbSAndroid Build Coastguard Worker
1135*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/close-flying", UMockdevTestbedFixture, NULL,
1136*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1137*86b64dcbSAndroid Build Coastguard Worker test_close_flying,
1138*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1139*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/close-cancelled", UMockdevTestbedFixture, NULL,
1140*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1141*86b64dcbSAndroid Build Coastguard Worker test_close_cancelled,
1142*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1143*86b64dcbSAndroid Build Coastguard Worker
1144*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/ctx-destroy", UMockdevTestbedFixture, NULL,
1145*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1146*86b64dcbSAndroid Build Coastguard Worker test_ctx_destroy,
1147*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1148*86b64dcbSAndroid Build Coastguard Worker
1149*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/string-descriptor", UMockdevTestbedFixture, NULL,
1150*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1151*86b64dcbSAndroid Build Coastguard Worker test_get_string_descriptor,
1152*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1153*86b64dcbSAndroid Build Coastguard Worker
1154*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/timeout", UMockdevTestbedFixture, NULL,
1155*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1156*86b64dcbSAndroid Build Coastguard Worker test_timeout,
1157*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1158*86b64dcbSAndroid Build Coastguard Worker
1159*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/threaded-submit", UMockdevTestbedFixture, NULL,
1160*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1161*86b64dcbSAndroid Build Coastguard Worker test_threaded_submit,
1162*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1163*86b64dcbSAndroid Build Coastguard Worker
1164*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/hotplug/enumerate", UMockdevTestbedFixture, NULL,
1165*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_with_canon,
1166*86b64dcbSAndroid Build Coastguard Worker test_hotplug_enumerate,
1167*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1168*86b64dcbSAndroid Build Coastguard Worker
1169*86b64dcbSAndroid Build Coastguard Worker g_test_add("/libusb/hotplug/add-remove", UMockdevTestbedFixture, NULL,
1170*86b64dcbSAndroid Build Coastguard Worker test_fixture_setup_empty,
1171*86b64dcbSAndroid Build Coastguard Worker test_hotplug_add_remove,
1172*86b64dcbSAndroid Build Coastguard Worker test_fixture_teardown);
1173*86b64dcbSAndroid Build Coastguard Worker
1174*86b64dcbSAndroid Build Coastguard Worker return g_test_run();
1175*86b64dcbSAndroid Build Coastguard Worker }
1176