Skip to content

Commit

Permalink
New, more optimizable writing routines
Browse files Browse the repository at this point in the history
Old (void **) funcs were a bad idea.
  • Loading branch information
petabyt committed Mar 10, 2024
1 parent 194b57a commit d21ebde
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 90 deletions.
16 changes: 10 additions & 6 deletions src/camlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ struct PtpRuntime {
/// is 512, but certain comm backends can manage more. For TCP, this isn't used.
int max_packet_size;

/// @brief Info about current connection, used to detect the vendor, supported opodes.
/// @brief Info about current connection, used to detect camera type, supported opodes, etc
/// @note Set by ptp_parse_device_info.
struct PtpDeviceInfo *di;
int device_type;

Expand Down Expand Up @@ -249,18 +250,21 @@ int ptp_buffer_resize(struct PtpRuntime *r, size_t size);
uint8_t ptp_read_uint8(void *dat);
uint16_t ptp_read_uint16(void *dat);
uint32_t ptp_read_uint32(void *dat);
void ptp_read_string(void *dat, char *string, int max);
int ptp_read_uint16_array(void *dat, uint16_t *buf, int max);
int ptp_read_uint32_array(void *dat, uint16_t *buf, int max);
int ptp_wide_string(char *buffer, int max, char *input);
void ptp_write_uint8(void *dat, uint8_t b);
int ptp_write_uint32(void *dat, uint32_t b);

void ptp_read_string(void *dat, char *string, int max);
int ptp_read_uint16_array(void *dat, uint16_t *buf, int max);
int ptp_write_string(void *dat, char *string);
int ptp_write_utf8_string(void *dat, char *string);
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);

int ptp_read_string2(uint8_t *dat, char *string, int max);
int ptp_write_string2(uint8_t *dat, char *string);
int ptp_write_utf8_string(void *dat, char *string);
int ptp_read_uint16_array2(uint8_t *dat, uint16_t *buf, int max, int *length);

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; }
Expand Down
32 changes: 16 additions & 16 deletions src/canon_adv.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,18 @@ static struct Tokens *lex_evproc_command(char string[]) {
return toks;
}

char *canon_evproc_pack(int *length, char *string) {
char *canon_evproc_pack(int *out_length, char *string) {
int length = 0;
// Allocate some memory for the footer, we will use this later
void *footer = malloc(500);
void *footer_ptr = footer;
uint32_t *long_args = footer;
int footer_length = 0;

// Set long_args to zero
footer_length += ptp_write_uint32(&footer_ptr, 0);
footer_length += ptp_write_u32(footer + footer_length, 0);

struct Tokens *toks = lex_evproc_command(string);

// You will need to make sure your request never exceeds this
// I can't be bothered to add bound checks
char *data = malloc(500);

if (toks->length == 0) {
Expand All @@ -209,16 +207,16 @@ char *canon_evproc_pack(int *length, char *string) {
int len = strlen(toks->t[0].string);
memcpy(data, toks->t[0].string, len);
data[len] = '\0';
(*length) += len + 1;
length += len + 1;
} else {
ptp_verbose_log("Error, first parameter must be plain text.\n");
return NULL;
}

// First uint32 is the number of parameters, we will save this ptr and modify it as we parse
uint32_t *num_args = (uint32_t *)(data + (*length));
uint32_t *num_args = (uint32_t *)(data + length);
(*num_args) = 0;
(*length) += 4;
length += 4;

// Pack parameters into data
for (int t = 1; t < toks->length; t++) {
Expand All @@ -229,8 +227,8 @@ char *canon_evproc_pack(int *length, char *string) {
integer.type = EOS_TOK_INT;
integer.number = toks->t[t].integer;

memcpy(data + (*length), &integer, sizeof(struct EvProcParam));
(*length) += sizeof(struct EvProcParam);
memcpy(data + length, &integer, sizeof(struct EvProcParam));
length += sizeof(struct EvProcParam);

(*num_args)++;
} break;
Expand All @@ -241,12 +239,12 @@ char *canon_evproc_pack(int *length, char *string) {
pstring.type = EOS_TOK_STR;
pstring.size = strlen(toks->t[t].string) + 1;

memcpy(data + (*length), &pstring, sizeof(struct EvProcParam));
memcpy(data + length, &pstring, sizeof(struct EvProcParam));

(*length) += sizeof(struct EvProcParam);
length += sizeof(struct EvProcParam);

footer_length += ptp_write_uint32((void **)&footer_ptr, 0);
footer_length += ptp_write_utf8_string((void **)&footer_ptr, toks->t[t].string);
footer_length += ptp_write_u32(footer + footer_length, 0);
footer_length += ptp_write_utf8_string(footer + footer_length, toks->t[t].string);
(*long_args)++;

(*num_args)++;
Expand All @@ -255,10 +253,12 @@ char *canon_evproc_pack(int *length, char *string) {
}

if (footer_length) {
memcpy(data + (*length), footer, footer_length);
(*length) += footer_length;
memcpy(data + length, footer, footer_length);
length += footer_length;
}

(*out_length) = length;

free(footer);
free(toks);

Expand Down
2 changes: 1 addition & 1 deletion src/cl_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ struct PtpFujiObjectInfo {
#pragma pack(pop)

#ifdef CAMLIB_INCLUDE_IMPL
int ptp_pack_object_info(struct PtpRuntime *r, struct PtpObjectInfo *oi, void **d, int max);
int ptp_pack_object_info(struct PtpRuntime *r, struct PtpObjectInfo *oi, void *buf, int max);

int ptp_parse_prop_value(struct PtpRuntime *r);
int ptp_parse_device_info(struct PtpRuntime *r, struct PtpDeviceInfo *di);
Expand Down
106 changes: 46 additions & 60 deletions src/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,6 @@ static int osnprintf(char *str, int cur, int size, const char *format, ...) {
return r;
}

// We do not have proper UTF16 support for now
static void format_sane_string(char *string) {
for (int i = 0; string[i] != '\0'; i++) {
if (string[i] < 0) {
string[i] = '?';
} else if (string[i] < 32) {
string[i] = ' ';
}
}
}

int ptp_get_data_size(void *d, int type) {
switch (type) {
case PTP_TC_INT8:
Expand All @@ -61,31 +50,35 @@ int ptp_get_data_size(void *d, int type) {
return 0;
}

int ptp_parse_data(void *d, int type) {
int ptp_parse_data(void *d, int type, int *out) {
uint8_t a;
uint16_t b;
uint32_t c;
switch (type) {
case PTP_TC_INT8:
case PTP_TC_UINT8:
return (uint8_t)ptp_read_uint8(d);
ptp_read_u8(d, &a); (*out) = (int)a; return 1;
case PTP_TC_INT16:
case PTP_TC_UINT16:
return (uint16_t)ptp_read_uint16(d);
ptp_read_u16(d, &b); (*out) = (int)b; return 2;
case PTP_TC_INT32:
case PTP_TC_UINT32:
return (uint32_t)ptp_read_uint32(d);
ptp_read_u16(d, &b); (*out) = (int)b; return 4;
}

return ptp_get_data_size(*((void **)d), type);
// skip the array
return ptp_get_data_size(d, type);
}

int ptp_parse_prop_value(struct PtpRuntime *r) {
void *d = ptp_get_payload(r);
uint8_t *d = ptp_get_payload(r);
switch (ptp_get_payload_length(r)) {
case 1:
return (int)(((uint8_t *)d)[0]);
return (int)(d[0]);
case 2:
return (int)(((uint16_t *)d)[0]);
return (int)(d[0]);
case 4:
return (int)(((uint32_t *)d)[0]);
return (int)(d[0]);
}

return -1;
Expand All @@ -95,8 +88,8 @@ int ptp_parse_prop_desc(struct PtpRuntime *r, struct PtpDevPropDesc *oi) {
uint8_t *d = ptp_get_payload(r);
memcpy(oi, d, PTP_PROP_DESC_VAR_START);
d += PTP_PROP_DESC_VAR_START;
oi->default_value = ptp_parse_data(&d, oi->data_type);
oi->current_value = ptp_parse_data(&d, oi->data_type);
d += ptp_parse_data(d, oi->data_type, &oi->default_value);
d += ptp_parse_data(d, oi->data_type, &oi->current_value);

// TODO: Form flag + form (for properties like date/time)
return 0;
Expand All @@ -106,38 +99,36 @@ int ptp_parse_object_info(struct PtpRuntime *r, struct PtpObjectInfo *oi) {
uint8_t *d = ptp_get_payload(r);
memcpy(oi, d, PTP_OBJ_INFO_VAR_START);
d += PTP_OBJ_INFO_VAR_START;
ptp_read_string(&d, oi->filename, sizeof(oi->filename));
ptp_read_string(&d, oi->date_created, sizeof(oi->date_created));
ptp_read_string(&d, oi->date_modified, sizeof(oi->date_modified));
ptp_read_string(&d, oi->keywords, sizeof(oi->keywords));
d += ptp_read_string2(d, oi->filename, sizeof(oi->filename));
d += ptp_read_string2(d, oi->date_created, sizeof(oi->date_created));
d += ptp_read_string2(d, oi->date_modified, sizeof(oi->date_modified));
d += ptp_read_string2(d, oi->keywords, sizeof(oi->keywords));

return 0;
}

// TODO: Different API
int ptp_pack_object_info(struct PtpRuntime *r, struct PtpObjectInfo *oi, void **dat, int max) {
int ptp_pack_object_info(struct PtpRuntime *r, struct PtpObjectInfo *oi, void *buf, int max) {
if (1024 > max) {
return 0;
}

uint8_t **ptr = (uint8_t **)(dat);
memcpy(*ptr, oi, PTP_OBJ_INFO_VAR_START);
(*ptr) += PTP_OBJ_INFO_VAR_START;

int length = PTP_OBJ_INFO_VAR_START;
memcpy(buf, oi, PTP_OBJ_INFO_VAR_START);
buf += PTP_OBJ_INFO_VAR_START;

// If the string is empty, don't add it to the packet
int of = PTP_OBJ_INFO_VAR_START;
if (oi->filename[0] != '\0')
length += ptp_write_string((ptr), oi->filename);
of += ptp_write_string2(buf + of, oi->filename);
if (oi->date_created[0] != '\0')
length += ptp_write_string((ptr), oi->date_created);
of += ptp_write_string2(buf + of, oi->date_created);
if (oi->date_modified[0] != '\0')
length += ptp_write_string((ptr), oi->date_modified);
of += ptp_write_string2(buf + of, oi->date_modified);
if (oi->keywords[0] != '\0')
length += ptp_write_string((ptr), oi->keywords);
of += ptp_write_string2(buf + of, oi->keywords);

// Return pointer length added
return length;
return of;
}

void *ptp_pack_chdk_upload_file(struct PtpRuntime *r, char *in, char *out, int *length) {
Expand Down Expand Up @@ -166,34 +157,29 @@ void *ptp_pack_chdk_upload_file(struct PtpRuntime *r, char *in, char *out, int *
}

int ptp_parse_device_info(struct PtpRuntime *r, struct PtpDeviceInfo *di) {
void *e = ptp_get_payload(r);

di->standard_version = ptp_read_uint16(&e);
di->vendor_ext_id = ptp_read_uint32(&e);
di->version = ptp_read_uint16(&e);

ptp_read_string(&e, di->extensions, sizeof(di->extensions));
uint8_t *e = ptp_get_payload(r);

di->functional_mode = ptp_read_uint16(&e);
e += ptp_read_u16(e, &di->standard_version);
e += ptp_read_u32(e, &di->vendor_ext_id);
e += ptp_read_u16(e, &di->version);

di->ops_supported_length = ptp_read_uint16_array(&e, di->ops_supported, sizeof(di->ops_supported) / 2);
di->events_supported_length = ptp_read_uint16_array(&e, di->events_supported, sizeof(di->events_supported) / 2);
di->props_supported_length = ptp_read_uint16_array(&e, di->props_supported, sizeof(di->props_supported) / 2);
di->capture_formats_length = ptp_read_uint16_array(&e, di->capture_formats, sizeof(di->capture_formats) / 2);
di->playback_formats_length = ptp_read_uint16_array(&e, di->playback_formats, sizeof(di->playback_formats) / 2);
e += ptp_read_string2(e, di->extensions, sizeof(di->extensions));

e += ptp_read_u16(e, &di->functional_mode);

ptp_read_string(&e, di->manufacturer, sizeof(di->manufacturer));
ptp_read_string(&e, di->model, sizeof(di->model));
e += ptp_read_uint16_array2(e, di->ops_supported, sizeof(di->ops_supported) / 2, &di->ops_supported_length);
e += ptp_read_uint16_array2(e, di->events_supported, sizeof(di->events_supported) / 2, &di->events_supported_length);
e += ptp_read_uint16_array2(e, di->props_supported, sizeof(di->props_supported) / 2, &di->props_supported_length);
e += ptp_read_uint16_array2(e, di->capture_formats, sizeof(di->capture_formats) / 2, &di->capture_formats_length);
e += ptp_read_uint16_array2(e, di->playback_formats, sizeof(di->playback_formats) / 2, &di->playback_formats_length);

ptp_read_string(&e, di->device_version, sizeof(di->device_version));
ptp_read_string(&e, di->serial_number, sizeof(di->serial_number));
e += ptp_read_string2(e, di->manufacturer, sizeof(di->manufacturer));
e += ptp_read_string2(e, di->model, sizeof(di->model));

format_sane_string(di->manufacturer);
format_sane_string(di->model);
format_sane_string(di->device_version);
format_sane_string(di->serial_number);
e += ptp_read_string2(e, di->device_version, sizeof(di->device_version));
e += ptp_read_string2(e, di->serial_number, sizeof(di->serial_number));

r->di = di;
r->di = di; // set last parsed di

return 0;
}
Expand Down Expand Up @@ -531,7 +517,7 @@ int ptp_fuji_parse_object_info(struct PtpRuntime *r, struct PtpFujiObjectInfo *o
uint8_t *d = ptp_get_payload(r);
memcpy(oi, d, PTP_FUJI_OBJ_INFO_VAR_START);
d += PTP_FUJI_OBJ_INFO_VAR_START;
ptp_read_string(&d, oi->filename, sizeof(oi->filename));
d += ptp_read_string2(d, oi->filename, sizeof(oi->filename));

/* TODO: Figure out payload later:
0D 44 00 53 00 43 00 46 00 35 00 30 00 38 00 37 00 2E 00 4A 00 50 00 47 00
Expand Down
3 changes: 1 addition & 2 deletions src/operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ int ptp_send_object_info(struct PtpRuntime *r, int storage_id, int handle, struc
cmd.params[1] = handle;

char temp[1024];
void *temp_ptr = temp;
int length = ptp_pack_object_info(r, oi, &temp_ptr, sizeof(temp));
int length = ptp_pack_object_info(r, oi, temp, sizeof(temp));
if (length == 0) {
return PTP_OUT_OF_MEM;
}
Expand Down
Loading

0 comments on commit d21ebde

Please sign in to comment.