CHDK_DE Vorschauversion  Trunk Rev. 5218
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
ptp.c-Dateireferenz
#include "camera_info.h"
#include "stddef.h"
#include "stdlib.h"
#include "keyboard.h"
#include "ptp_chdk.h"
#include "core.h"
#include "task.h"
#include "script.h"
#include "action_stack.h"
#include "live_view.h"
#include "meminfo.h"
#include "modules.h"
#include "callfunc.h"
#include "remotecap_core.h"
+ Include-Abhängigkeitsdiagramm für ptp.c:

gehe zum Quellcode dieser Datei

Datenstrukturen

struct  ptp_script_msg_q
 

Makrodefinitionen

#define PTP_SCRIPT_MSG_Q_LEN   16
 

Funktionen

static int handle_ptp (int h, ptp_data *data, int opcode, int sess_id, int trans_id, int param1, int param2, int param3, int param4, int param5)
 
static void init_chdk_ptp ()
 
void init_chdk_ptp_task ()
 
static int recv_ptp_data (ptp_data *data, char *buf, int size)
 
static void flush_recv_ptp_data (ptp_data *data, int size)
 
static int send_ptp_data (ptp_data *data, const char *buf, int size)
 
static int send_ptp_data_buffered (ptp_data *data, void *(*copy_fn)(void *d, const void *s, long sz), const char *src, char *buf, int size)
 
unsigned script_msg_q_next (unsigned i)
 
unsigned script_msg_q_full (ptp_script_msg_q *q)
 
unsigned script_msg_q_empty (ptp_script_msg_q *q)
 
int enqueue_script_msg (ptp_script_msg_q *q, ptp_script_msg *msg)
 
ptp_script_msgdequeue_script_msg (ptp_script_msg_q *q)
 
void empty_script_msg_q (ptp_script_msg_q *q)
 
ptp_script_msgptp_script_create_msg (unsigned type, unsigned subtype, unsigned datasize, const void *data)
 
int ptp_script_write_msg (ptp_script_msg *msg)
 
ptp_script_msgptp_script_read_msg (void)
 
int ptp_script_write_error_msg (unsigned errtype, const char *err)
 
void start_ptp_script ()
 
static long script_start_ptp (char *script)
 

Variablen

static int buf_size =0
 
static unsigned script_run_id
 
ptp_script_msg_q msg_q_in
 
ptp_script_msg_q msg_q_out
 
static char * ptp_script = 0
 
static int ptp_script_state = 0
 

Makro-Dokumentation

#define PTP_SCRIPT_MSG_Q_LEN   16

Definiert in Zeile 167 der Datei ptp.c.

Dokumentation der Funktionen

ptp_script_msg* dequeue_script_msg ( ptp_script_msg_q q)

Definiert in Zeile 206 der Datei ptp.c.

206  {
207  ptp_script_msg *msg;
208  if(script_msg_q_empty(q)) {
209  return NULL;
210  }
211  msg = q->q[q->r];
212  q->r = script_msg_q_next(q->r);
213  return msg;
214 }
void empty_script_msg_q ( ptp_script_msg_q q)

Definiert in Zeile 217 der Datei ptp.c.

217  {
218  ptp_script_msg *msg;
219  while((msg = dequeue_script_msg(q))) {
220  free(msg);
221  }
222 }
int enqueue_script_msg ( ptp_script_msg_q q,
ptp_script_msg msg 
)

Definiert in Zeile 193 der Datei ptp.c.

193  {
194  unsigned w = script_msg_q_next(q->w);
195  if(w == q->r) {
196  return 0;
197  }
198  if(msg == NULL) {
199  return 0;
200  }
201  q->q[q->w] = msg;
202  q->w = w;
203  return 1;
204 }
static void flush_recv_ptp_data ( ptp_data data,
int  size 
)
static

Definiert in Zeile 74 der Datei ptp.c.

74  {
75  char *buf;
76  buf = malloc((size > buf_size) ? buf_size:size);
77  if(!buf) // buf_size should always be less then available memory
78  return;
79  while ( size > 0 )
80  {
81  if ( size >= buf_size )
82  {
83  recv_ptp_data(data,buf,buf_size);
84  size -= buf_size;
85  } else {
86  recv_ptp_data(data,buf,size);
87  size = 0;
88  }
89  }
90  free(buf);
91 }
static int handle_ptp ( int  h,
ptp_data data,
int  opcode,
int  sess_id,
int  trans_id,
int  param1,
int  param2,
int  param3,
int  param4,
int  param5 
)
static

Definiert in Zeile 306 der Datei ptp.c.

309 {
310  static union {
311  char *str;
312  } temp_data;
313  static int temp_data_kind = 0; // 0: nothing, 1: ascii string
314  static int temp_data_extra; // size (ascii string)
315  PTPContainer ptp;
316 
317  // initialise default response
318  memset(&ptp,0,sizeof(PTPContainer));
319  ptp.code = PTP_RC_OK;
320  ptp.sess_id = sess_id;
321  ptp.trans_id = trans_id;
322  ptp.num_param = 0;
323 
324  // TODO
325  // calling this on every PTP command is not good on cameras without CAM_FIRMWARE_MEMINFO
326  // since it figures out free memory by repeatedly malloc'ing!
327  // using half of available memory may be undesirable in some cases as well
329  // make sure size is an integer number of words (avoid some possible issues with multiple receive calls)
330  buf_size &= 0xFFFFFFFC;
331 
332  // handle command
333  switch ( param1 )
334  {
335 
336  case PTP_CHDK_Version:
337  ptp.num_param = 2;
340  break;
342  ptp.num_param = 1;
343  ptp.param1 = 0;
345  break;
347  ptp.num_param = 1;
348  ptp.param1 = 0;
351  break;
352  case PTP_CHDK_GetMemory:
353  {
354  char *src=(char *)param2;
355  int size=param3;
356  int result=0;
357  if ( size < 1 ) // invalid size? NULL is accepted
358  {
360  break;
361  }
362 
363  if (param4 == PTP_CHDK_GETMEM_MODE_DIRECT) {
364  int total_size = size;
365  // canon data->send_data fails on NULL, send first word separately
366  // DMA from addresses occupied by TCM is suspect but seems to work on many cams
367  // can't directly check NULL https://chdk.setepontos.com/index.php?topic=13101.0
368  if((unsigned)param2 < 4 ) {
369  char x[4];
370  int send_size = 4 - param2;
371  if(send_size > size) {
372  send_size = size;
373  }
374  memcpy(x,src,send_size);
375 
376  // 0 is success
377  if(data->send_data(data->handle,x,send_size,total_size,0,0,0) != 0) {
379  break;
380  }
381  // that was all, done
382  if(size == send_size) {
383  break;
384  }
385  size -= send_size;
386  // total only sent on first send
387  total_size = 0;
388  src+=send_size;
389  }
390  // no need to send through send_ptp, faster with one call
391  if(data->send_data(data->handle,src,size,total_size,0,0,0) == 0) {
392  result = 1;
393  }
394  } else if(param4 == PTP_CHDK_GETMEM_MODE_BUFFER) {
395  int chunk_size = (size > buf_size) ? buf_size:size;
396  char *buf=malloc(chunk_size);
397  if(buf) {
398  result = send_ptp_data_buffered(data,memcpy,src,buf,size);
399  free(buf);
400  }
401  } // else error
402  if(!result)
403  {
405  }
406  break;
407  }
408  case PTP_CHDK_SetMemory:
409  if ( param2 == 0 || param3 < 1 ) // null pointer or invalid size?
410  {
412  break;
413  }
414 
415  data->get_data_size(data->handle); // XXX required call before receiving
416  if ( !recv_ptp_data(data,(char *) param2,param3) )
417  {
419  }
420  break;
421 
423  {
424  int s = data->get_data_size(data->handle);
425  if (s <= 0 || (s&3)) // no data or not an integer number of args
426  {
428  break;
429  }
430  unsigned *buf = malloc(s);
431 
432  if ( buf == NULL )
433  {
435  break;
436  }
437 
438  if ( recv_ptp_data(data,(char *) buf,s) )
439  {
440  ptp.num_param = 1;
441  ptp.param1 = call_func_ptr((void *)buf[0],(unsigned *)buf+1,(s-4)/4);
442  } else {
444  }
445 
446  free(buf);
447  break;
448  }
449 
450  case PTP_CHDK_TempData:
451  if ( param2 & PTP_CHDK_TD_DOWNLOAD )
452  {
453  const char *s = NULL;
454  size_t l = 0;
455 
456  if ( temp_data_kind == 0 )
457  {
459  break;
460  }
461 
462  if ( temp_data_kind == 1 )
463  {
464  s = temp_data.str;
465  l = temp_data_extra;
466  }
467 
468  if ( !send_ptp_data(data,s,l) )
469  {
471  break;
472  }
473 
474  } else if ( ! (param2 & PTP_CHDK_TD_CLEAR) ) {
475  if ( temp_data_kind == 1 )
476  {
477  free(temp_data.str);
478  }
479  temp_data_kind = 0;
480 
481  temp_data_extra = data->get_data_size(data->handle);
482 
483  temp_data.str = (char *) malloc(temp_data_extra);
484  if ( temp_data.str == NULL )
485  {
487  break;
488  }
489 
490  if ( !recv_ptp_data(data,temp_data.str,temp_data_extra) )
491  {
493  break;
494  }
495  temp_data_kind = 1;
496  }
497  if ( param2 & PTP_CHDK_TD_CLEAR )
498  {
499  if ( temp_data_kind == 1 )
500  {
501  free(temp_data.str);
502  }
503  temp_data_kind = 0;
504  }
505  break;
506 
507  case PTP_CHDK_UploadFile:
508  {
509  FILE *f=NULL;
510  char *buf=NULL, *fn=NULL;
511  unsigned data_size,fn_len,chunk_size;
512  data_size = data->get_data_size(data->handle);
513  while ( data_size > 0 ) {
514  chunk_size = (data_size > buf_size) ? buf_size:data_size;
515  // first time through
516  // allocate buffer, parse out the file name and open file
517  if(!buf) {
518  buf=malloc(chunk_size);
519  if(!buf) {
521  break;
522  }
523  recv_ptp_data(data,buf,chunk_size);
524  fn_len = *(unsigned *)buf;
525  fn = malloc(fn_len+1);
526  if(!fn) {
528  break;
529  }
530  memcpy(fn,buf+4,fn_len);
531  fn[fn_len] = 0;
532  f = fopen(fn,"wb");
533  free(fn);
534  if(!f) {
536  break;
537  }
538  fwrite(buf+4+fn_len,1,chunk_size - 4 - fn_len,f);
539  } else {
540  recv_ptp_data(data,buf,chunk_size);
541  fwrite(buf,1,chunk_size,f);
542  }
543  data_size -= chunk_size;
544  }
545  if(f) {
546  fclose(f);
547  }
548 
549  free(buf);
550  if(data_size > 0 && ptp.code != PTP_RC_OK) {
551  flush_recv_ptp_data(data,data_size);
552  }
553  break;
554  }
555 
557  {
558  FILE *f;
559  int tmp,t,s,r;
560  char *buf, *fn;
561 
562  if ( temp_data_kind != 1 )
563  {
564  // send dummy data, otherwise error hoses connection
565  send_ptp_data(data,"\0",1);
567  break;
568  }
569 
570  fn = (char *) malloc(temp_data_extra+1);
571  if ( fn == NULL )
572  {
573  // send dummy data, otherwise error hoses connection
574  send_ptp_data(data,"\0",1);
575  free(temp_data.str);
576  temp_data_kind = 0;
578  break;
579  }
580  memcpy(fn,temp_data.str,temp_data_extra);
581  fn[temp_data_extra] = '\0';
582 
583  free(temp_data.str);
584  temp_data_kind = 0;
585 
586  f = fopen(fn,"rb");
587  if ( f == NULL )
588  {
589  // send dummy data, otherwise error hoses connection
590  send_ptp_data(data,"\0",1);
592  free(fn);
593  break;
594  }
595  free(fn);
596 
597  fseek(f,0,SEEK_END);
598  s = ftell(f);
599  fseek(f,0,SEEK_SET);
600 
601  buf = (char *) malloc(buf_size);
602  if ( buf == NULL )
603  {
604  // send dummy data, otherwise error hoses connection
605  send_ptp_data(data,"\0",1);
607  break;
608  }
609 
610  tmp = s;
611  t = s;
612  while ( (r = fread(buf,1,(t<buf_size)?t:buf_size,f)) > 0 )
613  {
614  t -= r;
615  // cannot use send_ptp_data here
616  data->send_data(data->handle,buf,r,tmp,0,0,0);
617  tmp = 0;
618  }
619  fclose(f);
620  // XXX check that we actually read/send s bytes! (t == 0)
621 
622  ptp.num_param = 1;
623  ptp.param1 = s;
624 
625  free(buf);
626 
627  break;
628  }
629  break;
630 
632  {
633  int s;
634  char *buf;
635 
636  ptp.num_param = 2;
637  ptp.param1 = script_run_id; // in error case, ID of most recent script
638 
639  s = data->get_data_size(data->handle);
640 
641  if ( (param2&PTP_CHDK_SL_MASK) != PTP_CHDK_SL_LUA )
642  {
643  flush_recv_ptp_data(data,s);
645  break;
646  }
647 
648  buf = (char *) malloc(s);
649  if ( buf == NULL )
650  {
652  break;
653  }
654 
655  recv_ptp_data(data,buf,s);
656 
657  // applies to both running and "interrupted" state, since interrupted means running restore
659  // note script ID is still incremented in this case
660  if (param2 & PTP_CHDK_SCRIPT_FL_NOKILL) {
661  // no message is added in this case, since the running script might also be doing
662  // stuff with messages
664  free(buf);
665  break;
666  }
667  // kill the script
669  }
670  // empty message queues if requested.
671  if(param2 & PTP_CHDK_SCRIPT_FL_FLUSH_CAM_MSGS) {
673  }
674  // Script either was not running or has been killed, so safe to remove from inbound queue outside of kbd task
677  }
678 
679  // increment script ID if script is loaded
680  script_run_id++;
681  ptp.param1 = script_run_id;
682 
683  // error details will be passed in a message
684  if (script_start_ptp(buf) < 0) {
686  } else {
688  }
689 
690  free(buf);
691 
692  break;
693  }
695  {
696  char *pdata="";
697  unsigned datasize=1;
698 
700  ptp.num_param = 4;
701  if(msg) {
702  ptp.param1 = msg->type;
703  ptp.param2 = msg->subtype;
704  ptp.param3 = msg->script_id;
705  ptp.param4 = msg->size;
706  // empty messages must have a data phase, so use default if no data
707  if(msg->size) {
708  datasize = msg->size;
709  pdata = msg->data;
710  }
711  } else {
712  // return a fully formed message for easier handling
714  ptp.param2 = 0;
715  ptp.param3 = 0;
716  ptp.param4 = 0;
717  }
718 
719  // NOTE message is lost if sending failed
720  if ( !send_ptp_data(data,pdata,datasize) )
721  {
723  }
724  free(msg);
725  break;
726  }
728  {
729  int msg_size;
730  ptp_script_msg *msg;
731  ptp.num_param = 1;
733  if (!script_is_running()) {
735  } else if(param2 && param2 != script_run_id) {// check if target script for message is running
737  } else if(script_msg_q_full(&msg_q_in)) {
739  }
740 
741  msg_size = data->get_data_size(data->handle);
742 
743  // if something was wrong, don't bother creating message, just flush
744  if(ptp.param1 != PTP_CHDK_S_MSGSTATUS_OK) {
745  flush_recv_ptp_data(data,msg_size);
746  break;
747  }
749  if ( !msg ) // malloc error or zero size
750  {
751  // if size is zero, things will get hosed no matter what
752  flush_recv_ptp_data(data,msg_size);
754  break;
755  }
756  msg->script_id = param2;
757  if ( !recv_ptp_data(data,msg->data,msg->size) )
758  {
760  free(msg);
761  break;
762  }
763  if( !enqueue_script_msg(&msg_q_in,msg) ) {
765  free(msg);
766  }
767  break;
768  }
769 
771  {
772  extern int live_view_get_data(ptp_data *data, int flags);
773 
774  ptp.num_param = 1;
775  ptp.param1 = live_view_get_data(data,param2);
776  if(!ptp.param1)
777  {
779  // send dummy data, otherwise error hoses connection
780  send_ptp_data(data,"\0",1);
781  }
782  }
783  break;
785  ptp.num_param = 2;
786  remotecap_is_ready(&ptp.param1,&ptp.param2);
787  break;
789  {
790  unsigned int rcgd_size;
791  int rcgd_status;
792  char *rcgd_addr;
793  int rcgd_pos;
794 
795  rcgd_status = remotecap_get_data_chunk(param2, &rcgd_addr, &rcgd_size, &rcgd_pos);
796  ptp.num_param = 3;
797  ptp.param3 = rcgd_pos; //client needs to seek to this file position before writing the chunk (-1 = ignore)
798  if ( (rcgd_addr==0) || (rcgd_size==0) ) {
799  // send dummy data, otherwise error hoses connection
800  send_ptp_data(data,"\0",1);
801  ptp.param1 = 0; //size
802  ptp.param2 = 0; //0 = no more chunks
803  } else {
804  // send directly using send_data to avoid multiple send calls
805  data->send_data(data->handle,rcgd_addr,rcgd_size,rcgd_size,0,0,0);
806 
807  ptp.param1 = rcgd_size; //size
808  if(rcgd_status == REMOTECAP_CHUNK_STATUS_MORE) {
809  ptp.param2 = 1;
810  } else {
811  ptp.param2 = 0;
812  }
813  }
814  // data send complete, free hooks etc as needed, set error status if required
815  if(!remotecap_send_complete(rcgd_status,param2)) {
817  }
818  }
819  break;
820  default:
822  break;
823  }
824 
825  // send response
826  data->send_resp( data->handle, &ptp, 0 );
827 
828  return 1;
829 }
static void init_chdk_ptp ( )
static

Definiert in Zeile 26 der Datei ptp.c.

27 {
28  int r;
29 
30  // wait until ptp_handlers_info is initialised and add CHDK PTP interface
31  r = 0x17;
32  while ( r==0x17 )
33  {
35  msleep(250);
36  }
37 
38  ExitTask();
39 }
void init_chdk_ptp_task ( )

Definiert in Zeile 41 der Datei ptp.c.

42 {
43  CreateTask("InitCHDKPTP", 0x19, 0x200, init_chdk_ptp);
44 };
ptp_script_msg* ptp_script_create_msg ( unsigned  type,
unsigned  subtype,
unsigned  datasize,
const void *  data 
)

Definiert in Zeile 226 der Datei ptp.c.

226  {
227  ptp_script_msg *msg;
228  msg = malloc(sizeof(ptp_script_msg) + datasize);
229  msg->size = datasize;
230  msg->type = type;
231  msg->subtype = subtype;
232  // caller may fill in data themselves
233  // datasize may be empty (e.g. empty string)
234  if(data && datasize) {
235  memcpy(msg->data,data,msg->size);
236  }
237  return msg;
238 }
ptp_script_msg* ptp_script_read_msg ( void  )

Definiert in Zeile 247 der Datei ptp.c.

247  {
248  ptp_script_msg *msg;
249  while(1) {
250  msg = dequeue_script_msg(&msg_q_in);
251  // no messages
252  if(!msg) {
253  return NULL;
254  }
255  // does message belong to our script
256  if(!msg->script_id || msg->script_id == script_run_id) {
257  return msg;
258  } else {
259  // no: discard and keep looking
260  free(msg);
261  }
262  }
263 }
int ptp_script_write_error_msg ( unsigned  errtype,
const char *  err 
)

Definiert in Zeile 266 der Datei ptp.c.

266  {
268  return 0;
269  }
271  if(!msg) {
272  return 0;
273  }
274  return ptp_script_write_msg(msg);
275 }
int ptp_script_write_msg ( ptp_script_msg msg)

Definiert in Zeile 241 der Datei ptp.c.

241  {
242  msg->script_id = script_run_id;
243  return enqueue_script_msg(&msg_q_out,msg);
244 }
static int recv_ptp_data ( ptp_data data,
char *  buf,
int  size 
)
static

Definiert in Zeile 53 der Datei ptp.c.

55 {
56  while ( size >= buf_size )
57  {
58  data->recv_data(data->handle,buf,buf_size,0,0);
59  // XXX check for success??
60 
61  size -= buf_size;
62  buf += buf_size;
63  }
64  if ( size != 0 )
65  {
66  data->recv_data(data->handle,buf,size,0,0);
67  // XXX check for success??
68  }
69 
70  return 1;
71 }
unsigned script_msg_q_empty ( ptp_script_msg_q q)

Definiert in Zeile 189 der Datei ptp.c.

189  {
190  return (q->w == q->r);
191 }
unsigned script_msg_q_full ( ptp_script_msg_q q)

Definiert in Zeile 185 der Datei ptp.c.

185  {
186  return (script_msg_q_next(q->w) == q->r);
187 }
unsigned script_msg_q_next ( unsigned  i)

Definiert in Zeile 178 der Datei ptp.c.

178  {
179  if(i == PTP_SCRIPT_MSG_Q_LEN - 1) {
180  return 0;
181  }
182  return i+1;
183 }
static long script_start_ptp ( char *  script)
static

Definiert in Zeile 299 der Datei ptp.c.

300 {
301  ptp_script = script;
302  while (ptp_script) msleep(10);
303  return ptp_script_state;
304 }
static int send_ptp_data ( ptp_data data,
const char *  buf,
int  size 
)
static

Definiert in Zeile 93 der Datei ptp.c.

95 {
96  int tmpsize;
97 
98  tmpsize = size;
99  while ( size >= buf_size )
100  {
101  if ( data->send_data(data->handle,buf,buf_size,tmpsize,0,0,0) )
102  {
103  return 0;
104  }
105 
106  tmpsize = 0;
107  size -= buf_size;
108  buf += buf_size;
109  }
110  if ( size != 0 )
111  {
112  if ( data->send_data(data->handle,buf,size,tmpsize,0,0,0) )
113  {
114  return 0;
115  }
116  }
117 
118  return 1;
119 }
static int send_ptp_data_buffered ( ptp_data data,
void *(*)(void *d, const void *s, long sz)  copy_fn,
const char *  src,
char *  buf,
int  size 
)
static

Definiert in Zeile 126 der Datei ptp.c.

127 {
128  int tmpsize = size;
129  int send_size;
130  while ( size > 0 )
131  {
132  if(size > buf_size) {
133  send_size = buf_size;
134  } else {
135  send_size = size;
136  }
137  // src inside buf ?
138  if(src >= buf && src < buf + send_size) {
139  // send whatever is in buffer without attempting to copy
140  if(src + size < buf + buf_size) {
141  // all remainder is in buf
142  send_size = size;
143  } else {
144  // send up to end of buffer
145  send_size = buf_size - (src - buf);
146  }
147  } else {
148  // full copy size would overlap
149  if(src < buf && src + send_size > buf) {
150  // copy up to start of buf
151  send_size = buf - src;
152  }
153  copy_fn(buf,src,send_size);
154  }
155  if ( data->send_data(data->handle,buf,send_size,tmpsize,0,0,0) )
156  {
157  return 0;
158  }
159  tmpsize = 0;
160  size -= send_size;
161  src += send_size;
162  }
163  return 1;
164 }
void start_ptp_script ( )

Definiert in Zeile 282 der Datei ptp.c.

283 {
284  if (ptp_script)
285  {
286  module_set_script_lang(0); // Force Lua script language
288  {
291  }
292  else
293  ptp_script_state = -1;
294  ptp_script = 0;
295  }
296 }

Variablen-Dokumentation

int buf_size =0
static

Definiert in Zeile 16 der Datei ptp.c.

ptp_script_msg_q msg_q_in

Definiert in Zeile 175 der Datei ptp.c.

ptp_script_msg_q msg_q_out

Definiert in Zeile 176 der Datei ptp.c.

char* ptp_script = 0
static

Definiert in Zeile 277 der Datei ptp.c.

int ptp_script_state = 0
static

Definiert in Zeile 278 der Datei ptp.c.

unsigned script_run_id
static

Definiert in Zeile 20 der Datei ptp.c.