diff --git a/lua/lua.c b/lua/lua.c index e3d1060..43226d8 100644 --- a/lua/lua.c +++ b/lua/lua.c @@ -67,7 +67,6 @@ static int mylua_send_operation(lua_State *L) { if (!lua_istable(L, 2)) { return luaL_error(L, "arg2 expected array"); - return -1; } struct PtpCommand cmd; @@ -107,6 +106,10 @@ static int mylua_send_operation(lua_State *L) { lua_newtable(L); + lua_pushstring(L, "error"); + lua_pushinteger(L, rc); + lua_settable(L, -3); + lua_pushstring(L, "code"); lua_pushinteger(L, ptp_get_return_code(r)); lua_settable(L, -3); diff --git a/lua/runtime.c b/lua/runtime.c index 4fcaf19..2d96f15 100644 --- a/lua/runtime.c +++ b/lua/runtime.c @@ -13,11 +13,14 @@ // Must be provided int cam_lua_setup(lua_State *L); +int luaopen_cjson(lua_State *l); + static char error_buffer[64]; static struct CamLuaTasks { int tasks; struct lua_State *L[MAX_LUA_CONCURRENT]; + int state[MAX_LUA_CONCURRENT]; }lua_tasks = {0}; const char *cam_lua_get_error() { @@ -49,6 +52,14 @@ int lua_script_run_loop(int id) { return 0; } +static int get_task_id(lua_State *L) { + for (int i = 0; i < lua_tasks.tasks; i++) { + if (L == lua_tasks.L[i]) return i; + } + + return -1; +} + static int lua_script_print(lua_State *L) { const char *str = luaL_checkstring(L, 1); ptp_verbose_log("Lua: %s\n", str); @@ -75,12 +86,21 @@ static int mylua_itoa(lua_State* L) { return 1; } +int lua_mark_dead(lua_State *L) { + int id = get_task_id(L); + if (id == -1) abort(); + lua_tasks.state[id] = 1; + return 1; +} + lua_State *cam_lua_state() { lua_State *L = luaL_newstate(); luaopen_ptp(L); luaopen_base(L); + luaL_requiref(L, "json", luaopen_cjson, 1); luaL_requiref(L, "ptp", luaopen_ptp, 1); lua_register(L, "print", lua_script_print); + lua_register(L, "exit", lua_mark_dead); lua_register(L, "setStatusText", lua_script_set_status); cam_lua_setup(L); return L; @@ -110,15 +130,28 @@ int cam_run_lua_script(const char *buffer) { } lua_State *cam_new_task(int *id) { + (*id) = -1; if (lua_tasks.tasks >= MAX_LUA_CONCURRENT) { - return NULL; + for (int i = 0; i < lua_tasks.tasks; i++) { + if (lua_tasks.state[i] == 1) { + (*id) = i; + lua_close(lua_tasks.L[i]); + lua_tasks.L[i] = 0; + break; + } + } + if ((*id) == -1) { + return NULL; + } + } else { + (*id) = lua_tasks.tasks; + lua_tasks.tasks++; } lua_State *L = cam_lua_state(); - *id = lua_tasks.tasks; - lua_tasks.L[lua_tasks.tasks] = L; - lua_tasks.tasks++; + lua_tasks.L[(*id)] = L; + lua_tasks.state[(*id)] = 0; return L; } diff --git a/src/camlib.h b/src/camlib.h index 94184e5..b6d5dbc 100644 --- a/src/camlib.h +++ b/src/camlib.h @@ -28,7 +28,7 @@ void ptp_verbose_log(char *fmt, ...); void ptp_panic(char *fmt, ...); // 4mb recommended default buffer size -#define CAMLIB_DEFAULT_SIZE 8000000 +#define CAMLIB_DEFAULT_SIZE 1000000 // Transparency pixel used in liveview processor. Will be packed as RGB uint32 // uncompressed array of pixels in little-endian. This will be used as the first byte. diff --git a/src/cl_ops.h b/src/cl_ops.h index f0f28a1..ce24492 100644 --- a/src/cl_ops.h +++ b/src/cl_ops.h @@ -44,6 +44,8 @@ int ptp_delete_object(struct PtpRuntime *r, int handle, int format_code); 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); +/// @brief Download an object +int ptp_get_object(struct PtpRuntime *r, int handle); /// @brief Download an object from handle, to a local file (uses GetPartialObject) 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 diff --git a/src/lib.c b/src/lib.c index 74b8e70..3132b02 100644 --- a/src/lib.c +++ b/src/lib.c @@ -105,6 +105,9 @@ void ptpusb_free_device_list(struct PtpDeviceEntry *e) { } int ptp_buffer_resize(struct PtpRuntime *r, size_t size) { + if (size < r->data_length) { + ptp_panic("You cannot downside the data buffer"); + } // realloc with a little extra space to minimize reallocs later on static int extra = 100; ptp_verbose_log("Extending IO buffer to %X\n", size + extra); diff --git a/src/packet.c b/src/packet.c index 23afa54..5851c29 100644 --- a/src/packet.c +++ b/src/packet.c @@ -187,6 +187,7 @@ int ptpip_data_end_packet(struct PtpRuntime *r, void *data, int data_length) { // Generate a USB-only BulkContainer packet int ptpusb_bulk_packet(struct PtpRuntime *r, struct PtpCommand *cmd, int type) { + if (cmd->param_length > 5) ptp_panic("cmd->param_length more than 5"); struct PtpBulkContainer bulk; int size = 12 + (sizeof(uint32_t) * cmd->param_length); diff --git a/src/transport.c b/src/transport.c index 9658313..109fcc9 100644 --- a/src/transport.c +++ b/src/transport.c @@ -182,22 +182,22 @@ int ptpusb_read_all_packets(struct PtpRuntime *r) { // TODO: unsigned/unsigned compare if (read >= r->data_length - r->max_packet_size) { - ptp_verbose_log("recieve_bulk_packets: Not enough memory\n"); - return PTP_OUT_OF_MEM; + rc = ptp_buffer_resize(r, read + r->max_packet_size); + if (rc) return rc; } if (rc != r->max_packet_size) { - ptp_verbose_log("recieve_bulk_packets: Read %d bytes\n", read); + ptp_verbose_log("receive_bulk_packets: Read %d bytes\n", read); struct PtpBulkContainer *c = (struct PtpBulkContainer *)(r->data); // Read the response packet if only a data packet was sent (as per spec, always is 12 bytes) if (c->type == PTP_PACKET_TYPE_DATA) { rc = ptp_cmd_read(r, r->data + read, r->max_packet_size); - ptp_verbose_log("recieve_bulk_packets: Recieved response packet: %d\n", rc); + ptp_verbose_log("receive_bulk_packets: Received response packet: %d\n", rc); read += rc; } - ptp_verbose_log("recieve_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); + ptp_verbose_log("receive_bulk_packets: Return code: 0x%X\n", ptp_get_return_code(r)); return read; }