diff --git a/src/cl_backend.h b/src/cl_backend.h index 4c46001..21a2c0b 100644 --- a/src/cl_backend.h +++ b/src/cl_backend.h @@ -23,6 +23,7 @@ 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); diff --git a/src/lib.c b/src/lib.c index b789c50..b3af352 100644 --- a/src/lib.c +++ b/src/lib.c @@ -130,6 +130,7 @@ void ptp_mutex_lock(struct PtpRuntime *r) { pthread_mutex_lock(r->mutex); } +__attribute__((deprecated())) void ptp_mutex_keep_locked(struct PtpRuntime *r) { if (r->mutex == NULL) return; pthread_mutex_lock(r->mutex); diff --git a/src/libusb.c b/src/libusb.c index d849e9d..2fc8f65 100644 --- a/src/libusb.c +++ b/src/libusb.c @@ -21,9 +21,10 @@ struct LibUSBBackend { libusb_device_handle *handle; }; -// TODO: If this is accidentally called in the middle of a connection, it will cause a huge fault -static int ptp_comm_init(struct PtpRuntime *r) { - ptp_reset(r); +int ptp_comm_init(struct PtpRuntime *r) { + if (!r->io_kill_switch) { + ptp_panic("Connection is active\n"); + } // libusb 1.0 has no specificed limit for reads/writes r->max_packet_size = 512 * 4; @@ -33,6 +34,7 @@ static int ptp_comm_init(struct PtpRuntime *r) { memset(r->comm_backend, 0, sizeof(struct LibUSBBackend)); struct LibUSBBackend *backend = (struct LibUSBBackend *)r->comm_backend; + if (backend == NULL) ptp_panic(""); ptp_verbose_log("Initializing libusb...\n"); libusb_init(&(backend->ctx)); @@ -44,14 +46,10 @@ static int ptp_comm_init(struct PtpRuntime *r) { } struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) { - if (r->comm_backend == NULL) { - ptp_verbose_log("comm_backend is NULL\n"); - return NULL; - } + ptp_comm_init(r); if (!r->io_kill_switch) { - ptp_verbose_log("Connection is active\n"); - return NULL; + ptp_panic("Connection is active\n"); } ptp_mutex_lock(r); diff --git a/src/libwpd.c b/src/libwpd.c index bb73776..f519798 100644 --- a/src/libwpd.c +++ b/src/libwpd.c @@ -10,8 +10,6 @@ #include int ptp_comm_init(struct PtpRuntime *r) { - ptp_reset(r); - // We are not using low-level I/O operations, so this is never used r->max_packet_size = 512; @@ -32,7 +30,6 @@ int ptp_device_init(struct PtpRuntime *r) { } ptp_comm_init(r); - struct WpdStruct *wpd = (struct WpdStruct *)(r->comm_backend); if (wpd == NULL) return PTP_IO_ERR; @@ -69,13 +66,73 @@ int ptp_device_init(struct PtpRuntime *r) { return PTP_NO_DEVICE; } -// Unimplemented, don't use struct PtpDeviceEntry *ptpusb_device_list(struct PtpRuntime *r) { - ptp_panic("Unsupported"); + ptp_comm_init(r); + struct WpdStruct *wpd = (struct WpdStruct *)(r->comm_backend); + + ptp_mutex_lock(r); + + int num_devices = 0; + wchar_t **list = wpd_get_devices(wpd, &num_devices); + if (num_devices == 0) { + ptp_mutex_unlock(r); + return NULL; + } + + struct PtpDeviceEntry *curr_ent = calloc(1, sizeof(struct PtpDeviceEntry)); + + struct PtpDeviceEntry *new_list = curr_ent; + + for (int i = 0; i < num_devices; i++) { + if (i != 0) { + struct PtpDeviceEntry *next_ent = calloc(1, sizeof(struct PtpDeviceEntry)); + next_ent->prev = curr_ent; + next_ent->next = NULL; + curr_ent->next = next_ent; + curr_ent = next_ent; + } else { + curr_ent->prev = NULL; + } + + struct LibWPDDescriptor d; + int rc = wpd_parse_io_path(list[i], &d); + if (rc) ptp_panic("wpd_parse_io_path"); + + curr_ent->product_id = d.product_id; + curr_ent->vendor_id = d.vendor_id; + curr_ent->device_handle_ptr = list[i]; + } + + ptp_mutex_unlock(r); + return new_list; } int ptp_device_open(struct PtpRuntime *r, struct PtpDeviceEntry *entry) { - ptp_panic("Unsupported"); + ptp_mutex_lock(r); + struct WpdStruct *wpd = (struct WpdStruct *)(r->comm_backend); + + int ret = wpd_open_device(wpd, entry->device_handle_ptr); + if (ret) { + ptp_mutex_unlock(r); + return PTP_OPEN_FAIL; + } + + int type = wpd_get_device_type(wpd); + if (type == WPD_DEVICE_TYPE_CAMERA) { + r->io_kill_switch = 0; + r->operation_kill_switch = 0; + ptp_mutex_unlock(r); + return 0; + } + + ptp_verbose_log("Device is not a camera!\n"); + + ptp_mutex_unlock(r); + return PTP_OPEN_FAIL; +} + +void ptpusb_free_device_list_entry(void *handle) { + } int ptp_cmd_write(struct PtpRuntime *r, void *to, int length) { diff --git a/src/libwpd.h b/src/libwpd.h deleted file mode 100644 index 8e754a9..0000000 --- a/src/libwpd.h +++ /dev/null @@ -1,80 +0,0 @@ -// Header for libwpd -#ifndef PTP_WPD_H -#define PTP_WPD_H - -#include -#include - -// From Microsoft -typedef enum tagWPD_DEVICE_TYPES { - WPD_DEVICE_TYPE_GENERIC = 0, - WPD_DEVICE_TYPE_CAMERA = 1, - WPD_DEVICE_TYPE_MEDIA_PLAYER = 2, - WPD_DEVICE_TYPE_PHONE = 3, - WPD_DEVICE_TYPE_VIDEO = 4, - WPD_DEVICE_TYPE_PERSONAL_INFORMATION_MANAGER = 5, - WPD_DEVICE_TYPE_AUDIO_RECORDER = 6 -}WPD_DEVICE_TYPES; - -struct LibWPDPtpCommand { - int code; - uint32_t params[5]; - int param_length; - int data_length; -}; - -/// @brief Initialize thread -int wpd_init(int verbose, wchar_t *app_name); - -// Private, implemented by libwpd -struct WpdStruct { - void *dev; - void *results; - void *values; -}; - -/// @brief Create new WpdStruct object -struct WpdStruct *wpd_new(); - -/// @brief Recieve an array of wide strings. Length is set in num_devices. Each string holds the device -/// ID, similar to Linux /dev/bus/usb/001 -wchar_t **wpd_get_devices(struct WpdStruct *wpd, int *num_devices); - -/// @brief Initialize the WpdStruct with a new connection to the selected device ID wide string -int wpd_open_device(struct WpdStruct *wpd, wchar_t *device_id); - -/// @brief Close the device currently connected -int wpd_close_device(struct WpdStruct* wpd); - -/// @brief Returns enum WPD_DEVICE_TYPES -int wpd_get_device_type(struct WpdStruct *wpd); - -/// @brief Generic USB writing command. Will store all sent data into a buffer, which will be processed when wpd_ptp_cmd_read is called. -int wpd_ptp_cmd_write(struct WpdStruct *wpd, void *data, int size); - -/// @brief Processes all PTP packets sent through wpd_ptp_cmd_write, and performs operations. Will then store all results in the 'out' buffer. -/// Every time this function is called, it will return data from the 'out' buffer, as requested by `size`. -int wpd_ptp_cmd_read(struct WpdStruct *wpd, void *data, int size); - - -// Manual old API: - - -/// @brief Send command packet with no data packet, but expect data packet (device may not send data packet, that is fine) -/// Data packet should be recieved with wpd_receive_do_data -int wpd_receive_do_command(struct WpdStruct *wpd, struct LibWPDPtpCommand *cmd); - -/// @brief Get data payload from device, if any. -/// @note cmd struct will be filled with the response packet -int wpd_receive_do_data(struct WpdStruct *wpd, struct LibWPDPtpCommand *cmd, uint8_t *buffer, int length); - -/// @brief Send command packet with data phase, with no data packet response from device. Call wpd_send_do_data to get the response -/// and data packets -int wpd_send_do_command(struct WpdStruct* wpd, struct LibWPDPtpCommand* cmd, int length); - -/// @brief Send the actual data packet, if wpd_send_do_command was called with length != 0 -/// @note cmd struct will be filled with the response packet -int wpd_send_do_data(struct WpdStruct* wpd, struct LibWPDPtpCommand* cmd, uint8_t *buffer, int length); - -#endif - diff --git a/src/lua/doc.lua b/src/lua/doc.lua new file mode 100755 index 0000000..df6b08a --- /dev/null +++ b/src/lua/doc.lua @@ -0,0 +1,23 @@ +--- Runs PTP_OC_GetDeviceInfo and returns a structure +--- @return table +function ptp.getDeviceInfo() +end +--- Connect to the first available PTP device +--- @return number +function ptp.connect() +end +--- Perform a PTP operation with custom options +--- @param params table have a list of up to 5 integer parameters. +--- @param payload table payload to be sent to device. +--- @return table structure such as {"error": 0, "code": 0x2001, "payload": [0, 1, 2]} +function ptp.sendOperation(opcode, params, payload) +end +--- Run PTP_OC_SetDevicePropValue +--- @param propCode number PTP_DPC_* +--- @param value number value to be set, as a 32 bit integer +function ptp.setProperty(propCode, value) +end +--- Trigger the camera to take a picture +--- @return number Camlib error code +function ptp.takePicture() +end \ No newline at end of file diff --git a/src/lua/lua.c b/src/lua/lua.c index be619f9..9473d90 100644 --- a/src/lua/lua.c +++ b/src/lua/lua.c @@ -32,10 +32,15 @@ static int mylua_set_property(lua_State *L) { static int mylua_device_info(lua_State *L) { struct PtpRuntime *r = luaptp_get_runtime(L); - if (r->di == NULL) return 1; + struct PtpDeviceInfo di; + int rc = ptp_get_device_info(r, &di); + if (rc) { + lua_pushinteger(L, rc); + return 1; + } char buffer[4096]; - ptp_device_info_json(r->di, buffer, sizeof(buffer)); + ptp_device_info_json(&di, buffer, sizeof(buffer)); lua_json_decode(L, buffer, strlen(buffer)); diff --git a/src/lua/runtime.c b/src/lua/runtime.c index 2d96f15..0b416a4 100644 --- a/src/lua/runtime.c +++ b/src/lua/runtime.c @@ -15,7 +15,7 @@ int cam_lua_setup(lua_State *L); int luaopen_cjson(lua_State *l); -static char error_buffer[64]; +static char error_buffer[512] = {0}; static struct CamLuaTasks { int tasks; @@ -62,13 +62,13 @@ static int get_task_id(lua_State *L) { static int lua_script_print(lua_State *L) { const char *str = luaL_checkstring(L, 1); - ptp_verbose_log("Lua: %s\n", str); + ptp_verbose_log("%s\n", str); return 1; } static int lua_script_toast(lua_State *L) { const char *str = luaL_checkstring(L, 1); - ptp_verbose_log("Lua: %s\n", str); + ptp_verbose_log("%s\n", str); return 1; }