Skip to content

Commit

Permalink
Refresh a lot of desktop/cli stuff, rewrite test script
Browse files Browse the repository at this point in the history
  • Loading branch information
petabyt committed Aug 8, 2024
1 parent 3b85094 commit 8f2f184
Show file tree
Hide file tree
Showing 9 changed files with 347 additions and 385 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
set -e

models=("fuji_x_h1" "fuji_x_a2" "fuji_x_t20" "fuji_x_t2" "fuji_x_s10" "fuji_x_f10" "fuji_x30")

for model in "${models[@]}"; do
~/vcam/vcam $model --local &
pid=$!
desktop/fudge.out -tw
kill $pid
done
2 changes: 1 addition & 1 deletion .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ jobs:
- name: Compile desktop
run: cd desktop && make TARGET=l fudge.out
- name: Run desktop unit test
run: cd desktop && ./fudge.out -tw
run: bash .github/workflows/test.sh
6 changes: 3 additions & 3 deletions desktop/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FUDGE = ../lib

OBJ := main.o ui.o
OBJ := main.o ui.o jank.o

CAMLIB_CORE := transport.o operations.o packet.o enums.o data.o enum_dump.o lib.o canon.o liveview.o bind.o ml.o conv.o generic.o canon_adv.o
ifeq ($(TARGET),l)
Expand All @@ -13,7 +13,7 @@ OBJ += $(addprefix camlib-,$(CAMLIB_CORE))
OBJ += $(addprefix camlua-,lua.o runtime.o)
OBJ += $(addprefix camluajson-,lua_cjson.o strbuf.o)

FUDGE_CORE := fuji.o tester.o viewer.o data.o net.o discovery.o exif.o uilua.o fuji_usb.o
FUDGE_CORE := fuji.o tester.o data.o net.o discovery.o exif.o uilua.o fuji_usb.o
OBJ += $(addprefix fudge-,$(FUDGE_CORE))

CAMLIB_DIR := ../lib/camlib
Expand Down Expand Up @@ -58,4 +58,4 @@ fudge-%.o: $(FUDGE)/%.c
-include $(CAMLIB_DIR)/src/*.d $(CAMLIB_DIR)/lua/*.d $(CAMLIB_DIR)/lua/lua-cjson/*.d $(FUDGE)/*.d

clean:
$(RM) *.o $(LIB_OBJ) main *.exe *.res
$(RM) *.o $(LIB_OBJ) main *.exe *.res *.out
6 changes: 6 additions & 0 deletions desktop/desktop.h
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
void network_init(void);
int fudge_main_ui(void);

int fuji_test_discovery(struct PtpRuntime *r);

int fuji_test_filesystem(struct PtpRuntime *r);
int fuji_test_setup(struct PtpRuntime *r);
259 changes: 259 additions & 0 deletions desktop/jank.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
// Jank code from testing Fuji PTP
// Their protocols SUCK!
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#ifdef WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <poll.h>
#include <arpa/inet.h>
#endif
#include <camlib.h>
#include <fuji.h>
#include <app.h>
#include <fujiptp.h>
#include "desktop.h"

// Trying to set camera properties like Fuji tetherapp does.
int fudge_test(struct PtpRuntime *r) {
if (ptp_device_init(r)) {
puts("Device connection error");
return 0;
}

int rc;

ptp_open_session(r);

#if 0
struct PtpPropDesc pd;
rc = ptp_get_prop_desc(r, 0xd20b, &pd);

printf("Prop data type: %d\n", ptp_get_payload_length(r));

rc = ptp_get_prop_value(r, 0xD21c);
if (rc) return rc;

printf("Prop code: %x\n", ptp_parse_prop_value(r));
#endif

/*
Fuji Wireless/USB Tether:
- PtpGetPropValue must be called after PtpSetPropValue
- If menu (or quick menu) is open, PtpSetPropValue will return DeviceBusy
- PtpDeviceInfo seems to include some data to indicate what properties have changed (bitmap?)
- PtpDeviceInfo FunctionalState is 0x02a8 (can't remember, vendor?)
- AFAIK gphoto people have not documented this mode. There were a few github issues about brokenness.
*/

// char buffer[90000];
// int i = 0;
// while (1) {
// ptp_set_prop_value(r, 0x5015, entries[i % 8]);
// i++;
// ptp_get_prop_value(r, 0x5015);
//
// struct PtpDeviceInfo di;
// rc = ptp_get_device_info(r, &di);
// if (rc) return rc;
// ptp_device_info_json(&di, buffer, sizeof(buffer));
// printf("%s\n", buffer);
//
// ptp_get_prop_value(r, 0xd20b);
// //printf("%X: %d\n", 0xd20b, ptp_parse_prop_value(r));
// ptp_get_prop_value(r, 0xd212);
// //printf("%X: %d\n", 0xd212, ptp_parse_prop_value(r));
//
//
// usleep(1000 * 1000 * 2);
// }

return 0;
}

// Fuji sets this property while doing pc autosave
// guess: client tells camera what photos are already downloaded
int _fuji_d228(struct PtpRuntime *r) {
char buffer[64];
int s = 0;
s += ptp_write_u8(buffer + s, 6);
s += ptp_write_u32(buffer + s, 0x0020);
s += ptp_write_u32(buffer + s, 0x0030);
s += ptp_write_u32(buffer + s, 0x002f);
s += ptp_write_u32(buffer + s, 0x0036);
s += ptp_write_u32(buffer + s, 0x0030);
s += ptp_write_u32(buffer + s, 0x0000);
return ptp_set_prop_value_data(r, 0xd228, buffer, s);
}

/*
- GetPartialObject and GetObjectInfo both refuse to send response if conditions are wrong
- Most of the time we can recover
- Is there a way to determine if we shouldn't download an image? No, ObjectInfo is basically the same.
- The max doesn't seem to matter.
- It works fine if we download the entire image. If we don't, or try and skip to the end, the next getpartialobject/getobjectinfo returns no
response.
Conclusion: GetPartialObject tracks the number of bytes read, and freaks out when attemping another object with previous unfinished
*/
int fuji_autosave_thumb(struct PtpRuntime *r, int handle) {
int rc;

tester_log("Object #%d...", handle);
#if 0
struct PtpObjectInfo oi;
r->wait_for_response = 1;
rc = ptp_get_object_info(r, handle, &oi);
if (rc == PTP_CHECK_CODE) {
return 0;
}
if (rc) {
tester_fail("Failed to get object info: %d", rc);
return 0;
} else {
tester_log("Got object info");
}

char buffer[1024];
ptp_object_info_json(&oi, buffer, sizeof(buffer));
app_print(buffer);
#endif

// rc = ptp_get_partial_object(r, handle, 0, 0x0);
// rc = ptp_get_partial_object(r, handle, 0, 0x0);

// _fuji_d228(r);

//rc = ptp_set_prop_value16(r, PTP_PC_FUJI_NoCompression, 1);

rc = fuji_get_events(r);
if (rc) return rc;


int max = 0x100000/128;

// if (handle == 15 || handle == 8 || handle == 7) max = 0x100000;

r->wait_for_response = 2;
rc = ptp_get_partial_object(r, handle, 0, max);
if (rc == PTP_IO_ERR) return rc;
//rc = ptp_get_partial_object(r, handle, 0xfffffff, 0xfffffff);

rc = ptp_get_partial_object(r, handle, max, max * 2);
if (rc == PTP_IO_ERR) return rc;

rc = fuji_get_events(r);
if (rc) return rc;
rc = fuji_get_events(r);
if (rc) return rc;
rc = fuji_get_events(r);
if (rc) return rc;
rc = fuji_get_events(r);
if (rc) return rc;

/*
300-200
get event x1
max = 0x100000/32
partial object x2
get event x4
Took 67.956009 seconds
- x4 -> x1: crash
- x1/x3: 63.188999
- x1/x2: 56.750000
- x1/x1: crash
- getobjinfo+x1/x3: 73... without getobjectinfo, 62.955002
- get event x1/x1, usleep 100ms: 61.487000
- 0 get event, 300ms: crash
*/

//

// rc = ptp_get_partial_object(r, handle | (1 << 31), 0, 0x0);
// rc = ptp_get_partial_object(r, handle | (1 << 31), 0, 0x0);

// rc = fuji_get_events(r);
// if (rc) return rc;

//rc = ptp_get_partial_object(r, handle, 0x0fffffff, 0x0);

//rc = ptp_get_partial_object(r, handle, oi.compressed_size - 0x100000, 0x100000);
//if (rc == PTP_IO_ERR) return rc;

//rc = ptp_set_prop_value16(r, PTP_PC_FUJI_NoCompression, 1);
//rc = fuji_get_events(r);

return 0;
}

/*
Fuji Wireless Tether property setting:
- PtpGetPropValue must be called after PtpSetPropValue
- If menu (or quick menu) is open, PtpSetPropValue will return DeviceBusy
- PtpDeviceInfo seems to include some data to indicate what properties have changed
*/
static int dump_prop(struct PtpRuntime *r) {
struct PtpPropDesc pd;
int rc = ptp_get_prop_desc(r, 0x5015, &pd);
if (rc) return rc;
char buffer[70000];
ptp_prop_desc_json(&pd, buffer, sizeof(buffer));
printf("%s\n", buffer);
return 0;
}

int fuji_test_discovery(struct PtpRuntime *r) {
struct DiscoverInfo info = {0};
network_init();

int sock = socket(AF_INET, SOCK_DGRAM, 0);

int rc = fuji_discover_thread(&info, "Fudge (desktop)", NULL);
if (rc == FUJI_D_REGISTERED) {
plat_dbg("Registered %s %s", info.camera_name, info.camera_model);
} else if (rc == FUJI_D_GO_PTP) {
usleep(100000); // TODO: Kind of have to wait before connecting

printf("connecting to %s:%d\n", info.camera_ip, info.camera_port);
if (ptpip_connect(r, info.camera_ip, info.camera_port)) {
printf("Error connecting to %s:%d\n", info.camera_ip, info.camera_port);
return 0;
}

fuji_reset_ptp(r);
r->connection_type = PTP_IP_USB;
fuji_get(r)->transport = info.transport;

//rc = fujitether_setup(r);
rc = fuji_setup(r, info.camera_ip);
if (rc) return rc;

float startTime = (float)clock()/CLOCKS_PER_SEC;

int max = fuji_get(r)->num_objects;
for (int i = max; i != max - 100; i--) {
rc = fuji_autosave_thumb(r, i);
if (rc) {
plat_dbg("Failed autosave thumb");
return rc;
}
}

float endTime = (float)clock()/CLOCKS_PER_SEC;

plat_dbg("Took %f seconds", endTime - startTime);

int16_t entries[] = {0, 10, 20, 30};

ptpip_close(r);
} else {
plat_dbg("Response code: %d\n", rc);
}

return -1;
}
Loading

0 comments on commit 8f2f184

Please sign in to comment.