@@ -92,41 +92,53 @@ 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 ;
99-
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 );
123+ struct libhoth_usb_loc usb_loc = usb_dev -> loc ;
113124
114125 uint64_t start_time_ms = libhoth_get_monotonic_ms ();
115-
116126 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 );
127+ libusb_device * new_libusb_dev = NULL ;
128+ int ret = libhoth_usb_get_device (usb_ctx , & usb_loc , & new_libusb_dev );
127129 if (ret == 0 ) {
128- // Found the device
129- break ;
130+ struct libhoth_usb_device_init_options opts ;
131+ opts .usb_ctx = usb_ctx ;
132+ opts .usb_device = new_libusb_dev ;
133+ opts .timeout_us = timeout_us ;
134+ opts .prng_seed = libhoth_prng_seed ();
135+
136+ // Close the old handle and driver data, but keep the usb_dev structure.
137+ libhoth_usb_close_internal (usb_dev );
138+
139+ ret = libhoth_usb_device_open (& opts , dev );
140+ libusb_unref_device (new_libusb_dev );
141+ return ret ;
130142 }
131143
132144 uint64_t current_time_ms = libhoth_get_monotonic_ms ();
@@ -136,27 +148,18 @@ static int libhoth_usb_reconnect(struct libhoth_device* dev) {
136148 stderr ,
137149 "libhoth_usb_open timed out while reconnecting (error: %d (%s))\n" ,
138150 ret , libusb_strerror (ret ));
139- libusb_exit (usb_ctx );
140151 return ret ; // Timeout
141152 }
142153
143154 // 100ms delay
144155 usleep (100 * 1000 );
145156 }
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 );
154157}
155158
156159static int libhoth_usb_device_open (
157160 const struct libhoth_usb_device_init_options * options ,
158161 struct libhoth_device * dev ) {
159- struct libhoth_usb_device * usb_dev = NULL ;
162+ struct libhoth_usb_device * usb_dev = dev -> user_ctx ;
160163 struct libusb_device_descriptor device_descriptor ;
161164 int status =
162165 libusb_get_device_descriptor (options -> usb_device , & device_descriptor );
@@ -185,14 +188,23 @@ static int libhoth_usb_device_open(
185188 goto err_out ;
186189 }
187190
188- usb_dev = calloc (1 , sizeof (struct libhoth_usb_device ));
189191 if (usb_dev == NULL ) {
190- status = LIBHOTH_ERR_MALLOC_FAILED ;
191- goto err_out ;
192+ usb_dev = calloc (1 , sizeof (struct libhoth_usb_device ));
193+ if (usb_dev == NULL ) {
194+ status = LIBHOTH_ERR_MALLOC_FAILED ;
195+ goto err_out ;
196+ }
197+ dev -> user_ctx = usb_dev ;
192198 }
193199 usb_dev -> info = info ;
194200 usb_dev -> ctx = options -> usb_ctx ;
195201 usb_dev -> claim_timeout_us = options -> timeout_us ;
202+
203+ if (libhoth_get_usb_loc (options -> usb_device , & usb_dev -> loc ) != 0 ) {
204+ status = LIBUSB_ERROR_OTHER ;
205+ goto err_out ;
206+ }
207+
196208 status = libusb_open (options -> usb_device , & usb_dev -> handle );
197209 if (status != LIBUSB_SUCCESS ) {
198210 goto err_out ;
@@ -204,7 +216,6 @@ static int libhoth_usb_device_open(
204216 dev -> claim = libhoth_usb_claim ;
205217 dev -> release = libhoth_usb_release ;
206218 dev -> reconnect = libhoth_usb_reconnect ;
207- dev -> user_ctx = usb_dev ;
208219
209220 status = libhoth_claim_device (dev , options -> timeout_us );
210221 if (status != LIBHOTH_OK ) {
@@ -231,14 +242,10 @@ static int libhoth_usb_device_open(
231242 return LIBHOTH_OK ;
232243
233244err_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- }
245+ if (usb_dev != NULL && usb_dev -> handle != NULL ) {
246+ libusb_release_interface (usb_dev -> handle , usb_dev -> info .interface_id );
247+ libusb_close (usb_dev -> handle );
248+ usb_dev -> handle = NULL ;
242249 }
243250 libusb_free_config_descriptor (config_descriptor );
244251 return status ;
@@ -257,6 +264,9 @@ int libhoth_usb_open(const struct libhoth_usb_device_init_options* options,
257264
258265 int ret = libhoth_usb_device_open (options , dev );
259266 if (ret != LIBUSB_SUCCESS ) {
267+ if (dev -> user_ctx != NULL ) {
268+ free (dev -> user_ctx );
269+ }
260270 free (dev );
261271 return ret ;
262272 }
@@ -273,6 +283,9 @@ int libhoth_usb_send_request(struct libhoth_device* dev, const void* request,
273283
274284 struct libhoth_usb_device * usb_dev =
275285 (struct libhoth_usb_device * )dev -> user_ctx ;
286+ if (usb_dev -> handle == NULL ) {
287+ return LIBUSB_ERROR_NO_DEVICE ;
288+ }
276289 switch (usb_dev -> info .type ) {
277290 case LIBHOTH_USB_INTERFACE_TYPE_MAILBOX :
278291 return libhoth_usb_mailbox_send_request (usb_dev , request , request_size );
@@ -293,6 +306,9 @@ int libhoth_usb_receive_response(struct libhoth_device* dev, void* response,
293306
294307 struct libhoth_usb_device * usb_dev =
295308 (struct libhoth_usb_device * )dev -> user_ctx ;
309+ if (usb_dev -> handle == NULL ) {
310+ return LIBUSB_ERROR_NO_DEVICE ;
311+ }
296312 switch (usb_dev -> info .type ) {
297313 case LIBHOTH_USB_INTERFACE_TYPE_MAILBOX :
298314 return libhoth_usb_mailbox_receive_response (
@@ -307,33 +323,17 @@ int libhoth_usb_receive_response(struct libhoth_device* dev, void* response,
307323}
308324
309325int libhoth_usb_close (struct libhoth_device * dev ) {
310- int status ;
311326 if (dev -> user_ctx == NULL ) {
312- return LIBUSB_ERROR_INVALID_PARAM ;
327+ return LIBUSB_SUCCESS ;
313328 }
314329
315330 struct libhoth_usb_device * usb_dev =
316331 (struct libhoth_usb_device * )dev -> user_ctx ;
317332 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- }
333+
334+ int status = libhoth_usb_close_internal (usb_dev );
335335 free (usb_dev );
336- return LIBHOTH_OK ;
336+ return status ;
337337}
338338
339339enum libusb_error transfer_status_to_error (
0 commit comments