Skip to content

Commit

Permalink
Add operation_kill_switch and ptp_report_error example
Browse files Browse the repository at this point in the history
  • Loading branch information
petabyt committed Oct 20, 2024
1 parent c68aa0c commit 9b960bb
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 7 deletions.
7 changes: 4 additions & 3 deletions src/camlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,12 @@ struct PtpPropAvail {
/// @brief Represents a single device connection
/// @struct PtpRuntime
struct PtpRuntime {
/// @brief Set to 1 to kill all IO operations. By default, this is 1. When a valid connection
/// is achieved by libusb, libwpd, and tcp backends, it will be set to 0. On IO error, it
/// will be set to 1.
/// @brief Set to 1 when it is no longer safe to send any data to the device (socket closed, device unplugged)
uint8_t io_kill_switch;

/// @brief Set to 1 when it is no longer safe to run operations (device is unresponsive, pipe issues)
uint8_t operation_kill_switch;

/// @brief One of enum PtpConnType
/// @note Is set to USB by default
uint8_t connection_type;
Expand Down
40 changes: 40 additions & 0 deletions src/error.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Example implementation of function to safely kill the connection in a multithreaded application.
// Copyright 2024 by Daniel C (https://github.com/petabyt/camlib)

#include <camlib.h>

void ptp_report_error(struct PtpRuntime *r, char *reason, int code) {
if (r->io_kill_switch) return;
// Prevent any further operations if this is intentional
if (code != 0) {
r->operation_kill_switch = 1;
}
// Wait until we have a lock
ptp_mutex_lock(r);
// If io_kill_switch was set while waiting for a lock
if (r->io_kill_switch) {
ptp_mutex_unlock(r);
return;
}

// Safely disconnect if intentional
if (code == 0) {
ptp_verbose_log("Closing session\n");
ptp_close_session(r);
}

r->operation_kill_switch = 1;
r->io_kill_switch = 1;

ptp_mutex_unlock(r);

if (reason == NULL) {
if (code == PTP_IO_ERR) {
ptp_verbose_log("Disconnected: IO Error\n");
} else {
ptp_verbose_log("Disconnected: Runtime error\n");
}
} else {
ptp_verbose_log("Disconnected: %s\n", reason);
}
}
1 change: 1 addition & 0 deletions src/ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ int ptpip_connect(struct PtpRuntime *r, const char *addr, int port, int extra_tm
if (fd > 0) {
b->fd = fd;
r->io_kill_switch = 0;
r->operation_kill_switch = 0;
return 0;
} else {
b->fd = 0;
Expand Down
21 changes: 18 additions & 3 deletions src/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
void ptp_reset(struct PtpRuntime *r) {
if (r == NULL) abort();
r->io_kill_switch = 1;
r->operation_kill_switch = 1;
r->transaction = 0;
r->session = 0;
r->session = 0;
r->connection_type = PTP_USB;
r->response_wait_default = 1;
r->wait_for_response = 1;
Expand Down Expand Up @@ -180,7 +181,12 @@ static int ptp_send_try(struct PtpRuntime *r, struct PtpCommand *cmd) {

// Perform a generic command transaction - no data phase
int ptp_send(struct PtpRuntime *r, struct PtpCommand *cmd) {
if (r->operation_kill_switch) return PTP_IO_ERR;
ptp_mutex_lock(r);
if (r->operation_kill_switch) {
ptp_mutex_unlock(r);
return PTP_IO_ERR;
}

r->data_phase_length = 0;

Expand All @@ -190,11 +196,13 @@ int ptp_send(struct PtpRuntime *r, struct PtpCommand *cmd) {
rc = ptp_send_try(r, cmd);
if (rc) {
ptp_verbose_log("Command ignored again.\n");
r->operation_kill_switch = 1;
ptp_mutex_unlock(r);
return PTP_IO_ERR;
}
} else if (rc) {
ptp_mutex_unlock(r);
r->operation_kill_switch = 1;
return PTP_IO_ERR;
}

Expand Down Expand Up @@ -240,9 +248,14 @@ static int ptp_send_data_try(struct PtpRuntime *r, struct PtpCommand *cmd, void

// Perform a command request with a data phase to the camera
int ptp_send_data(struct PtpRuntime *r, struct PtpCommand *cmd, void *data, int length) {
if (r->operation_kill_switch) return PTP_IO_ERR;
ptp_mutex_lock(r);
if (r->operation_kill_switch) {
ptp_mutex_unlock(r);
return PTP_IO_ERR;
}

// Required for libWPD and PTP/IP
// Required for PTP/IP
r->data_phase_length = length;

// Resize buffer if needed
Expand All @@ -258,11 +271,13 @@ int ptp_send_data(struct PtpRuntime *r, struct PtpCommand *cmd, void *data, int
rc = ptp_send_data_try(r, cmd, data, length);
if (rc) {
ptp_verbose_log("Command ignored again.\n");
r->operation_kill_switch = 1;
ptp_mutex_unlock(r);
return PTP_IO_ERR;
}
} else if (rc) {
ptp_mutex_unlock(r);
r->operation_kill_switch = 1;
return PTP_IO_ERR;
}

Expand All @@ -275,7 +290,7 @@ int ptp_send_data(struct PtpRuntime *r, struct PtpCommand *cmd, void *data, int

int ptp_device_type(struct PtpRuntime *r) {
struct PtpDeviceInfo *di = r->di;
if (di == NULL) return PTP_DEV_EMPTY; // TODO: panic?
if (di == NULL) return PTP_DEV_EMPTY; // panic?
if (!strcmp(di->manufacturer, "Canon Inc.")) {
if (ptp_check_opcode(r, PTP_OC_EOS_GetStorageIDs)) {
return PTP_DEV_EOS;
Expand Down
3 changes: 3 additions & 0 deletions src/libusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ int ptp_device_open(struct PtpRuntime *r, struct PtpDeviceEntry *entry) {
}

r->io_kill_switch = 0;
r->operation_kill_switch = 0;

ptp_mutex_unlock(r);
return 0;
Expand Down Expand Up @@ -279,12 +280,14 @@ int ptp_device_init(struct PtpRuntime *r) {
}

r->io_kill_switch = 0;
r->operation_kill_switch = 0;

return 0;
}

int ptp_device_close(struct PtpRuntime *r) {
r->io_kill_switch = 1;
r->operation_kill_switch = 1;
struct LibUSBBackend *backend = (struct LibUSBBackend *)r->comm_backend;
if (libusb_release_interface(backend->handle, 0)) {
return 1;
Expand Down
1 change: 1 addition & 0 deletions src/libwpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ int ptp_device_init(struct PtpRuntime *r) {
ptp_verbose_log("Found device of type: %d\n", type);
if (type == WPD_DEVICE_TYPE_CAMERA) {
r->io_kill_switch = 0;
r->operation_kill_switch = 0;
ptp_mutex_unlock(r);
return 0;
}
Expand Down
1 change: 0 additions & 1 deletion src/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,6 @@ int ptpipusb_receive_bulk_packets(struct PtpRuntime *r) {
}

int ptp_receive_all_packets(struct PtpRuntime *r) {
if (r->io_kill_switch) return -1;
if (r->connection_type == PTP_IP) {
return ptpip_receive_bulk_packets(r);
} else if (r->connection_type == PTP_USB) {
Expand Down

0 comments on commit 9b960bb

Please sign in to comment.