Changeset 1101


Ignore:
Timestamp:
03/23/11 04:41:29 (2 years ago)
Author:
reyalP
Message:

ptp script communication improvements, see http://chdk.setepontos.com/index.php?topic=4338.msg62725#msg62725
NOTE PTP protocol is updated, old clients will not be completely compatible

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/core/action_stack.c

    r1050 r1101  
    169169} 
    170170 
     171// handle initializing and checking a timeout value on the stack 
     172// p is the how far up the stack the timout value is 
     173// returns zero if the timeout has not expired, 1 if it has 
     174// does not pop the delay value off the stack or clear the delay value 
     175int action_process_delay(int p) 
     176{ 
     177    int t = get_tick_count(); 
     178    // FIXME take care if overflow occurs 
     179    if (action_stacks[active_stack]->delay_target_ticks == 0) 
     180    { 
     181        /* setup timer */ 
     182        action_stacks[active_stack]->delay_target_ticks = t+action_get_prev(p); 
     183        return 0; 
     184    } 
     185    if (action_stacks[active_stack]->delay_target_ticks <= t) 
     186    { 
     187        return 1; 
     188    } 
     189    return 0; 
     190} 
     191 
     192void action_clear_delay(void) 
     193{ 
     194    action_stacks[active_stack]->delay_target_ticks = 0; 
     195} 
     196 
    171197// Defines some standard operations. Returns false if it could not process anything. 
    172198// Can only be called from an action stack 
     
    188214        break; 
    189215    case AS_SLEEP: 
    190         t = get_tick_count(); 
    191         // FIXME take care if overflow occurs 
    192         if (action_stacks[active_stack]->delay_target_ticks == 0) 
    193         { 
    194             /* setup timer */ 
    195             action_stacks[active_stack]->delay_target_ticks = t+action_get_prev(2); 
    196         } 
    197         else 
    198         { 
    199             if (action_stacks[active_stack]->delay_target_ticks <= t) 
    200             { 
    201                 action_stacks[active_stack]->delay_target_ticks = 0; 
    202  
    203                 // pop sleep op. 
    204                 action_pop(); 
    205                 action_pop(); 
    206             } 
     216        if(action_process_delay(2)) 
     217        { 
     218            action_clear_delay(); 
     219            action_pop(); 
     220            action_pop(); 
    207221        } 
    208222        break; 
     
    239253        break; 
    240254    case AS_WAIT_CLICK: 
    241         t = get_tick_count(); 
    242         if (action_stacks[active_stack]->delay_target_ticks == 0) 
    243         { 
    244             /* setup timer */ 
    245             action_stacks[active_stack]->delay_target_ticks = t+((action_get_prev(2))?action_get_prev(2):86400000); 
    246         } 
    247         else 
    248         { 
    249             kbd_last_clicked = kbd_get_clicked_key(); 
    250             if (kbd_last_clicked || (action_stacks[active_stack]->delay_target_ticks <= t)) 
    251             { 
    252                 if (!kbd_last_clicked)  
    253                     kbd_last_clicked=0xFFFF; 
    254              
    255                 action_stacks[active_stack]->delay_target_ticks = 0; 
    256  
    257                 // pop up 
    258                 action_pop(); 
    259                 action_pop(); 
    260             } 
     255        if(action_process_delay(2) || (kbd_last_clicked = kbd_get_clicked_key())) 
     256        { 
     257            if (!kbd_last_clicked)  
     258                kbd_last_clicked=0xFFFF; 
     259            action_clear_delay(); 
     260            action_pop(); 
     261            action_pop(); 
    261262        } 
    262263        break; 
  • trunk/core/action_stack.h

    r1032 r1101  
    1919    AS_WAIT_CLICK, 
    2020    AS_SCRIPT_RUN, 
    21     AS_MOTION_DETECTOR 
     21    AS_MOTION_DETECTOR, 
     22    AS_SCRIPT_READ_USB_MSG, // params: timeout 
     23    AS_SCRIPT_WRITE_USB_MSG, // params: timeout, msg 
    2224}; 
    2325 
     
    3234void action_wait_for_click(int timeout); 
    3335void action_pop(); 
     36int action_process_delay(int p); 
     37void action_clear_delay(void); 
    3438long action_get_prev(int p); 
    3539int action_stack_standard(long p); 
  • trunk/core/luascript.c

    r1036 r1101  
    1515#include "action_stack.h" 
    1616#include "motion_detector.h" 
     17#include "ptp.h" 
    1718 
    1819#include "../lib/lua/lstate.h"  // for L->nCcalls, baseCcalls 
     
    2021lua_State* L; 
    2122lua_State* Lt; 
    22 int lua_keep_result; 
    23  
    24 void *lua_consume_result() 
    25 { 
    26   lua_State* r = L; 
     23 
     24static int lua_script_is_ptp; 
     25 
     26static int yield_hook_enabled; 
     27 
     28static void lua_script_disable_yield_hook(void) { 
     29    yield_hook_enabled = 0; 
     30} 
     31static void lua_script_enable_yield_hook(void) { 
     32    yield_hook_enabled = 1; 
     33} 
     34 
     35#ifdef CAM_CHDK_PTP 
     36// create a ptp message from the given stack index 
     37// incompatible types will return a TYPE_UNSUPPORTED message 
     38static ptp_script_msg *lua_create_usb_msg( lua_State* L, int index, unsigned msgtype) { 
     39    // TODO maybe we should just pass the lua type constants 
     40    unsigned datatype, datasize = 4; 
     41    int ivalue = 0; 
     42    void *data = &ivalue; 
     43    int ltype = lua_type(L,index); 
     44    switch(ltype) { 
     45        case LUA_TNONE: 
     46            return NULL; // nothing on the stack, no message generated 
     47        break; 
     48        case LUA_TNIL: 
     49            datatype = PTP_CHDK_TYPE_NIL; 
     50        break; 
     51        case LUA_TBOOLEAN: 
     52            datatype = PTP_CHDK_TYPE_BOOLEAN; 
     53            ivalue = lua_toboolean(L,index); 
     54        break; 
     55        case LUA_TNUMBER: 
     56            datatype = PTP_CHDK_TYPE_INTEGER; 
     57            ivalue = lua_tonumber(L,index); 
     58        break; 
     59        case LUA_TSTRING: 
     60            datatype = PTP_CHDK_TYPE_STRING; 
     61            data = (char *)lua_tolstring(L,index,&datasize); 
     62        break; 
     63        // TODO this converts to a string and returns as STRING, format as described at  
     64        // http://chdk.setepontos.com/index.php?topic=4338.msg62606#msg62606 
     65        // for compatibility with current PTPCAM/PTPCAMGUI implementation 
     66        // later we should switch to a proper serialized table with it's own return type 
     67        case LUA_TTABLE:  
     68            lua_script_disable_yield_hook(); // don't want to yeild while converting 
     69            lua_getglobal(L, "usb_msg_table_to_string"); // push function 
     70            lua_pushvalue(L, index); // copy specified index to top of stack 
     71            lua_pcall(L,1,1,0); // this will leave an error message as a string on the stack if call fails 
     72            lua_script_enable_yield_hook(); 
     73            // an empty table will be returned as an empty string 
     74            // a non-string should never show up here 
     75            if ( !(lua_isstring(L,-1) /*&& ( lua_objlen(L,-1) > 0 )*/)) {  
     76                return NULL; 
     77            } 
     78            datatype = PTP_CHDK_TYPE_STRING; 
     79            data = (char *)lua_tolstring(L,-1,&datasize); 
     80            lua_pop(L,1); 
     81        break; 
     82        default: 
     83            datatype = PTP_CHDK_TYPE_UNSUPPORTED; 
     84            data = (char *)lua_typename(L,ltype); // return type name as message data 
     85            datasize = strlen(data); 
     86    } 
     87    return ptp_script_create_msg(msgtype,datatype,datasize,data); 
     88} 
     89 
     90void lua_script_error_ptp(int runtime, const char *err) { 
     91    if(runtime) { 
     92        ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_RUN, err); 
     93        script_end(); 
     94    } else { 
     95        ptp_script_write_error_msg(PTP_CHDK_S_ERRTYPE_COMPILE, err); 
     96        lua_script_reset(); 
     97    } 
     98} 
     99#endif 
     100 
     101void lua_script_reset() 
     102{ 
     103  lua_close( L ); 
    27104  L = 0; 
    28   return r; 
    29 } 
    30  
    31 void lua_script_reset() 
    32 { 
    33   if ( !lua_keep_result ) 
    34   { 
    35     lua_close( L ); 
    36     L = 0; 
    37   } 
    38   Lt = 0; 
    39105} 
    40106 
    41107static void lua_count_hook(lua_State *L, lua_Debug *ar) 
    42108{ 
    43   if( L->nCcalls <= L->baseCcalls ) 
     109  if( L->nCcalls <= L->baseCcalls && yield_hook_enabled ) 
    44110    lua_yield( L, 0 ); 
    45111} 
    46112 
    47 int lua_script_start( char const* script ) 
    48 { 
    49   lua_keep_result = 0; 
     113void lua_script_error(lua_State *Lt,int runtime) 
     114{ 
     115    const char *err = lua_tostring( Lt, -1 ); 
     116    script_console_add_line( err ); 
     117    if(lua_script_is_ptp) { 
     118#ifdef CAM_CHDK_PTP 
     119        lua_script_error_ptp(runtime,err); 
     120#endif 
     121    } else { 
     122        if(runtime) { 
     123            if(conf.debug_lua_restart_on_error) { 
     124                lua_script_reset(); 
     125                script_start_gui(0); 
     126            } else { 
     127                script_wait_and_end(); 
     128            } 
     129        } else { 
     130            script_print_screen_end(); 
     131            script_wait_and_end(); 
     132        } 
     133    } 
     134} 
     135 
     136 
     137// TODO more stuff from script.c should be moved here 
     138void lua_script_finish(lua_State *L)  
     139{ 
     140#ifdef CAM_CHDK_PTP 
     141    if(lua_script_is_ptp) { 
     142        // send all return values as RET messages 
     143        int i,end = lua_gettop(L); 
     144        for(i=1;i<=end; i++) { 
     145            // if the queue is full return values will be silently discarded 
     146            // incompatible types will be returned as TYPE_UNSUPPORTED to preserve expected number and order of return values 
     147            ptp_script_write_msg(lua_create_usb_msg(L,i,PTP_CHDK_S_MSGTYPE_RET));  
     148        } 
     149    } 
     150#endif 
     151} 
     152 
     153int lua_script_start( char const* script, int ptp ) 
     154{ 
     155  lua_script_is_ptp = ptp; 
    50156  L = lua_open(); 
    51157  luaL_openlibs( L ); 
     
    55161  lua_setfield( L, LUA_REGISTRYINDEX, "Lt" ); 
    56162  if( luaL_loadstring( Lt, script ) != 0 ) { 
    57     script_console_add_line( lua_tostring( Lt, -1 ) ); 
    58     lua_script_reset(); 
     163    lua_script_error(Lt,0); 
    59164    return 0; 
    60165  } 
    61166  lua_sethook(Lt, lua_count_hook, LUA_MASKCOUNT, 1000 ); 
     167  lua_script_enable_yield_hook(); 
    62168  return 1; 
    63169} 
     
    13871493        return 1; 
    13881494} 
     1495 
     1496#ifdef CAM_CHDK_PTP 
     1497/* 
     1498msg = read_usb_msg([timeout]) 
     1499read a message from the CHDK ptp interface. 
     1500Returns the next available message as a string, or nil if no messages are available 
     1501If timeout is given and not zero, wait until a message is available or timeout expires 
     1502*/ 
     1503static int luaCB_read_usb_msg( lua_State* L ) 
     1504{ 
     1505  int timeout = luaL_optnumber( L, 1, 0 ); 
     1506  if(timeout) { 
     1507    action_push(timeout); 
     1508    action_push(AS_SCRIPT_READ_USB_MSG); 
     1509    return lua_yield( L, 0 ); 
     1510  } 
     1511  ptp_script_msg *msg = ptp_script_read_msg(); 
     1512  if(msg) { 
     1513    lua_pushlstring(L,msg->data,msg->size); 
     1514    return 1; 
     1515  } 
     1516  lua_pushnil(L); 
     1517  return 1; 
     1518} 
     1519 
     1520/* 
     1521status = write_usb_msg(msg,[timeout]) 
     1522writes a message to the CHDK ptp interface 
     1523msg may be nil, boolean, number, string or table (table has some restrictions, will be converted to string) 
     1524returns true if the message was queued successfully, otherwise false 
     1525if timeout is set and not zero, wait until message is written or timeout expires 
     1526NOTE strings will not include a terminating NULL, must be handled by recipient 
     1527*/ 
     1528static int luaCB_write_usb_msg( lua_State* L ) 
     1529{ 
     1530  ptp_script_msg *msg; 
     1531  int timeout = luaL_optnumber( L, 2, 0 ); 
     1532  // TODO would it be better to either ignore this or return nil ? 
     1533  // a write_usb_msg(function_which_returns_no_value()) is an error in this case 
     1534  // replacing with nil might be more luaish 
     1535  if(lua_gettop(L) < 1) { 
     1536    return luaL_error(L,"missing argument"); 
     1537  } 
     1538  msg=lua_create_usb_msg(L,1,PTP_CHDK_S_MSGTYPE_USER); 
     1539  // for user messages, trying to create a message from an incompatible type throws an error 
     1540  if(msg->subtype == PTP_CHDK_TYPE_UNSUPPORTED) { 
     1541    free(msg); 
     1542    return luaL_error(L,"unsupported type"); 
     1543  } 
     1544  if(!msg) { 
     1545    return luaL_error(L,"failed to create message"); 
     1546  } 
     1547  if(timeout) { 
     1548    action_push(timeout); 
     1549    action_push((int)msg); 
     1550    action_push(AS_SCRIPT_WRITE_USB_MSG); 
     1551    return lua_yield( L, 0 ); 
     1552  } 
     1553  lua_pushboolean(L,ptp_script_write_msg(msg));  
     1554  return 1; 
     1555} 
     1556#endif 
    13891557 
    13901558void register_lua_funcs( lua_State* L ) 
     
    15541722#endif 
    15551723   FUNC(reboot); 
    1556 } 
     1724#ifdef CAM_CHDK_PTP 
     1725   FUNC(read_usb_msg); 
     1726   FUNC(write_usb_msg); 
     1727   luaL_dostring(L,"function usb_msg_table_to_string(t)" 
     1728                    " local v2s=function(v)" 
     1729                        " local t=type(v)" 
     1730                        " if t=='string' then return v end" 
     1731                        " if t=='number' or t=='boolean' or t=='nil' then return tostring(v) end" 
     1732                        " return '' end" 
     1733                    " local r=''" 
     1734                    " for k,v in pairs(t) do" 
     1735                        " local s,vs=''" 
     1736                        " if type(v)=='table' then" 
     1737                            " for i=1,table.maxn(v) do" 
     1738                            " s=s..'\\t'..v2s(v[i]) end" 
     1739                        " else" 
     1740                            " vs=v2s(v)" 
     1741                            " if #vs then s=s..'\\t'..vs end" 
     1742                        " end" 
     1743                        " vs=v2s(k)" 
     1744                        " if #vs>0 and #s>0 then r=r..vs..s..'\\n' end" 
     1745                    " end" 
     1746                    " return r" 
     1747                   " end"); 
     1748 
     1749#endif 
     1750} 
  • trunk/core/luascript.h

    r1021 r1101  
    44#include "lua.h" 
    55 
    6 void *lua_consume_result(); 
    76void lua_script_reset(); 
    8 int lua_script_start( char const* script ); 
     7int lua_script_start( char const* script,int is_ptp ); 
     8void lua_script_error( lua_State* L,int runtime ); 
     9void lua_script_finish( lua_State* L ); 
    910extern void register_lua_funcs( lua_State* L ); 
    1011// run the "restore" function at the end of a script 
     
    1314extern lua_State* L; 
    1415extern lua_State* Lt; 
    15 extern int lua_keep_result; 
    1616 
    1717#endif 
  • trunk/core/ptp.c

    r1078 r1101  
    1414#include "script.h" 
    1515#include "action_stack.h" 
    16  
    17 static lua_State *get_lua_thread(lua_State *L) 
    18 { 
    19   lua_State *Lt; 
    20  
    21   lua_getfield(L,LUA_REGISTRYINDEX,"Lt"); 
    22   Lt = lua_tothread(L,-1); 
    23   lua_pop(L,1); 
    24  
    25   return Lt; 
    26 } 
     16// process id for scripts, increments before each attempt to run script 
     17// does not handle wraparound 
     18static unsigned script_run_id;  
    2719#endif 
    2820 
     
    6456 
    6557  return 1; 
     58} 
     59 
     60// camera will shut down if you ignore a recv data phase 
     61static void flush_recv_ptp_data(ptp_data *data,int size) { 
     62  char *buf; 
     63  buf = malloc((size > buf_size) ? buf_size:size); 
     64  if(!buf) // buf_size should always be less then available memory 
     65    return; 
     66  while ( size > 0 ) 
     67  { 
     68    if ( size >= buf_size ) 
     69    { 
     70      recv_ptp_data(data,buf,buf_size); 
     71      size -= buf_size; 
     72    } else { 
     73      recv_ptp_data(data,buf,size); 
     74      size = 0; 
     75    } 
     76  } 
     77  free(buf); 
    6678} 
    6779 
     
    94106} 
    95107 
     108#ifdef OPT_LUA 
     109// TODO this could be a generic ring buffer of words 
     110#define PTP_SCRIPT_MSG_Q_LEN 16 
     111typedef struct { 
     112  unsigned r; // index of current read value 
     113  unsigned w; // index of next write value, if w == r, empty TODO "full" currently wastes a slot 
     114  ptp_script_msg *q[PTP_SCRIPT_MSG_Q_LEN]; 
     115} ptp_script_msg_q; 
     116 
     117// TODO it would be better to allocate these only when needed 
     118ptp_script_msg_q msg_q_in; // messages to pc from script 
     119ptp_script_msg_q msg_q_out; // messages to script from pc 
     120 
     121unsigned script_msg_q_next(unsigned i) { 
     122  if(i == PTP_SCRIPT_MSG_Q_LEN - 1) { 
     123    return 0; 
     124  } 
     125  return i+1; 
     126} 
     127 
     128unsigned script_msg_q_full(ptp_script_msg_q *q) { 
     129  return (script_msg_q_next(q->w) == q->r); 
     130} 
     131 
     132unsigned script_msg_q_empty(ptp_script_msg_q *q) { 
     133  return (q->w == q->r); 
     134} 
     135 
     136int enqueue_script_msg(ptp_script_msg_q *q,ptp_script_msg *msg) { 
     137  unsigned w = script_msg_q_next(q->w); 
     138  if(w == q->r) { 
     139    return 0; 
     140  } 
     141  // zero size messages don't make any sense 
     142  if(msg == NULL || msg->size == 0) { 
     143    return 0; 
     144  } 
     145  q->q[q->w] = msg; 
     146  q->w = w; 
     147  return 1; 
     148} 
     149 
     150ptp_script_msg* dequeue_script_msg(ptp_script_msg_q *q) { 
     151  ptp_script_msg *msg; 
     152  if(script_msg_q_empty(q)) { 
     153    return NULL; 
     154  } 
     155  msg = q->q[q->r]; 
     156  q->r = script_msg_q_next(q->r); 
     157  return msg; 
     158} 
     159 
     160// public interface for script 
     161ptp_script_msg* ptp_script_create_msg(unsigned type, unsigned subtype, unsigned datasize, const void *data) { 
     162  ptp_script_msg *msg; 
     163  if(!datasize) { 
     164    return NULL; 
     165  } 
     166  msg = malloc(sizeof(ptp_script_msg) + datasize); 
     167  msg->size = datasize; 
     168  msg->type = type; 
     169  msg->subtype = subtype; 
     170  // caller may fill in data themselves 
     171  if(data) { 
     172      memcpy(msg->data,data,msg->size); 
     173  } 
     174  return msg; 
     175} 
     176 
     177int ptp_script_write_msg(ptp_script_msg *msg) { 
     178  msg->script_id = script_run_id; 
     179  return enqueue_script_msg(&msg_q_out,msg); 
     180} 
     181 
     182ptp_script_msg* ptp_script_read_msg(void) { 
     183  ptp_script_msg *msg; 
     184  while(1) { 
     185    msg = dequeue_script_msg(&msg_q_in);  
     186    // no messages 
     187    if(!msg) { 
     188        return NULL; 
     189    } 
     190    // does message belong to our script 
     191    if(!msg->script_id || msg->script_id == script_run_id) { 
     192      return msg; 
     193    } else { 
     194    // no: discard and keep looking 
     195      free(msg); 
     196    } 
     197  } 
     198} 
     199int ptp_script_write_error_msg(unsigned errtype, const char *err) { 
     200  if(script_msg_q_full(&msg_q_out)) { 
     201    return 0; 
     202  } 
     203  ptp_script_msg *msg = ptp_script_create_msg(PTP_CHDK_S_MSGTYPE_ERR,errtype,strlen(err),err); 
     204  if(!msg) { 
     205    return 0; 
     206  } 
     207  return ptp_script_write_msg(msg); 
     208} 
     209 
     210#endif 
     211 
    96212static int handle_ptp( 
    97213               int h, ptp_data *data, int opcode, int sess_id, int trans_id, 
     
    100216  static union { 
    101217    char *str; 
    102 #ifdef OPT_LUA 
    103     lua_State *lua_state; 
    104 #endif 
    105218  } temp_data; 
    106219  static int temp_data_kind = 0; // 0: nothing, 1: ascii string, 2: lua object 
     
    115228  ptp.num_param = 0; 
    116229   
     230  // TODO calling this on every PTP command is not good, 
     231  // since it figures out free memory by repeatedly malloc'ing! 
    117232  buf_size=core_get_free_memory()>>1; 
    118233 
     
    139254#ifdef OPT_SCRIPTING 
    140255      ptp.param1 |= script_is_running()?PTP_CHDK_SCRIPT_STATUS_RUN:0; 
     256#ifdef OPT_LUA 
     257      ptp.param1 |= (!script_msg_q_empty(&msg_q_out))?PTP_CHDK_SCRIPT_STATUS_MSG:0; 
     258#endif 
    141259#endif 
    142260      break; 
     
    210328          l = temp_data_extra; 
    211329        } 
    212 #ifdef OPT_LUA 
    213         else { // temp_data_kind == 2 
    214           s = lua_tolstring(get_lua_thread(temp_data.lua_state),1,&l); 
    215         } 
    216 #endif 
    217330 
    218331        if ( !send_ptp_data(data,s,l) ) 
     
    227340          free(temp_data.str); 
    228341        } 
    229 #ifdef OPT_LUA 
    230         else if ( temp_data_kind == 2 ) 
    231         { 
    232           lua_close(temp_data.lua_state); 
    233         } 
    234 #endif 
    235342        temp_data_kind = 0; 
    236343 
     
    257364          free(temp_data.str); 
    258365        } 
    259 #ifdef OPT_LUA 
    260         else if ( temp_data_kind == 2 ) 
    261         { 
    262           lua_close(temp_data.lua_state); 
    263         } 
    264 #endif 
    265366        temp_data_kind = 0; 
    266367      } 
     
    392493 
    393494#ifdef OPT_LUA 
     495    // TODO this should flush data even if scripting isn't supported 
    394496    case PTP_CHDK_ExecuteScript: 
    395497      { 
    396498        int s; 
    397499        char *buf; 
     500 
     501        script_run_id++; 
     502        ptp.num_param = 2; 
     503        ptp.param1 = script_run_id; 
    398504 
    399505        if ( param2 != PTP_CHDK_SL_LUA ) 
     
    414520        recv_ptp_data(data,buf,s); 
    415521 
    416         long script_action_stack = script_start_ptp(buf, param3&PTP_CHDK_ES_RESULT); 
     522        // error details will be passed in a message 
     523        if (script_start_ptp(buf) < 0) { 
     524          ptp.param2 = PTP_CHDK_S_ERRTYPE_COMPILE; 
     525        } else { 
     526          ptp.param2 = PTP_CHDK_S_ERRTYPE_NONE; 
     527        } 
    417528 
    418529        free(buf); 
    419530         
    420         if (script_action_stack < 0) 
    421         { 
    422           ptp.code = PTP_RC_InvalidParameter; 
    423           break; 
    424         } 
    425         else 
    426         { 
    427  
    428           if ( param3 & PTP_CHDK_ES_WAIT ) 
    429           { 
    430  
    431             while ( script_is_running() ) 
    432               msleep(100); 
    433  
    434             if ( param3 & PTP_CHDK_ES_RESULT ) 
    435             { 
    436               lua_State *Lt; 
    437               temp_data.lua_state = lua_consume_result(); 
    438               Lt = get_lua_thread(temp_data.lua_state); 
    439               temp_data_kind = 2; 
    440               if ( lua_gettop(Lt) == 0 ) 
    441               { 
    442                 temp_data_extra = PTP_CHDK_TYPE_NOTHING; 
    443               } else if ( lua_isnil(Lt,1) ) 
    444               { 
    445                 temp_data_extra = PTP_CHDK_TYPE_NIL; 
    446               } else if ( lua_isboolean(Lt,1) ) 
    447               { 
    448                 temp_data_extra = PTP_CHDK_TYPE_BOOLEAN; 
    449               } else if ( lua_isnumber(Lt,1) ) 
    450               { 
    451                 temp_data_extra = PTP_CHDK_TYPE_INTEGER; 
    452               } else if ( lua_isstring(Lt,1) ) 
    453               { 
    454                 temp_data_extra = PTP_CHDK_TYPE_STRING; 
    455               } else if ( lua_istable(Lt,1) ) 
    456               { 
    457                 temp_data_extra = PTP_CHDK_TYPE_NOTHING; 
    458                 int i; 
    459                 int count = 0; 
    460                 lua_pushstring(Lt,""); 
    461                 lua_pushnil(Lt); 
    462                 while (lua_next(Lt,1) ) 
    463                 { 
    464                   lua_pushvalue(Lt,-2); 
    465                   lua_insert(Lt,-4); 
    466                   if ( lua_istable(Lt,-1) && (lua_objlen(Lt,-1) > 0) ) 
    467                   { 
    468                     lua_pushstring(Lt,""); 
    469                     for ( i = 1; i <= lua_objlen(Lt,-2); i++ ) 
    470                     { 
    471                       lua_rawgeti(Lt,-2,i); 
    472                       if ( lua_isnil(Lt,-1) ) 
    473                       { 
    474                         lua_pushstring(Lt,"nil"); 
    475                         lua_remove(Lt,-2); 
    476                       } 
    477                       if ( lua_isboolean(Lt,-1) ) 
    478                       { 
    479                         lua_pushstring(Lt,lua_toboolean(Lt,-1)?"true":"false"); 
    480                         lua_remove(Lt,-2); 
    481                       } 
    482                       if ( !lua_isstring(Lt,-1) ) 
    483                       { 
    484                         lua_pop(Lt,1); 
    485                         lua_pushstring(Lt,""); 
    486                       } 
    487                       if ( lua_objlen(Lt,-2) > 0 ) 
    488                       { 
    489                         lua_pushlstring(Lt,"\t",1); 
    490                         lua_insert(Lt,-2); 
    491                         lua_concat(Lt,3); 
    492                       } 
    493                       else lua_concat(Lt,2); 
    494                     } 
    495                     lua_remove(Lt,-2); 
    496                   } 
    497                   if ( lua_isboolean(Lt,-1) ) 
    498                   { 
    499                     lua_pushstring(Lt,lua_toboolean(Lt,-1)?"true":"false"); 
    500                     lua_remove(Lt,-2); 
    501                   } 
    502                   if ( lua_isstring(Lt,-1) ) 
    503                   { 
    504                     lua_pushlstring(Lt,"\t",1); 
    505                     lua_insert(Lt,-2); 
    506                     if ( lua_objlen(Lt,-4) > 0 ) 
    507                     { 
    508                       lua_pushlstring(Lt,"\n",1); 
    509                       lua_insert(Lt,-4); 
    510                       lua_concat(Lt, 5); 
    511                     } 
    512                     else lua_concat(Lt, 4); 
    513                   } 
    514                   else lua_pop(Lt,2); 
    515                   lua_insert(Lt,-2); 
    516                   lua_pushvalue(Lt,-1);  //set entry to nil for save memory 
    517                   lua_pushnil(Lt); 
    518                   lua_settable(Lt,1); 
    519                 } 
    520                 if ( lua_gettop(Lt) == 2 ) lua_remove(Lt,1); 
    521                 if ( lua_isstring(Lt,1) && ( lua_objlen(Lt,1) > 0 )) temp_data_extra = PTP_CHDK_TYPE_STRING; 
    522               } else { 
    523                 temp_data_extra = PTP_CHDK_TYPE_NOTHING; 
    524               } 
    525               ptp.num_param = 1; 
    526               ptp.param1 = temp_data_extra; 
    527               if ( temp_data_extra != PTP_CHDK_TYPE_STRING ) 
    528               { 
    529                 if ( temp_data_extra == PTP_CHDK_TYPE_BOOLEAN ) 
    530                 { 
    531                   ptp.num_param = 2; 
    532                   ptp.param2 = lua_toboolean(Lt,1); 
    533                 } if ( temp_data_extra == PTP_CHDK_TYPE_INTEGER ) 
    534                 { 
    535                   ptp.num_param = 2; 
    536                   ptp.param2 = lua_tonumber(Lt,1); 
    537                 } 
    538                 lua_close(Lt); 
    539                 temp_data_kind = 0; 
    540               } else { 
    541                 ptp.num_param = 2; 
    542                 ptp.param2 = lua_objlen(Lt,1); 
    543               } 
    544             } 
    545           } 
    546         } 
    547  
    548         break; 
    549       } 
     531        break; 
     532      } 
     533    case PTP_CHDK_ReadScriptMsg: 
     534    { 
     535      ptp_script_msg *msg = dequeue_script_msg(&msg_q_out); 
     536      ptp.num_param = 4; 
     537      if(!msg) { 
     538        // return a fully formed message for easier handling 
     539        ptp.param1 = PTP_CHDK_S_MSGTYPE_NONE; 
     540        ptp.param2 = 0; 
     541        ptp.param3 = 0; 
     542        ptp.param4 = 4; 
     543        // looks like we need to send some data no matter what 
     544        if ( !send_ptp_data(data,"\0\0\0",4) ) 
     545        { 
     546          ptp.code = PTP_RC_GeneralError; 
     547        } 
     548        break; 
     549      } 
     550      ptp.param1 = msg->type; 
     551      ptp.param2 = msg->subtype; 
     552      ptp.param3 = msg->script_id; 
     553      ptp.param4 = msg->size; 
     554 
     555      // NOTE message is lost if sending failed 
     556      if ( !send_ptp_data(data,msg->data,msg->size) ) 
     557      { 
     558        ptp.code = PTP_RC_GeneralError; 
     559      } 
     560      free(msg); 
     561      break; 
     562    } 
     563    case PTP_CHDK_WriteScriptMsg: 
     564    { 
     565      int msg_size; 
     566      ptp_script_msg *msg; 
     567      ptp.num_param = 1; 
     568      ptp.param1 = PTP_CHDK_S_MSGSTATUS_OK; 
     569      if (!script_is_running()) { 
     570        ptp.param1 = PTP_CHDK_S_MSGSTATUS_NOTRUN; 
     571      } else if(param2 && param2 != script_run_id) {// check if target script for message is running 
     572        ptp.param1 = PTP_CHDK_S_MSGSTATUS_BADID; 
     573      } else if(script_msg_q_full(&msg_q_in)) { 
     574        ptp.param1 = PTP_CHDK_S_MSGSTATUS_QFULL; 
     575      } 
     576 
     577      msg_size = data->get_data_size(data->handle); 
     578 
     579      // if something was wrong, don't bother creating message, just flush 
     580      if(ptp.param1 != PTP_CHDK_S_MSGSTATUS_OK) { 
     581        flush_recv_ptp_data(data,msg_size); 
     582        break; 
     583      } 
     584      msg = ptp_script_create_msg(PTP_CHDK_S_MSGTYPE_USER,PTP_CHDK_TYPE_STRING,msg_size,NULL); 
     585      if ( !msg ) // malloc error or zero size 
     586      { 
     587        // if size is zero, things will get hosed no matter what 
     588        flush_recv_ptp_data(data,msg_size); 
     589        ptp.code = PTP_RC_GeneralError; 
     590        break; 
     591      } 
     592      msg->script_id = param2; 
     593      if ( !recv_ptp_data(data,msg->data,msg->size) ) 
     594      { 
     595        ptp.code = PTP_RC_GeneralError; 
     596        free(msg); 
     597        break; 
     598      } 
     599      if( !enqueue_script_msg(&msg_q_in,msg) ) { 
     600        ptp.code = PTP_RC_GeneralError; 
     601        free(msg); 
     602      } 
     603      break; 
     604    } 
    550605#endif 
    551606 
  • trunk/core/ptp.h

    r1051 r1101  
    11#ifndef __PTP_H 
    22#define __PTP_H 
    3  
    4 // N.B.: not checking to see if CAM_CHDK_PTP is set as ptp.h is currently 
    5 // only included by ptp.c (which already checks this before including ptp.h) 
    6  
    7 #define PTP_CHDK_VERSION_MAJOR 0  // increase only with backwards incompatible changes (and reset minor) 
    8 #define PTP_CHDK_VERSION_MINOR 2  // increase with extensions of functionality 
     3#define PTP_CHDK_VERSION_MAJOR 1  // increase only with backwards incompatible changes (and reset minor) 
     4#define PTP_CHDK_VERSION_MINOR 0  // increase with extensions of functionality 
    95/* 
    106protocol version history 
    1170.1 - initial proposal from mweerden, + luar 
    1280.2 - Added ScriptStatus and ScriptSupport, based on work by ultimA 
     91.0 - removed old script result code (luar), replace with message system 
    1310*/ 
    1411 
     
    3936  PTP_CHDK_ExecuteScript,   // data is script to be executed 
    4037                            // param2 is language of script 
    41                             // param3 is for the ES flags below 
    42   PTP_CHDK_ScriptStatus,        // Script execution status 
    43                             // param1 CHDK_PTP_SCRIPT_STATUS_RUN is set if a script running, cleared if not 
    44                                                         // all other bits and params are reserved for future use 
     38                            // return param1 is script id, like a process id 
     39                            // return param2 is status, PTP_CHDK_S_ERRTYPE* 
     40  PTP_CHDK_ScriptStatus,    // Script execution status 
     41                            // return param1 bits 
     42                            // CHDK_PTP_SCRIPT_STATUS_RUN is set if a script running, cleared if not 
     43                            // CHDK_PTP_SCRIPT_STATUS_MSG is set if script messages from script waiting to be read 
     44                            // all other bits and params are reserved for future use 
    4545  PTP_CHDK_ScriptSupport,   // Which scripting interfaces are supported in this build 
    4646                            // param1 CHDK_PTP_SUPPORT_LUA is set if lua is supported, cleared if not 
    47                                                         // all other bits and params are reserved for future use 
     47                            // all other bits and params are reserved for future use 
     48  PTP_CHDK_ReadScriptMsg,   // read next message from camera script system 
     49                            // return param1 is chdk_ptp_s_msg_type 
     50                            // return param2 is message subtype: 
     51                            //   for script return and users this is ptp_chdk_script_data_type 
     52                            //   for error it may be an error ptp_chdk_script_error_type 
     53                            // return param3 is script id of script that generated the message 
     54                            // return param4 is length of the message data 
     55                            // return data is message. 
     56                            // A minimum of 4 bytes of zeros is returned if there would not be data otherwise 
     57  PTP_CHDK_WriteScriptMsg,  // write a message for scripts running on camera 
     58                            // input param2 is target script id, 0=don't care. Messages for a non-running script will be discarded 
     59                            // data length is handled by ptp data phase 
     60                            // input messages do not have type or subtype, they are always a string destined for the script (similar to USER/string) 
     61                            // output param1 is ptp_chdk_script_msg_status 
    4862} ptp_chdk_command; 
    4963 
    50 // data types as used by TempData and ExecuteScript 
     64// data types as used by ReadScriptMessage 
    5165enum { 
    52   PTP_CHDK_TYPE_NOTHING = 0, 
     66  PTP_CHDK_TYPE_UNSUPPORTED = 0, // type name will be returned in data 
    5367  PTP_CHDK_TYPE_NIL, 
    5468  PTP_CHDK_TYPE_BOOLEAN, 
    5569  PTP_CHDK_TYPE_INTEGER, 
    56   PTP_CHDK_TYPE_STRING 
    57 } ptp_chdk_type; 
     70  PTP_CHDK_TYPE_STRING, // NOTE tables currently returned as string 
     71} ptp_chdk_script_data_type; 
    5872 
    5973// TempData flags 
     
    6478                                   // just clear 
    6579 
    66 // ExecuteScript flags 
    67 #define PTP_CHDK_ES_WAIT      0x1  // do not return after script initialisation 
    68                                    // but wait until execution has finished 
    69                                    // (should only be used with short execution 
    70                                    // times) 
    71 #define PTP_CHDK_ES_RESULT    0x2  // only in combination with WAIT; return 
    72                                    // param1 will be the ptp_chdk_type of the 
    73                                    // code result and param2 the value (booleans 
    74                                    // and integers) or length (strings) 
    75  
    76 // Script Languages - for execution 
     80// Script Languages - for execution only lua is supported for now 
    7781#define PTP_CHDK_SL_LUA    0 
    7882#define PTP_CHDK_SL_UBASIC 1 
    7983 
    8084// bit flags for script status 
    81 #define PTP_CHDK_SCRIPT_STATUS_RUN   0x1 
     85#define PTP_CHDK_SCRIPT_STATUS_RUN   0x1 // script running 
     86#define PTP_CHDK_SCRIPT_STATUS_MSG   0x2 // messages waiting 
    8287// bit flags for scripting support 
    8388#define PTP_CHDK_SCRIPT_SUPPORT_LUA  0x1 
    8489 
     90// message types 
     91enum { 
     92    PTP_CHDK_S_MSGTYPE_NONE = 0, // no messages waiting 
     93    PTP_CHDK_S_MSGTYPE_ERR,         // error message 
     94    PTP_CHDK_S_MSGTYPE_RET,      // script return value 
     95    PTP_CHDK_S_MSGTYPE_USER,     // message queued by script 
     96// TODO chdk console data ? 
     97} ptp_chdk_script_msg_type; 
     98 
     99// error subtypes for PTP_CHDK_S_MSGTYPE_ERR and script startup status 
     100enum { 
     101    PTP_CHDK_S_ERRTYPE_NONE = 0, 
     102    PTP_CHDK_S_ERRTYPE_COMPILE, 
     103    PTP_CHDK_S_ERRTYPE_RUN, 
     104} ptp_chdk_script_error_type; 
     105 
     106// message status 
     107enum { 
     108    PTP_CHDK_S_MSGSTATUS_OK = 0, // queued ok 
     109    PTP_CHDK_S_MSGSTATUS_NOTRUN, // no script is running 
     110    PTP_CHDK_S_MSGSTATUS_QFULL,  // queue is full 
     111    PTP_CHDK_S_MSGSTATUS_BADID,  // specified ID is not running 
     112} ptp_chdk_script_msg_status; 
    85113#endif // __PTP_H 
  • trunk/core/script.c

    r1051 r1101  
    467467} 
    468468 
    469 static void wait_and_end(void) 
     469void script_wait_and_end(void) 
    470470{ 
    471471        script_console_add_line("PRESS SHUTTER TO CLOSE"); 
     
    496496 
    497497            if (Lres != LUA_YIELD && Lres != 0) { 
    498                 script_console_add_line( lua_tostring( Lt, -1 ) ); 
    499                 if(conf.debug_lua_restart_on_error){ 
    500                     lua_script_reset(); 
    501                     script_start_gui(0); 
    502                 } else { 
    503                     wait_and_end(); 
    504                 } 
     498                lua_script_error(Lt,1); 
    505499                return; 
    506500            } 
    507501 
    508502            if (Lres != LUA_YIELD) { 
     503                // add ptp result 
     504                lua_script_finish(Lt); 
    509505                script_console_add_line(lang_str(LANG_CONSOLE_TEXT_FINISHED)); 
    510506                action_pop(); 
     
    556552            } 
    557553            break; 
     554#if defined(OPT_LUA) && defined(CAM_CHDK_PTP) 
     555        case AS_SCRIPT_READ_USB_MSG: 
     556            if(L) { // only lua supported for now 
     557                ptp_script_msg *msg = ptp_script_read_msg(); 
     558                if(action_process_delay(2) || msg) { 
     559                    if(msg) { 
     560                        lua_pushlstring( Lt,msg->data,msg->size); 
     561                    } else { 
     562                        lua_pushnil(Lt); 
     563                    } 
     564                    action_clear_delay(); 
     565                    action_pop(); 
     566                    action_pop(); 
     567                } 
     568            } 
     569            break; 
     570        case AS_SCRIPT_WRITE_USB_MSG: 
     571            if(L) { // only lua supported for now 
     572                ptp_script_msg *msg = (ptp_script_msg *)action_get_prev(2); 
     573                int r = ptp_script_write_msg(msg); 
     574                if(action_process_delay(3) || r) { 
     575                    action_clear_delay(); 
     576                    action_pop(); 
     577                    action_pop(); 
     578                    action_pop(); 
     579                    lua_pushboolean(Lt,r); 
     580                } 
     581            } 
     582            break; 
     583#endif 
    558584        default: 
    559585            if (!action_stack_standard(p) && !state_kbd_script_run) 
     
    630656    if( is_lua() ) { 
    631657#ifdef OPT_LUA 
    632         if( !lua_script_start(script_source_str) ) { 
    633             script_print_screen_end(); 
    634             wait_and_end(); 
     658        if( !lua_script_start(script_source_str,0) ) { 
    635659            return -1; 
    636660        } 
     
    673697} 
    674698 
    675 #ifdef OPT_LUA 
    676 long script_start_ptp( char *script , int keep_result ) 
    677 { 
    678   if (!lua_script_start(script)) return -1; 
    679   lua_keep_result = keep_result; 
     699#if defined(OPT_LUA) && defined(CAM_CHDK_PTP) 
     700long script_start_ptp( char *script ) 
     701{ 
     702  if (!lua_script_start(script,1)) return -1; 
    680703  state_lua_kbd_first_call_to_resume = 1; 
    681704  state_kbd_script_run = 1; 
  • trunk/include/platform.h

    r1024 r1101  
    541541void init_chdk_ptp_task(); 
    542542 
     543typedef struct { 
     544    unsigned size; 
     545    unsigned script_id; // id of script message is to/from  
     546    unsigned type; 
     547    unsigned subtype; 
     548    char data[]; 
     549} ptp_script_msg; 
     550int ptp_script_write_msg(ptp_script_msg *msg); 
     551ptp_script_msg* ptp_script_read_msg(void); 
     552ptp_script_msg* ptp_script_create_msg(unsigned type, unsigned subtype, unsigned datasize, const void *data); 
     553int ptp_script_write_error_msg(unsigned errtype, const char *err); 
     554 
    543555#endif // CAM_CHDK_PTP 
    544556 
  • trunk/include/script.h

    r1036 r1101  
    3232//------------------------------------------------------------------- 
    3333 
    34 extern long script_start_ptp(char *script, int keep_result); 
    3534long script_stack_start(); 
    3635int script_is_running(); 
     
    4241int script_keyid_by_name( const char *name ); 
    4342#ifdef OPT_LUA 
    44 long script_start_ptp( char *script , int keep_result ); 
     43long script_start_ptp( char *script ); 
    4544#endif 
     45void script_wait_and_end(); 
    4646 
    4747#endif 
Note: See TracChangeset for help on using the changeset viewer.