Skip to content

Commit

Permalink
New data struct API, also UintArray -> PtpArray
Browse files Browse the repository at this point in the history
Some steps to not depend on misaligned access so much
  • Loading branch information
petabyt committed Jan 25, 2024
1 parent 6b95532 commit 24af49d
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 93 deletions.
4 changes: 2 additions & 2 deletions src/bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ int bind_get_device_info(struct BindReq *bind, struct PtpRuntime *r) {
}

int bind_get_storage_ids(struct BindReq *bind, struct PtpRuntime *r) {
struct UintArray *arr;
struct PtpArray *arr;
int x = ptp_get_storage_ids(r, &arr);
if (x) return sprintf(bind->buffer, "{\"error\": %d}", x);

Expand All @@ -113,7 +113,7 @@ int bind_get_storage_info(struct BindReq *bind, struct PtpRuntime *r) {
}

int bind_get_object_handles(struct BindReq *bind, struct PtpRuntime *r) {
struct UintArray *arr;
struct PtpArray *arr;
// Parameters changed to correct order 14 nov 2023
int x = ptp_get_object_handles(r, bind->params[0], bind->params[1], bind->params[2], &arr);
if (x) return sprintf(bind->buffer, "{\"error\": %d}", x);
Expand Down
17 changes: 13 additions & 4 deletions src/camlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ 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.
// TODO: Should the IO backend toggle the IO kill switch
uint8_t io_kill_switch;

/// @brief One of enum PtpConnType
Expand Down Expand Up @@ -167,6 +166,12 @@ struct PtpCommand {
int data_length;
};

/// @brief Generic Struct for arrays
struct PtpArray {
uint32_t length;
uint32_t data[];
};

/// @brief Returns the return code (RC) currently in the data buffer.
/// @note Not thread safe.
int ptp_get_return_code(struct PtpRuntime *r);
Expand Down Expand Up @@ -258,6 +263,13 @@ int ptp_write_unicode_string(char *dat, char *string);
int ptp_read_unicode_string(char *buffer, char *dat, int max);
void ptp_read_utf8_string(void *dat, char *string, int max);

inline static int ptp_write_u8 (void *buf, uint8_t out) { ((uint8_t *)buf)[0] = out; return 1; }
inline static int ptp_write_u16(void *buf, uint16_t out) { ((uint16_t *)buf)[0] = out; return 2; }
inline static int ptp_write_u32(void *buf, uint32_t out) { ((uint32_t *)buf)[0] = out; return 4; }
inline static int ptp_read_u32 (void *buf, uint32_t *out) { *out = ((uint32_t *)buf)[0]; return 4; }
inline static int ptp_read_u16 (void *buf, uint16_t *out) { *out = ((uint16_t *)buf)[0]; return 2; }
inline static int ptp_read_u8 (void *buf, uint8_t *out) { *out = ((uint8_t *)buf)[0]; return 1; }

// Build a new PTP/IP or PTP/USB command packet in r->data
int ptp_new_cmd_packet(struct PtpRuntime *r, struct PtpCommand *cmd);

Expand All @@ -274,9 +286,6 @@ void ptp_update_transaction(struct PtpRuntime *r, int t);
// Set avail info for prop
void ptp_set_prop_avail_info(struct PtpRuntime *r, int code, int memb_size, int cnt, void *data);

// Duplicate array, return malloc'd buffer
struct UintArray *ptp_dup_uint_array(struct UintArray *arr) __attribute__ ((deprecated));

void *ptp_dup_payload(struct PtpRuntime *r);

// Write r->data to a file called DUMP
Expand Down
58 changes: 29 additions & 29 deletions src/canon_adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,35 @@
#include <stdlib.h>
#include <camlib.h>

#define EOS_TOK_INT 2
#define EOS_TOK_STR 4

struct EvProcParam {
uint32_t type;
uint32_t number;
uint32_t p3;
uint32_t p4;
uint32_t size;
};

enum Types {
TOK_TEXT,
TOK_STR,
TOK_INT,
};

#define MAX_STR 128
#define MAX_TOK 10

struct Tokens {
struct T {
int type;
char string[MAX_STR];
int integer;
} t[MAX_TOK];
int length;
};

// Required on some newer cameras, like the EOS M.
int ptp_eos_activate_command(struct PtpRuntime *r) {
if (!ptp_check_opcode(r, PTP_OC_EOS_EnableEventProc)) {
Expand Down Expand Up @@ -53,35 +82,6 @@ int ptp_eos_evproc_return_data(struct PtpRuntime *r) {
return ptp_send(r, &cmd);
}

#define EOS_TOK_INT 2
#define EOS_TOK_STR 4

struct EvProcParam {
uint32_t type;
uint32_t number;
uint32_t p3;
uint32_t p4;
uint32_t size;
};

enum Types {
TOK_TEXT,
TOK_STR,
TOK_INT,
};

#define MAX_STR 128
#define MAX_TOK 10

struct Tokens {
struct T {
int type;
char string[MAX_STR];
int integer;
} t[MAX_TOK];
int length;
};

static int alpha(char c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
Expand Down
1 change: 1 addition & 0 deletions src/cl_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct PtpStorageIds {
uint32_t data[4];
};

// TODO: Rename PtpUintArray
struct UintArray {
uint32_t length;
uint32_t data[];
Expand Down
51 changes: 29 additions & 22 deletions src/cl_ops.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
// TODO: Documentation should be in header file or above C code?
/** \file */
#ifndef OPERATIONS_H
#define OPERATIONS_H

// Generic device-independent functionality
/// @brief Set a generic property - abstraction over SetDeviceProp
/// @note May reject writes if an invalid property is found (see event code)
int ptp_set_generic_property(struct PtpRuntime *r, char *name, int value);

/// @brief Call before taking a picture - this is generally for 'focusing'
/// Sometimes will do nothing.
/// @note This is meant for a onMouseDown-like event. ptp_take_picture should be called on onMouseUp
int ptp_pre_take_picture(struct PtpRuntime *r);
int ptp_take_picture(struct PtpRuntime *r);

// Standard PTP operation code functions
/// @brief Call after calling ptp_pre_take_picture - this time a picture will be taken.
int ptp_take_picture(struct PtpRuntime *r);

// Note that opening a session is required for most vendor commands
/// @brief Open a new session - required for most commands
int ptp_open_session(struct PtpRuntime *r);
int ptp_close_session(struct PtpRuntime *r);
int ptp_get_device_info(struct PtpRuntime *r, struct PtpDeviceInfo *di);
// Recieves storage IDs into an UintArray. The 'pointer pointer' will be assigned to the r->data
// buffer, so it will eventually be overwritten. You can duplicate the array with ptp_dup_uint_array()
int ptp_get_storage_ids(struct PtpRuntime *r, struct UintArray **a);
/// @brief Returns allocated array of storage IDs
/// call free() afterwards
int ptp_get_storage_ids(struct PtpRuntime *r, struct PtpArray **a);
int ptp_init_capture(struct PtpRuntime *r, int storage_id, int object_format);
int ptp_init_open_capture(struct PtpRuntime *r, int storage_id, int object_format);
int ptp_terminate_open_capture(struct PtpRuntime *r, int trans);
Expand All @@ -25,29 +30,31 @@ int ptp_get_prop_value(struct PtpRuntime *r, int code);
int ptp_set_prop_value(struct PtpRuntime *r, int code, int value);
int ptp_set_prop_value_data(struct PtpRuntime *r, int code, void *data, int length);
int ptp_get_prop_desc(struct PtpRuntime *r, int code, struct PtpDevPropDesc *pd);
// Gets a list of object handles in a storage device or folder.
// id: storage ID
// format: Can specify file format ID, or zero for all
// in: Can be folder object ID, or 0 for recursive all
// Output array is a pointer to data packet, and will be overwritten by new operations
int ptp_get_object_handles(struct PtpRuntime *r, int id, int format, int in, struct UintArray **a);
/// @brief Gets a list of object handles in a storage device or folder.
// @param id storage ID
// @param format Can specify file format ID, or zero for all IDs
// @param in Can be folder object ID, or 0 for recursive (entire filesystem)
// @param[out] a Output array is a pointer to data packet, and will be overwritten by new operations
int ptp_get_object_handles(struct PtpRuntime *r, int id, int format, int in, struct PtpArray **a);
int ptp_get_object_info(struct PtpRuntime *r, uint32_t handle, struct PtpObjectInfo *oi);
int ptp_move_object(struct PtpRuntime *r, int storage_id, int handle, int folder);
int ptp_delete_object(struct PtpRuntime *r, int handle, int format_code);
// Raw JPEG data is accessible from ptp_get_payload()
/// @brief Raw JPEG data is accessible from ptp_get_payload()
/// @note Not thread safe.
int ptp_get_thumbnail(struct PtpRuntime *r, int handle);
/// @note Not thread safe.
int ptp_get_partial_object(struct PtpRuntime *r, uint32_t handle, int offset, int max);
// Download an object from handle, to a local file (uses GetPartialObject)
/// @brief Download an object from handle, to a local file (uses GetPartialObject)
int ptp_download_file(struct PtpRuntime *r, int handle, char *file);
// Run an opcode - For debugging and prototyping only
int ptp_custom_receive(struct PtpRuntime *r, int code);
// Recieve a generic list of all properties received in DeviceInfo - caller must free s
// This is similar to getting all events, but for first startup when you know nothing.
// Some vendors do this, but this gets all the properties manually.
/// @brief Recieve a generic list of all properties received in DeviceInfo
/// This is similar to getting all events, but for first startup when you know nothing.
/// Some vendors do this, but this gets all the properties manually.
/// @param[out] s Output structure, caller must free
int ptp_get_all_known(struct PtpRuntime *r, struct PtpGenericEvent **s, int *length);

// PTP/IP only
/// @note PTP/IP only
int ptpip_init_events(struct PtpRuntime *r);
/// @note PTP/IP only
int ptpip_init_command_request(struct PtpRuntime *r, char *device_name);

// EOS Only functions - not for Canon point and shoot
Expand Down
1 change: 0 additions & 1 deletion src/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <camlib.h>

// Custom snprint with offset - for safer string building
// Eventually, this should be used for all JSON string builders
static int osnprintf(char *str, int cur, int size, const char *format, ...) {
if (size - cur < 0) {
return 0;
Expand Down
2 changes: 2 additions & 0 deletions src/libusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *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 Down
15 changes: 11 additions & 4 deletions src/operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@
#include <camlib.h>
#include <ptp.h>

static struct UintArray *dup_uint_array(struct UintArray *arr) {
struct UintArray *dup = malloc(4 + arr->length * 4);
static struct PtpArray *dup_uint_array(struct UintArray *arr) {
struct PtpArray *dup = malloc(4 + arr->length * 4);
if (dup == NULL) return NULL;

memcpy(dup, arr, 4 + arr->length * 4);

ptp_write_u32(&dup->length, arr->length);
for (int i = 0; i < arr->length; i++) {
ptp_write_u32(&dup->data[i], arr->data[i]);
}

return dup;
}

Expand Down Expand Up @@ -137,7 +144,7 @@ int ptp_terminate_open_capture(struct PtpRuntime *r, int trans) {
}

// TODO: Return PtpStorageIds
int ptp_get_storage_ids(struct PtpRuntime *r, struct UintArray **a) {
int ptp_get_storage_ids(struct PtpRuntime *r, struct PtpArray **a) {
struct PtpCommand cmd;
cmd.code = PTP_OC_GetStorageIDs;
cmd.param_length = 0;
Expand Down Expand Up @@ -207,7 +214,7 @@ int ptp_send_object_info(struct PtpRuntime *r, int storage_id, int handle, struc
return ptp_send_data(r, &cmd, temp, length);
}

int ptp_get_object_handles(struct PtpRuntime *r, int id, int format, int in, struct UintArray **a) {
int ptp_get_object_handles(struct PtpRuntime *r, int id, int format, int in, struct PtpArray **a) {
struct PtpCommand cmd;
cmd.code = PTP_OC_GetObjectHandles;
cmd.param_length = 3;
Expand Down
28 changes: 0 additions & 28 deletions src/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,6 @@ uint32_t ptp_read_uint32(void *dat) {
return x;
}

#if 0
// This seems slower than misaligned access lol
uint8_t ptp_read_u8(void *dat) {
uint8_t **p = (uint8_t **)dat;
uint8_t x = (**p);
(*p)++;
return x;
}

uint16_t ptp_read_u6(void *dat) {
uint8_t **p = (uint8_t **)dat;
uint16_t x = (p[0][0] << 8) | p[0][0];
(*p) += 2;
return x;
}

uint32_t ptp_read_u32(void *dat) {
uint8_t **p = (uint8_t **)dat;
uint32_t x;
((uint8_t *)&x)[0] = p[0][0];
((uint8_t *)&x)[1] = p[0][1];
((uint8_t *)&x)[2] = p[0][2];
((uint8_t *)&x)[3] = p[0][3];
(*p) += 4;
return x;
}
#endif

void ptp_write_uint8(void *dat, uint8_t b) {
uint8_t **ptr = (uint8_t **)dat;
(**ptr) = b;
Expand Down
6 changes: 3 additions & 3 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int test_eos_t6() {
assert(!strcmp(di.extensions, "G-V: 1.0;"));
assert(!strcmp(di.model, "Canon EOS Rebel T6"));

struct UintArray *arr;
struct PtpArray *arr;
rc = ptp_get_storage_ids(&r, &arr);
if (rc) return rc;
int id = arr->data[0];
Expand Down Expand Up @@ -149,7 +149,7 @@ int test_fs() {
ptp_device_info_json(&di, buffer, sizeof(buffer));
printf("%s\n", buffer);

struct UintArray *arr;
struct PtpArray *arr;
rc = ptp_get_storage_ids(&r, &arr);
if (rc) return rc;
int id = arr->data[0];
Expand Down Expand Up @@ -195,7 +195,7 @@ static void *thread(void *arg) {
ptp_device_info_json(&di, buffer, sizeof(buffer));
printf("%s\n", buffer);
} else {
struct UintArray *arr;
struct PtpArray *arr;
int rc = ptp_get_storage_ids(r, &arr);
if (rc) goto err;
printf("%X\n", arr->data[0]);
Expand Down

0 comments on commit 24af49d

Please sign in to comment.