@@ -92,41 +92,52 @@ static int libhoth_usb_release(struct libhoth_device* dev) {
9292 return libusb_release_interface (usb_dev -> handle , usb_dev -> info .interface_id );
9393}
9494
95+ static int libhoth_usb_close_internal (struct libhoth_usb_device * usb_dev ) {
96+ int status = LIBUSB_SUCCESS ;
97+ if (usb_dev -> handle != NULL ) {
98+ switch (usb_dev -> info .type ) {
99+ case LIBHOTH_USB_INTERFACE_TYPE_MAILBOX :
100+ status = libhoth_usb_mailbox_close (usb_dev );
101+ break ;
102+ case LIBHOTH_USB_INTERFACE_TYPE_FIFO :
103+ status = libhoth_usb_fifo_close (usb_dev );
104+ break ;
105+ default :
106+ status = LIBHOTH_ERR_INTERFACE_NOT_FOUND ;
107+ break ;
108+ }
109+ libusb_release_interface (usb_dev -> handle , usb_dev -> info .interface_id );
110+ libusb_close (usb_dev -> handle );
111+ usb_dev -> handle = NULL ;
112+ }
113+ return status ;
114+ }
115+
95116static int libhoth_usb_reconnect (struct libhoth_device * dev ) {
96117 struct libhoth_usb_device * usb_dev = dev -> user_ctx ;
118+ if (usb_dev == NULL ) {
119+ return LIBUSB_ERROR_INVALID_PARAM ;
120+ }
97121 libusb_context * usb_ctx = usb_dev -> ctx ;
98122 uint64_t timeout_us = usb_dev -> claim_timeout_us ;
99123
100- struct libusb_device * libusb_dev = libusb_get_device (usb_dev -> handle );
101-
102- struct libhoth_usb_loc usb_loc ;
103- usb_loc .bus = libusb_get_bus_number (libusb_dev );
104- usb_loc .num_ports = libusb_get_port_numbers (
105- libusb_dev , (uint8_t * )& usb_loc .ports , LIBHOTH_NUM_PORTS );
106- if (usb_loc .num_ports == LIBUSB_ERROR_OVERFLOW ) {
107- fprintf (stderr , "Failed to list port numbers when reconnecting. (%s)\n" ,
108- libusb_strerror (LIBUSB_ERROR_OVERFLOW ));
109- return LIBUSB_ERROR_OVERFLOW ;
110- }
111-
112- libhoth_usb_close (dev );
113-
114124 uint64_t start_time_ms = libhoth_get_monotonic_ms ();
115-
116125 while (1 ) {
117- libusb_exit (usb_ctx );
118- int ret = libusb_init (& usb_ctx );
119- if (ret != 0 ) {
120- fprintf (
121- stderr ,
122- "libusb_init_context failed while reconnecting (error: %d (%s))\n" ,
123- ret , libusb_strerror (ret ));
124- }
125-
126- ret = libhoth_usb_get_device (usb_ctx , & usb_loc , & libusb_dev );
126+ libusb_device * new_libusb_dev = NULL ;
127+ int ret = libhoth_usb_get_device (usb_ctx , & usb_dev -> loc , & new_libusb_dev );
127128 if (ret == 0 ) {
128- // Found the device
129- break ;
129+ struct libhoth_usb_device_init_options opts ;
130+ opts .usb_ctx = usb_ctx ;
131+ opts .usb_device = new_libusb_dev ;
132+ opts .timeout_us = timeout_us ;
133+ opts .prng_seed = libhoth_prng_seed ();
134+
135+ // Close the old handle and driver data, but keep the usb_dev structure.
136+ libhoth_usb_close_internal (usb_dev );
137+
138+ ret = libhoth_usb_device_open (& opts , dev );
139+ libusb_unref_device (new_libusb_dev );
140+ return ret ;
130141 }
131142
132143 uint64_t current_time_ms = libhoth_get_monotonic_ms ();
@@ -136,27 +147,18 @@ static int libhoth_usb_reconnect(struct libhoth_device* dev) {
136147 stderr ,
137148 "libhoth_usb_open timed out while reconnecting (error: %d (%s))\n" ,
138149 ret , libusb_strerror (ret ));
139- libusb_exit (usb_ctx );
140150 return ret ; // Timeout
141151 }
142152
143153 // 100ms delay
144154 usleep (100 * 1000 );
145155 }
146-
147- struct libhoth_usb_device_init_options opts ;
148- opts .usb_ctx = usb_ctx ;
149- opts .usb_device = libusb_dev ;
150- opts .timeout_us = timeout_us ;
151- opts .prng_seed = libhoth_prng_seed ();
152-
153- return libhoth_usb_device_open (& opts , dev );
154156}
155157
156158static int libhoth_usb_device_open (
157159 const struct libhoth_usb_device_init_options * options ,
158160 struct libhoth_device * dev ) {
159- struct libhoth_usb_device * usb_dev = NULL ;
161+ struct libhoth_usb_device * usb_dev = dev -> user_ctx ;
160162 struct libusb_device_descriptor device_descriptor ;
161163 int status =
162164 libusb_get_device_descriptor (options -> usb_device , & device_descriptor );
@@ -185,14 +187,23 @@ static int libhoth_usb_device_open(
185187 goto err_out ;
186188 }
187189
188- usb_dev = calloc (1 , sizeof (struct libhoth_usb_device ));
189190 if (usb_dev == NULL ) {
190- status = LIBHOTH_ERR_MALLOC_FAILED ;
191- goto err_out ;
191+ usb_dev = calloc (1 , sizeof (struct libhoth_usb_device ));
192+ if (usb_dev == NULL ) {
193+ status = LIBHOTH_ERR_MALLOC_FAILED ;
194+ goto err_out ;
195+ }
196+ dev -> user_ctx = usb_dev ;
192197 }
193198 usb_dev -> info = info ;
194199 usb_dev -> ctx = options -> usb_ctx ;
195200 usb_dev -> claim_timeout_us = options -> timeout_us ;
201+
202+ if (libhoth_get_usb_loc (options -> usb_device , & usb_dev -> loc ) != 0 ) {
203+ status = LIBUSB_ERROR_OTHER ;
204+ goto err_out ;
205+ }
206+
196207 status = libusb_open (options -> usb_device , & usb_dev -> handle );
197208 if (status != LIBUSB_SUCCESS ) {
198209 goto err_out ;
@@ -204,7 +215,6 @@ static int libhoth_usb_device_open(
204215 dev -> claim = libhoth_usb_claim ;
205216 dev -> release = libhoth_usb_release ;
206217 dev -> reconnect = libhoth_usb_reconnect ;
207- dev -> user_ctx = usb_dev ;
208218
209219 status = libhoth_claim_device (dev , options -> timeout_us );
210220 if (status != LIBHOTH_OK ) {
@@ -231,14 +241,10 @@ static int libhoth_usb_device_open(
231241 return LIBHOTH_OK ;
232242
233243err_out :
234- if (dev != NULL ) {
235- if (usb_dev != NULL ) {
236- if (usb_dev -> handle != NULL ) {
237- libusb_release_interface (usb_dev -> handle , usb_dev -> info .interface_id );
238- libusb_close (usb_dev -> handle );
239- }
240- free (usb_dev );
241- }
244+ if (usb_dev != NULL && usb_dev -> handle != NULL ) {
245+ libusb_release_interface (usb_dev -> handle , usb_dev -> info .interface_id );
246+ libusb_close (usb_dev -> handle );
247+ usb_dev -> handle = NULL ;
242248 }
243249 libusb_free_config_descriptor (config_descriptor );
244250 return status ;
@@ -257,6 +263,9 @@ int libhoth_usb_open(const struct libhoth_usb_device_init_options* options,
257263
258264 int ret = libhoth_usb_device_open (options , dev );
259265 if (ret != LIBUSB_SUCCESS ) {
266+ if (dev -> user_ctx != NULL ) {
267+ free (dev -> user_ctx );
268+ }
260269 free (dev );
261270 return ret ;
262271 }
@@ -273,6 +282,9 @@ int libhoth_usb_send_request(struct libhoth_device* dev, const void* request,
273282
274283 struct libhoth_usb_device * usb_dev =
275284 (struct libhoth_usb_device * )dev -> user_ctx ;
285+ if (usb_dev -> handle == NULL ) {
286+ return LIBUSB_ERROR_NO_DEVICE ;
287+ }
276288 switch (usb_dev -> info .type ) {
277289 case LIBHOTH_USB_INTERFACE_TYPE_MAILBOX :
278290 return libhoth_usb_mailbox_send_request (usb_dev , request , request_size );
@@ -293,6 +305,9 @@ int libhoth_usb_receive_response(struct libhoth_device* dev, void* response,
293305
294306 struct libhoth_usb_device * usb_dev =
295307 (struct libhoth_usb_device * )dev -> user_ctx ;
308+ if (usb_dev -> handle == NULL ) {
309+ return LIBUSB_ERROR_NO_DEVICE ;
310+ }
296311 switch (usb_dev -> info .type ) {
297312 case LIBHOTH_USB_INTERFACE_TYPE_MAILBOX :
298313 return libhoth_usb_mailbox_receive_response (
@@ -307,33 +322,17 @@ int libhoth_usb_receive_response(struct libhoth_device* dev, void* response,
307322}
308323
309324int libhoth_usb_close (struct libhoth_device * dev ) {
310- int status ;
311325 if (dev -> user_ctx == NULL ) {
312- return LIBUSB_ERROR_INVALID_PARAM ;
326+ return LIBUSB_SUCCESS ;
313327 }
314328
315329 struct libhoth_usb_device * usb_dev =
316330 (struct libhoth_usb_device * )dev -> user_ctx ;
317331 dev -> user_ctx = NULL ;
318- switch (usb_dev -> info .type ) {
319- case LIBHOTH_USB_INTERFACE_TYPE_MAILBOX :
320- status = libhoth_usb_mailbox_close (usb_dev );
321- break ;
322- case LIBHOTH_USB_INTERFACE_TYPE_FIFO :
323- status = libhoth_usb_fifo_close (usb_dev );
324- break ;
325- default :
326- return LIBHOTH_ERR_INTERFACE_NOT_FOUND ;
327- }
328- if (status != LIBHOTH_OK ) {
329- return status ;
330- }
331- if (usb_dev -> handle != NULL ) {
332- libusb_release_interface (usb_dev -> handle , usb_dev -> info .interface_id );
333- libusb_close (usb_dev -> handle );
334- }
332+
333+ int status = libhoth_usb_close_internal (usb_dev );
335334 free (usb_dev );
336- return LIBHOTH_OK ;
335+ return status ;
337336}
338337
339338enum libusb_error transfer_status_to_error (
0 commit comments