From 688670948f2ab927ab55d95324743f91f3ea358f Mon Sep 17 00:00:00 2001 From: Daniel C Date: Wed, 20 Dec 2023 21:47:46 -0500 Subject: [PATCH] ptp_set_generic_property now only accepts validated current values if provided in runtime property table For EOS only --- src/data.c | 22 +++++++++++++------- src/generic.c | 53 ++++++++++++++++++++++++++++++++++++++++++++----- src/lib.c | 5 +++-- src/transport.c | 11 +++++----- 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/data.c b/src/data.c index 00ad138..b50b05b 100644 --- a/src/data.c +++ b/src/data.c @@ -390,9 +390,7 @@ struct PtpEventReader { void *ptr; }; -// TODO: misnomer: ptp_eos_unpack_events -// TODO: we should have a way to read next entry without allocating/freeing memory -int ptp_eos_events(struct PtpRuntime *r, struct PtpGenericEvent **p) { +int ptp_eos_events_length(struct PtpRuntime *r) { uint8_t *dp = ptp_get_payload(r); int length = 0; @@ -410,11 +408,20 @@ int ptp_eos_events(struct PtpRuntime *r, struct PtpGenericEvent **p) { length++; } + return length; +} + +// TODO: misnomer: ptp_eos_unpack_events +// TODO: we should have a way to read next entry without allocating/freeing memory +int ptp_eos_events(struct PtpRuntime *r, struct PtpGenericEvent **p) { + int length = ptp_eos_events_length(r); + if (length == 0) return 0; + if (length < 0) return length; (*p) = malloc(sizeof(struct PtpGenericEvent) * length); - dp = ptp_get_payload(r); + uint8_t *dp = ptp_get_payload(r); for (int i = 0; i < length; i++) { // TODO: Simplify these triple pointers struct PtpGenericEvent *cur = &((*p)[i]); @@ -454,12 +461,13 @@ int ptp_eos_events(struct PtpRuntime *r, struct PtpGenericEvent **p) { uint32_t count = ptp_read_uint32(&d); int payload_size = (size - 20); - int memb_size = 0; + + // Make sure to not divide by zero :) if (payload_size != 0 && count != 0) { - memb_size = (size - 20) / count; + int memb_size = payload_size / count; + ptp_set_prop_avail_info(r, code, memb_size, count, d); } - //printf("Avail List changed: %X of type %X\n", code, dat_type); } break; } diff --git a/src/generic.c b/src/generic.c index 00396cb..320e940 100644 --- a/src/generic.c +++ b/src/generic.c @@ -5,20 +5,64 @@ #include +int ptp_validate_property_value(struct PtpRuntime *r, int prop_code, uint32_t value) { + struct PtpPropAvail *n; + for (n = r->avail; n != NULL; n = n->prev) { + if (n->code == prop_code) break; + } + + if (n == NULL) return 1; + + for (int i = 0; i < n->memb_cnt; i++) { + uint32_t cur_val; + switch (n->memb_size) { + case 4: + cur_val = ((uint32_t *)n->data)[i]; + break; + case 2: + cur_val = ((uint16_t *)n->data)[i]; + break; + case 1: + cur_val = ((uint8_t *)n->data)[i]; + break; + default: + ptp_panic("Unsupported PTP prop length %X\n", prop_code); + } + + if (value == cur_val) { + ptp_verbose_log("Found valid prop value %X for 0x%X\n", value, prop_code); + return 0; + } + } + + return 2; +} + +static int ptp_eos_set_validate_prop(struct PtpRuntime *r, int prop_code, uint32_t value) { + int rc = ptp_validate_property_value(r, prop_code, value); + + // If invalid value, don't set. Else... we don't have any info, and we assume it's valid + if (rc == 2) { + return rc; + } + + return ptp_eos_set_prop_value(r, prop_code, value); +} + int ptp_set_generic_property(struct PtpRuntime *r, char *name, int value) { int dev = ptp_device_type(r); int rc = 0; if (!strcmp(name, "aperture")) { if (dev == PTP_DEV_EOS) { - rc = ptp_eos_set_prop_value(r, PTP_PC_EOS_Aperture, ptp_eos_get_aperture(value, 1)); + rc = ptp_eos_set_validate_prop(r, PTP_PC_EOS_Aperture, ptp_eos_get_aperture(value, 1)); } } else if (!strcmp(name, "iso")) { if (dev == PTP_DEV_EOS) { - rc = ptp_eos_set_prop_value(r, PTP_PC_EOS_ISOSpeed, ptp_eos_get_iso(value, 1)); + rc = ptp_eos_set_validate_prop(r, PTP_PC_EOS_ISOSpeed, ptp_eos_get_iso(value, 1)); } } else if (!strcmp(name, "shutter speed")) { if (dev == PTP_DEV_EOS) { - rc = ptp_eos_set_prop_value(r, PTP_PC_EOS_ShutterSpeed, ptp_eos_get_shutter(value, 1)); + rc = ptp_eos_set_validate_prop(r, PTP_PC_EOS_ShutterSpeed, ptp_eos_get_shutter(value, 1)); } } else if (!strcmp(name, "white balance")) { if (dev == PTP_DEV_EOS) { @@ -26,8 +70,7 @@ int ptp_set_generic_property(struct PtpRuntime *r, char *name, int value) { rc = ptp_eos_set_prop_value(r, PTP_PC_EOS_EVFWBMode, ptp_eos_get_white_balance(value, 1)); } } else if (!strcmp(name, "destination")) { - return 0; - //bind_capture_type = value; + return PTP_UNSUPPORTED; } else { return PTP_UNSUPPORTED; } diff --git a/src/lib.c b/src/lib.c index c29abf4..d93a178 100644 --- a/src/lib.c +++ b/src/lib.c @@ -53,13 +53,14 @@ struct PtpRuntime *ptp_new(int options) { } void ptp_set_prop_avail_info(struct PtpRuntime *r, int code, int memb_size, int cnt, void *data) { + // Traverse backwards to first item struct PtpPropAvail *n; for (n = r->avail; n != NULL; n = n->prev) { if (n->code == code) break; } if (n != NULL) { - // Only realloc if needed (eventually will stop allocating) + // Only realloc if needed (eventually will stop allocating once we have hit a maximum) if (cnt > n->memb_cnt) { n->data = realloc(n->data, memb_size * cnt); } @@ -69,7 +70,7 @@ void ptp_set_prop_avail_info(struct PtpRuntime *r, int code, int memb_size, int } // Handle first element of linked list - if (r->avail->prev == NULL) { + if (r->avail->code == 0x0) { n = r->avail; } else { n = calloc(1, sizeof(struct PtpPropAvail)); diff --git a/src/transport.c b/src/transport.c index a59a4be..14a9761 100644 --- a/src/transport.c +++ b/src/transport.c @@ -130,8 +130,7 @@ int ptpip_receive_bulk_packets(struct PtpRuntime *r) { return PTP_IO_ERR; } - ptp_verbose_log("receive_bulk_packets: Read %d bytes\n", read); - ptp_verbose_log("receive_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); + ptp_verbose_log("ptpip_receive_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); return 0; } @@ -288,8 +287,8 @@ int ptpipusb_receive_bulk_packets(struct PtpRuntime *r) { read += rc; } - ptp_verbose_log("receive_bulk_packets: Read %d bytes\n", read); - ptp_verbose_log("receive_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); + ptp_verbose_log("ptpipusb_receive_bulk_packets: Read %d bytes\n", read); + ptp_verbose_log("ptpipusb_receive_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); return read; } @@ -371,12 +370,12 @@ int ptp_freceive_bulk_packets(struct PtpRuntime *r, FILE *stream, int of) { read += x; if (x != r->max_packet_size) { - ptp_verbose_log("receive_bulk_packets: Read %d bytes\n", read); + ptp_verbose_log("ptp_freceive_bulk_packets: Read %d bytes\n", read); // Read the response packet if only a data packet was sent if (type == PTP_PACKET_TYPE_DATA) { x = ptp_cmd_read(r, r->data, r->max_packet_size); - ptp_verbose_log("receive_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); + ptp_verbose_log("ptp_freceive_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); } else { // TODO: Why send a small packet with stream reader? }