diff --git a/Doxyfile b/Doxyfile
index e673981..893b4f8 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1,4 +1,14 @@
PROJECT_NAME = "camlib"
PROJECT_BRIEF = "Documentation for camlib is still a work-in-progress"
-INPUT = README.md docs/chdk.md docs/ml.md docs/ptp.md src/camlib.h src/cl_ops.h
+INPUT = README.md docs/chdk.md docs/ml.md docs/ptp.md \
+rc/camlib.h src/cl_backend.h src/cl_bind.h src/cl_data.h src/cl_enum.h src/cl_ops.h src/ptp.h
USE_MDFILE_AS_MAINPAGE = README.md
+GENERATE_LATEX = NO
+GENERATE_HTML = YES
+SOURCE_BROWSER = YES
+LAYOUT_FILE = docs/DoxygenLayout.xml
+
+VERBATIM_HEADERS = NO
+
+EXAMPLE_PATH = examples/usb.c
+EXAMPLE_PATTERNS = *
diff --git a/Makefile b/Makefile
index d4552a2..69658a0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
-include config.mak
-CFLAGS := -Isrc/ -g -fpic -Wall -Wshadow -Wcast-qual -Wpedantic -Werror=incompatible-pointer-types -Werror=deprecated-declarations
+CFLAGS := -Isrc/ -g -fpic -Wall -Wshadow -Wcast-qual -Wpedantic -Werror=incompatible-pointer-types -Werror=deprecated-declarations -Wstrict-aliasing=3
CFLAGS += -D CAMLIB_NO_COMPAT -D VERBOSE
# Camlib needs to be compiled with these files, with some exceptions:
diff --git a/docs/DoxygenLayout.xml b/docs/DoxygenLayout.xml
new file mode 100644
index 0000000..1f84b82
--- /dev/null
+++ b/docs/DoxygenLayout.xml
@@ -0,0 +1,248 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/pktest.c b/examples/pktest.c
index ec0a932..2b08f16 100644
--- a/examples/pktest.c
+++ b/examples/pktest.c
@@ -30,7 +30,6 @@ int main() {
cmd.code = PTP_OC_OpenSession;
cmd.params[0] = 1;
cmd.param_length = 1;
- cmd.data_length = 0;
int l = ptp_new_cmd_packet(&r, &cmd);
print_bytes(r.data, l);
diff --git a/examples/usb.c b/examples/usb.c
index 27c2e6e..d50f124 100644
--- a/examples/usb.c
+++ b/examples/usb.c
@@ -1,4 +1,5 @@
-// Test device list API
+/// @file
+/// @brief Example of using the device list API
#include
#include
#include
@@ -15,7 +16,7 @@ static int connect(struct PtpRuntime *r) {
}
if (ptp_device_init(r)) {
- puts("Device connection error");
+ printf("Device connection error\n");
return 1;
}
@@ -27,11 +28,10 @@ static int connect(struct PtpRuntime *r) {
}
int main() {
- struct PtpRuntime r;
- ptp_generic_init(&r);
+ struct PtpRuntime *r = ptp_new(PTP_USB);
- if (connect(&r)) return 1;
- if (connect(&r)) return 1;
+ if (connect(r)) return 1;
+ if (connect(r)) return 1;
return 0;
}
diff --git a/examples/wifi.c b/examples/wifi.c
index 7be6bf9..aa52b18 100644
--- a/examples/wifi.c
+++ b/examples/wifi.c
@@ -1,4 +1,5 @@
-// Test basic opcode, get device properties
+/// @file
+/// @brief Hello
#include
#include
#include
@@ -23,10 +24,8 @@ int main() {
r.connection_type = PTP_IP;
char *ip = "192.168.1.2";
- ip = "127.0.0.1";
- int port = PTP_IP_PORT;
- if (ptpip_connect(&r, ip, port)) {
+ if (ptpip_connect(&r, ip, PTP_IP_PORT)) {
puts("Device connection error");
return 0;
}
diff --git a/src/camlib.h b/src/camlib.h
index 5cbf54e..e746bf3 100644
--- a/src/camlib.h
+++ b/src/camlib.h
@@ -186,94 +186,74 @@ struct PtpArray {
/// @brief Returns the return code (RC) currently in the data buffer.
/// @note Not thread safe.
-/// @memberof PtpRuntime
PUB int ptp_get_return_code(struct PtpRuntime *r);
/// @brief Get number of parameters in packet in data buffer
/// @note Not thread safe.
-/// @memberof PtpRuntime
PUB int ptp_get_param_length(struct PtpRuntime *r);
/// @brief Get parameter at index i
/// @note Not thread safe.
-/// @memberof PtpRuntime
PUB uint32_t ptp_get_param(struct PtpRuntime *r, int i);
/// @brief Get transaction ID of packet in the data buffer
/// @note Not thread safe.
-/// @memberof PtpRuntime
PUB int ptp_get_last_transaction_id(struct PtpRuntime *r);
/// @brief Get ptr of packet payload in data buffer, after packet header
/// @note Not thread safe.
-/// @memberof PtpRuntime
PUB uint8_t *ptp_get_payload(struct PtpRuntime *r);
/// @brief Get length of payload returned by ptp_get_payload
/// @note Not thread safe.
-/// @memberof PtpRuntime
PUB int ptp_get_payload_length(struct PtpRuntime *r);
/// @brief Allocate new PtpRuntime based on bitfield options - see PtpConnType
-/// @memberof PtpRuntime
PUB struct PtpRuntime *ptp_new(int options);
/// @brief Reset all session-specific fields of PtpRuntime - both libusb and libwpd backends call
/// this before establishing connection, so calling this is not required
-/// @memberof PtpRuntime
PUB void ptp_reset(struct PtpRuntime *r);
/// @brief Init PtpRuntime locally - uses default recommended settings (USB)
-/// @memberof PtpRuntime
PUB void ptp_init(struct PtpRuntime *r);
/// @brief Frees PtpRuntime data buffer - doesn't free the actual structure, or device info (yet)
-/// @memberof PtpRuntime
PUB void ptp_close(struct PtpRuntime *r);
/// @brief Send a command request to the device with no data phase
-/// @memberof PtpRuntime
PUB int ptp_send(struct PtpRuntime *r, struct PtpCommand *cmd);
/// @brief Send a command request to the device with a data phase (thread safe)
-/// @memberof PtpRuntime
PUB int ptp_send_data(struct PtpRuntime *r, struct PtpCommand *cmd, void *data, int length);
/// @brief Try and get an event from the camera over int endpoint (USB-only)
-/// @memberof PtpRuntime
PUB int ptp_get_event(struct PtpRuntime *r, struct PtpEventContainer *ec);
/// @brief Unlock the IO mutex (unless it was kept locked)
-/// @memberof PtpRuntime
PUB void ptp_mutex_unlock(struct PtpRuntime *r);
/// @brief Completely unlock the mutex for the current thread, to ensure there isn't a deadlock.
/// This is normally used on handling errors, and when exiting a thread.
-/// @memberof PtpRuntime
PUB void ptp_mutex_unlock_thread(struct PtpRuntime *r);
/// @brief Lock the IO mutex - only should be used by backend
-/// @memberof PtpRuntime
PUB void ptp_mutex_lock(struct PtpRuntime *r);
/// @brief Gets type of device from r->di
/// @returns enum PtpDeviceType
-/// @memberof PtpRuntime
PUB int ptp_device_type(struct PtpRuntime *r);
/// @brief Check if an opcode is supported by looking through supported props in r->di
/// @returns 1 if yes, 0 if no
-/// @memberof PtpRuntime
PUB int ptp_check_opcode(struct PtpRuntime *r, int opcode);
/// @brief Check if a property code is supported by looking through supported props in r->di
/// @returns 1 if yes, 0 if no
-/// @memberof PtpRuntime
PUB int ptp_check_prop(struct PtpRuntime *r, int code);
/// @brief Mostly for internal use - realloc the data buffer
/// @note r->data will be reassigned, any old references must be updated
-/// @memberof PtpRuntime
PUB int ptp_buffer_resize(struct PtpRuntime *r, size_t size);
// Data structure functions
@@ -285,6 +265,7 @@ PUB int ptp_write_string(uint8_t *dat, const char *string);
PUB int ptp_write_utf8_string(void *dat, const char *string);
PUB int ptp_read_uint16_array(const uint8_t *dat, uint16_t *buf, int max, int *length);
PUB int ptp_read_uint16_array_s(uint8_t *bs, uint8_t *be, uint16_t *buf, int max, int *length);
+// TODO: This is bad
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; }
diff --git a/src/cl_backend.h b/src/cl_backend.h
index 5e92397..a28806f 100644
--- a/src/cl_backend.h
+++ b/src/cl_backend.h
@@ -1,6 +1,12 @@
+/** \file */
#ifndef CL_BACKEND_H
#define CL_BACKEND_H
+/// @defgroup Backend Backend interface
+/// @brief Layer over OS-dependent I/O interface
+/// @addtogroup Backend
+/// @{
+
#define PTP_TIMEOUT 1000
/// @brief Linked-list entry for a single USB device
@@ -24,64 +30,47 @@ struct PtpDeviceEntry {
/// @brief Get a linked list of USB or PTP Devices
/// @returns linked list of devices or NULL if no devices are connected (or OS error)
-/// @memberof PTP/USB
struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r);
-/// @memberof PTP/USB
void ptpusb_free_device_list(struct PtpDeviceEntry *e);
/// @brief Open and connect to a device from the PtpDeviceEntry structure
/// @note Sets kill switch to 0
-/// @memberof PTP/USB
int ptp_device_open(struct PtpRuntime *r, struct PtpDeviceEntry *entry);
/// @brief Connects to the first PTP device it finds
int ptp_device_init(struct PtpRuntime *r);
/// @brief Send data over the raw command endpoint
-/// @memberof PTP/USB
int ptp_cmd_write(struct PtpRuntime *r, void *to, int length);
/// @brief Receive raw data over the command endpoint
-/// @memberof PTP/USB
int ptp_cmd_read(struct PtpRuntime *r, void *to, int length);
/// @brief Reset the USB endpoints if possible
-/// @memberof PTP/USB
int ptp_device_reset(struct PtpRuntime *r);
/// @brief Send packets in r->data
-/// @memberof PTP/USB
int ptp_send_packet(struct PtpRuntime *r, int length);
/// @brief Receive all packets into r->data
-/// @memberof PTP/USB
int ptp_receive_all_packets(struct PtpRuntime *r);
/// @brief Poll the interrupt endpoint
-/// @memberof PTP/USB
int ptp_read_int(struct PtpRuntime *r, void *to, int length);
/// @brief Disconnect from the current device
-/// @memberof PTP/USB
int ptp_device_close(struct PtpRuntime *r);
/// @brief Connect to a TCP port on the default network adapter
/// @note Sets kill switch to 0
-/// @memberof PTP/IP
int ptpip_connect(struct PtpRuntime *r, const char *addr, int port, int extra_tmout);
-/// @memberof PTP/IP
int ptpip_cmd_write(struct PtpRuntime *r, void *data, int size);
-/// @memberof PTP/IP
int ptpip_cmd_read(struct PtpRuntime *r, void *data, int size);
-/// @memberof PTP/IP
int ptpip_connect_events(struct PtpRuntime *r, const char *addr, int port);
-/// @memberof PTP/IP
int ptpip_event_send(struct PtpRuntime *r, void *data, int size);
-/// @memberof PTP/IP
int ptpip_event_read(struct PtpRuntime *r, void *data, int size);
-/// @memberof PTP/IP
int ptpip_close(struct PtpRuntime *r);
void ptpusb_free_device_list_entry(void *);
@@ -89,4 +78,6 @@ void ptpusb_free_device_list_entry(void *);
/// @brief Get status of connected device
int ptpusb_get_status(struct PtpRuntime *r);
+/// @}
+
#endif
diff --git a/src/cl_bind.h b/src/cl_bind.h
index d056401..913c728 100644
--- a/src/cl_bind.h
+++ b/src/cl_bind.h
@@ -1,3 +1,4 @@
+/** \file */
#ifndef CL_BIND_H
#define CL_BIND_H
diff --git a/src/cl_data.h b/src/cl_data.h
index 8a623c7..9d25021 100644
--- a/src/cl_data.h
+++ b/src/cl_data.h
@@ -1,12 +1,12 @@
+/** \file */
// PTP data structures - some very similar to the exact MTP/PTP spec.
-// Variable sized arrays/strings are replaced with fixed arrays, to allow
-// packing and unpacking in the same struct.
#ifndef CL_DATA_H
#define CL_DATA_H
-// Need to avoid structure packing - most architectures are fine with this
-// (accessing a 32 bit integer at an unaligned address - but some might have problems)
-#pragma pack(push, 1)
+/// @defgroup Data Data structures
+/// @brief Functions to pack/unpack PTP data structures
+/// @addtogroup Data
+/// @{
struct PtpStorageIds {
uint32_t length;
@@ -161,9 +161,6 @@ enum PtpCHDKCommands {
PTP_CHDK_UploadFile = 5,
};
-#pragma pack(pop)
-
-#ifdef CAMLIB_INCLUDE_IMPL
int ptp_pack_object_info(struct PtpRuntime *r, struct PtpObjectInfo *oi, uint8_t *buf, int max);
int ptp_parse_prop_value(struct PtpRuntime *r);
@@ -191,5 +188,3 @@ int ptp_eos_get_imgformat_value(uint32_t data[5]);
void *ptp_pack_chdk_upload_file(struct PtpRuntime *r, char *in, char *out, int *length);
#endif
-
-#endif
diff --git a/src/cl_enum.h b/src/cl_enum.h
index 142ebe2..983f616 100644
--- a/src/cl_enum.h
+++ b/src/cl_enum.h
@@ -1,8 +1,14 @@
+/** \file */
#ifndef CL_ENUM_H
#define CL_ENUM_H
#define MAX_ENUM_LENGTH 64
+/// @defgroup Enums Enums
+/// @brief API to get string that represents PTP code
+/// @addtogroup Enums
+/// @{
+
int ptp_enum_all(char *string);
int ptp_enum(int type, char *string);
char *ptp_get_enum(int type, int vendor, int id);
@@ -33,4 +39,6 @@ struct PtpEnum {
extern int ptp_enums_length;
extern struct PtpEnum ptp_enums[];
+/// @}
+
#endif
diff --git a/src/cl_ops.h b/src/cl_ops.h
index 8da0b3b..b370e16 100644
--- a/src/cl_ops.h
+++ b/src/cl_ops.h
@@ -21,62 +21,52 @@ struct PtpLiveviewParams {
enum PtpLiveViewFormat format;
};
+/// @defgroup Operations PTP Operations
+/// @brief PTP opcode functions - may also call unpack data structures
+/// @addtogroup Operations
+/// @{
+
int ptp_liveview_params(struct PtpRuntime *r, struct PtpLiveviewParams *params);
/// @brief Set a generic property - abstraction over SetDeviceProp
/// @note May reject writes if an invalid property is found (see event code)
-/// @memberof PtpRuntime
int ptp_set_generic_property(struct PtpRuntime *r, const char *name, int value);
/// @brief Call before taking a picture - this is generally for 'focusing'
/// On some cameras this does nothing.
/// @note This is meant for a onMouseDown-like event. ptp_take_picture should be called on onMouseUp
-/// @memberof PtpRuntime
int ptp_pre_take_picture(struct PtpRuntime *r);
/// @brief Call after calling ptp_pre_take_picture - this time a picture will be taken.
-/// @memberof PtpRuntime
int ptp_take_picture(struct PtpRuntime *r);
/// @brief Open a new session - required for most commands
-/// @memberof PtpRuntime
int ptp_open_session(struct PtpRuntime *r);
-/// @memberof PtpRuntime
int ptp_close_session(struct PtpRuntime *r);
-/// @memberof PtpRuntime
int ptp_get_device_info(struct PtpRuntime *r, struct PtpDeviceInfo *di);
/// @brief Returns allocated array of storage IDs
/// call free() afterwards
int ptp_get_storage_ids(struct PtpRuntime *r, struct PtpArray **a);
-/// @memberof PtpRuntime
int ptp_init_capture(struct PtpRuntime *r, int storage_id, int object_format);
-/// @memberof PtpRuntime
int ptp_init_open_capture(struct PtpRuntime *r, int storage_id, int object_format);
-/// @memberof PtpRuntime
int ptp_terminate_open_capture(struct PtpRuntime *r, int trans);
-/// @memberof PtpRuntime
int ptp_get_storage_info(struct PtpRuntime *r, int id, struct PtpStorageInfo *si);
-/// @memberof PtpRuntime
int ptp_send_object_info(struct PtpRuntime *r, int storage_id, int handle, struct PtpObjectInfo *oi);
-/// @memberof PtpRuntime
int ptp_get_prop_value(struct PtpRuntime *r, int code);
-/// @memberof PtpRuntime
int ptp_set_prop_value(struct PtpRuntime *r, int code, int value);
-/// @memberof PtpRuntime
int ptp_set_prop_value_data(struct PtpRuntime *r, int code, void *data, int length);
-/// @memberof PtpRuntime
int ptp_get_prop_desc(struct PtpRuntime *r, int code, struct PtpPropDesc *pd);
/// @brief Gets a list of object handles in a storage device or folder.
@@ -84,48 +74,37 @@ int ptp_get_prop_desc(struct PtpRuntime *r, int code, struct PtpPropDesc *pd);
// @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
-/// @memberof PtpRuntime
int ptp_get_object_handles(struct PtpRuntime *r, int id, int format, int in, struct PtpArray **a);
-/// @memberof PtpRuntime
int ptp_get_object_info(struct PtpRuntime *r, uint32_t handle, struct PtpObjectInfo *oi);
-/// @memberof PtpRuntime
int ptp_move_object(struct PtpRuntime *r, int storage_id, int handle, int folder);
-/// @memberof PtpRuntime
int ptp_delete_object(struct PtpRuntime *r, int handle, int format_code);
/// @brief Raw JPEG data is accessible from ptp_get_payload()
/// @note Not thread safe.
-/// @memberof PtpRuntime
int ptp_get_thumbnail(struct PtpRuntime *r, int handle);
/// @note Not thread safe.
-/// @memberof PtpRuntime
int ptp_get_partial_object(struct PtpRuntime *r, uint32_t handle, int offset, int max);
/// @brief Download an object
-/// @memberof PtpRuntime
int ptp_get_object(struct PtpRuntime *r, int handle);
/// @brief Download an object from handle, to a local file (uses GetPartialObject)
-/// @memberof PtpRuntime
int ptp_download_object(struct PtpRuntime *r, int handle, FILE *stream, size_t max);
/// @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
-/// @memberof PtpRuntime
int ptp_get_all_known(struct PtpRuntime *r, struct PtpGenericEvent **s, int *length);
/// @note PTP/IP only
-/// @memberof PtpRuntime
int ptpip_init_events(struct PtpRuntime *r);
/// @note PTP/IP only
-/// @memberof PtpRuntime
int ptpip_init_command_request(struct PtpRuntime *r, const char *device_name);
// EOS Only functions - not for Canon point and shoot
@@ -175,4 +154,6 @@ int ptp_eos_fa_get_build_version(struct PtpRuntime *r, char *buffer, int max);
/// @returns enum PtpGeneralError, 0 for 'camera is busy', or the size of the image in the payload
int ptp_eos_get_liveview(struct PtpRuntime *r);
+/** @}*/
+
#endif
diff --git a/src/data.c b/src/data.c
index 58dcbeb..9563d6f 100644
--- a/src/data.c
+++ b/src/data.c
@@ -63,6 +63,7 @@ int ptp_get_prop_size(uint8_t *d, int type) {
return 0;
}
+// Cheap dumb function
int ptp_parse_data_u32(void *d, int type, int *out) {
uint8_t a;
uint16_t b;
@@ -80,8 +81,6 @@ int ptp_parse_data_u32(void *d, int type, int *out) {
ptp_read_u32(d, &c); (*out) = (int)c; return 4;
}
- // TODO: function to preserve signedness
-
// skip the array
return ptp_get_prop_size(d, type);
}
diff --git a/src/lua/lua.c b/src/lua/lua.c
index 9473d90..8c6d550 100644
--- a/src/lua/lua.c
+++ b/src/lua/lua.c
@@ -104,9 +104,9 @@ static int mylua_send_operation(lua_State *L) {
int rc = 0;
if (data_array == NULL) {
- rc = ptp_generic_send(r, &cmd);
+ rc = ptp_send(r, &cmd);
} else {
- rc = ptp_generic_send_data(r, &cmd, data_array, data_length);
+ rc = ptp_send_data(r, &cmd, data_array, data_length);
}
lua_newtable(L);
diff --git a/src/ptp.h b/src/ptp.h
index a5dc9f0..10fde26 100644
--- a/src/ptp.h
+++ b/src/ptp.h
@@ -1,3 +1,4 @@
+/** \file */
// This file describes Picture Transfer Protocol (ISO 15740)
// And many vendor opcodes, property codes, and event codes.