Skip to content

Commit

Permalink
Ensure device open API is thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
petabyt committed Jan 27, 2024
1 parent 24af49d commit 87734d9
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
28 changes: 25 additions & 3 deletions src/libusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,15 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) {
return NULL;
}

if (!r->io_kill_switch) {
ptp_verbose_log("Connection is active\n");
return NULL;
}

ptp_mutex_lock(r);

struct LibUSBBackend *backend = (struct LibUSBBackend *)r->comm_backend;

// #warning "TODO: bad access @ libusb_get_device_list + 267 -> pthread_mutex_lock + 4"
// Caused by double calling ptpusb_device_list = race condition. GUI problem?
libusb_device **list;
ssize_t count = libusb_get_device_list(backend->ctx, &list);

Expand All @@ -65,6 +70,7 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) {
struct PtpDeviceEntry *orig_ent = curr_ent;

if (count == 0) {
ptp_mutex_unlock(r);
return NULL;
}

Expand All @@ -74,6 +80,7 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) {
int rc = libusb_get_device_descriptor(dev, &desc);
if (rc) {
perror("libusb_get_device_descriptor");
ptp_mutex_unlock(r);
return NULL;
}

Expand All @@ -84,6 +91,7 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) {
rc = libusb_get_config_descriptor(dev, 0, &config);
if (rc) {
perror("libusb_get_config_descriptor");
ptp_mutex_unlock(r);
return NULL;
}

Expand Down Expand Up @@ -151,6 +159,7 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) {
rc = libusb_open(dev, &handle);
if (rc) {
perror("usb_open() failure");
ptp_mutex_unlock(r);
return NULL;
}

Expand Down Expand Up @@ -178,6 +187,8 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) {

//libusb_free_device_list(list, 0);

ptp_mutex_unlock(r);

if (valid_devices == 0) {
return NULL;
}
Expand All @@ -186,9 +197,16 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) {
}

int ptp_device_open(struct PtpRuntime *r, struct PtpDeviceEntry *entry) {
ptp_mutex_lock(r);
if (r->comm_backend == NULL) {
ptp_verbose_log("comm_backend is NULL\n");
return PTP_IO_ERR;
ptp_mutex_unlock(r);
return PTP_OPEN_FAIL;
}

if (!r->io_kill_switch) {
ptp_verbose_log("Connection is active\n");
return PTP_OPEN_FAIL;
}

struct LibUSBBackend *backend = (struct LibUSBBackend *)r->comm_backend;
Expand All @@ -200,22 +218,26 @@ int ptp_device_open(struct PtpRuntime *r, struct PtpDeviceEntry *entry) {
int rc = libusb_open(entry->device_handle_ptr, &(backend->handle));
if (rc) {
perror("usb_open() failure");
ptp_mutex_unlock(r);
return PTP_OPEN_FAIL;
}

if (libusb_set_auto_detach_kernel_driver(backend->handle, 0)) {
perror("libusb_set_auto_detach_kernel_driver");
ptp_mutex_unlock(r);
return PTP_OPEN_FAIL;
}

if (libusb_claim_interface(backend->handle, 0)) {
perror("usb_claim_interface() failure");
libusb_close(backend->handle);
ptp_mutex_unlock(r);
return PTP_OPEN_FAIL;
}

r->io_kill_switch = 0;

ptp_mutex_unlock(r);
return 0;
}

Expand Down
15 changes: 14 additions & 1 deletion src/libwpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,47 @@ int ptp_comm_init(struct PtpRuntime *r) {
}

int ptp_device_init(struct PtpRuntime *r) {
if (!r->io_kill_switch) {
ptp_verbose_log("Connection is active\n");
return NULL;
}

ptp_comm_init(r);

struct WpdStruct *wpd = (struct WpdStruct *)(r->comm_backend);
if (wpd == NULL) return PTP_IO_ERR;

ptp_mutex_lock(r);

int length = 0;
wchar_t **devices = wpd_get_devices(wpd, &length);

if (length == 0) return PTP_NO_DEVICE;
if (length == 0) {
ptp_mutex_unlock(r);
return PTP_NO_DEVICE;
}

for (int i = 0; i < length; i++) {
wprintf(L"Trying device: %s\n", devices[i]);

int ret = wpd_open_device(wpd, devices[i]);
if (ret) {
ptp_mutex_unlock(r);
return PTP_OPEN_FAIL;
}

int type = wpd_get_device_type(wpd);
ptp_verbose_log("Found device of type: %d\n", type);
if (type == WPD_DEVICE_TYPE_CAMERA) {
r->io_kill_switch = 0;
ptp_mutex_unlock(r);
return 0;
}

wpd_close_device(wpd);
}

ptp_mutex_unlock(r);
return PTP_NO_DEVICE;
}

Expand Down

0 comments on commit 87734d9

Please sign in to comment.