summaryrefslogtreecommitdiff
path: root/src/chdk_ptp.h
blob: 65dcfd787142bb23e4bf840aa7bf96c84c5401c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
#ifndef __CHDK_PTP_H
#define __CHDK_PTP_H

// CHDK PTP protocol interface (can also be used in client PTP programs)

// Note: used in modules and platform independent code. 
// Do not add platform dependent stuff in here (#ifdef/#endif compile options or camera dependent values)

#define PTP_CHDK_VERSION_MAJOR 2  // increase only with backwards incompatible changes (and reset minor)
#define PTP_CHDK_VERSION_MINOR 6  // increase with extensions of functionality
                                  // minor > 1000 for development versions

/*
protocol version history
0.1 - initial proposal from mweerden, + luar
0.2 - Added ScriptStatus and ScriptSupport, based on work by ultimA
1.0 - removed old script result code (luar), replace with message system
2.0 - return PTP_CHDK_TYPE_TABLE for tables instead of TYPE_STRING, allow return of empty strings
2.1 - experimental live view, not formally released
2.2 - live view (work in progress)
2.3 - live view - released in 1.1
2.4 - live view protocol 2.1
2.5 - remote capture
2.6 - script execution flags
*/

#define PTP_OC_CHDK 0x9999

// N.B.: unused parameters should be set to 0
//enum ptp_chdk_command {
enum PTP_CHDK_Command {
  PTP_CHDK_Version = 0,     // return param1 is major version number
                            // return param2 is minor version number
  PTP_CHDK_GetMemory,       // param2 is base address (not NULL; circumvent by taking 0xFFFFFFFF and size+1)
                            // param3 is size (in bytes)
                            // return data is memory block
  PTP_CHDK_SetMemory,       // param2 is address
                            // param3 is size (in bytes)
                            // data is new memory block
  PTP_CHDK_CallFunction,    // data is array of function pointer and 32 bit int arguments (max: 10 args prior to protocol 2.5)
                            // return param1 is return value
  PTP_CHDK_TempData,        // data is data to be stored for later
                            // param2 is for the TD flags below
  PTP_CHDK_UploadFile,      // data is 4-byte length of filename, followed by filename and contents
  PTP_CHDK_DownloadFile,    // preceded by PTP_CHDK_TempData with filename
                            // return data are file contents
  PTP_CHDK_ExecuteScript,   // data is script to be executed
                            // param2 is language of script
                            //  in proto 2.6 and later, language is the lower byte, rest is used for PTP_CHDK_SCRIPT_FL* flags
                            // return param1 is script id, like a process id
                            // return param2 is status from ptp_chdk_script_error_type
  PTP_CHDK_ScriptStatus,    // Script execution status
                            // return param1 bits
                            // PTP_CHDK_SCRIPT_STATUS_RUN is set if a script running, cleared if not
                            // PTP_CHDK_SCRIPT_STATUS_MSG is set if script messages from script waiting to be read
                            // all other bits and params are reserved for future use
  PTP_CHDK_ScriptSupport,   // Which scripting interfaces are supported in this build
                            // param1 CHDK_PTP_SUPPORT_LUA is set if lua is supported, cleared if not
                            // all other bits and params are reserved for future use
  PTP_CHDK_ReadScriptMsg,   // read next message from camera script system
                            // return param1 is chdk_ptp_s_msg_type
                            // return param2 is message subtype:
                            //   for script return and users this is ptp_chdk_script_data_type
                            //   for error ptp_chdk_script_error_type
                            // return param3 is script id of script that generated the message
                            // return param4 is length of the message data. 
                            // return data is message.
                            // A minimum of 1 bytes of zeros is returned if the message has no data (empty string or type NONE)
  PTP_CHDK_WriteScriptMsg,  // write a message for scripts running on camera
                            // input param2 is target script id, 0=don't care. Messages for a non-running script will be discarded
                            // data length is handled by ptp data phase
                            // input messages do not have type or subtype, they are always a string destined for the script (similar to USER/string)
                            // output param1 is ptp_chdk_script_msg_status
  PTP_CHDK_GetDisplayData,  // Return camera display data
                            // This is defined as separate sub protocol in live_view.h
                            // Changes to the sub-protocol will always be considered a minor change to the main protocol
                            //  param2 bitmask of data
                            //  output param1 = total size of data
                            //  return data is protocol information, frame buffer descriptions and selected display data
                            //  Currently a data phase is always returned. Future versions may define other behavior 
                            //  for values in currently unused parameters.
  // Direct image capture over USB.
  // Use lua get_usb_capture_support for available data types, lua init_usb_capture for setup
  PTP_CHDK_RemoteCaptureIsReady, // Check if data is available
                                 // return param1 is status 
                                 //  0 = not ready
                                 //  0x10000000 = remote capture not initialized
                                 //  otherwise bitmask of PTP_CHDK_CAPTURE_* datatypes
                                 // return param2 is image number
  PTP_CHDK_RemoteCaptureGetData  // retrieve data
                                 // param2 is bit indicating data type to get
                                 // return param1 is length
                                 // return param2 more chunks available?
                                 //  0 = no more chunks of selected format
                                 // return param3 seek required to pos (-1 = no seek)
};

// data types as used by ReadScriptMessage
enum ptp_chdk_script_data_type {
  PTP_CHDK_TYPE_UNSUPPORTED = 0, // type name will be returned in data
  PTP_CHDK_TYPE_NIL,
  PTP_CHDK_TYPE_BOOLEAN,
  PTP_CHDK_TYPE_INTEGER,
  PTP_CHDK_TYPE_STRING, // Empty strings are returned with length=0
  PTP_CHDK_TYPE_TABLE,  // tables are converted to a string by usb_msg_table_to_string, 
                        // this function can be overridden in lua to change the format
                        // the string may be empty for an empty table
};

// TempData flags
#define PTP_CHDK_TD_DOWNLOAD  0x1  // download data instead of upload
#define PTP_CHDK_TD_CLEAR     0x2  // clear the stored data; with DOWNLOAD this
                                   // means first download, then clear and
                                   // without DOWNLOAD this means no uploading,
                                   // just clear

// Script Languages - for execution only lua is supported for now
#define PTP_CHDK_SL_LUA    0
#define PTP_CHDK_SL_UBASIC 1
#define PTP_CHDK_SL_MASK 0xFF

/* standard message chdkptp sends */
#define PTP_CHDK_LUA_SERIALIZE "\n\
serialize_r = function(v,opts,r,seen,depth)\n\
	local vt = type(v)\n\
	if vt == 'nil' or  vt == 'boolean' or vt == 'number' then\n\
		table.insert(r,tostring(v))\n\
		return\n\
	end\n\
	if vt == 'string' then\n\
		table.insert(r,string.format('%%q',v))\n\
		return\n\
	end\n\
	if vt == 'table' then\n\
		if not depth then\n\
			depth = 1\n\
		end\n\
		if depth >= opts.maxdepth then\n\
			error('serialize: max depth')\n\
		end\n\
		if not seen then\n\
			seen={}\n\
		elseif seen[v] then\n\
			if opts.err_cycle then\n\
				error('serialize: cycle')\n\
			else\n\
				table.insert(r,'\"cycle:'..tostring(v)..'\"')\n\
				return\n\
			end\n\
		end\n\
		seen[v] = true;\n\
		table.insert(r,'{')\n\
		for k,v1 in pairs(v) do\n\
			if opts.pretty then\n\
				table.insert(r,'\\n'..string.rep(' ',depth))\n\
			end\n\
			if type(k) == 'string' and string.match(k,'^[_%%a][%%a%%d_]*$') then\n\
				table.insert(r,k)\n\
			else\n\
				table.insert(r,'[')\n\
				serialize_r(k,opts,r,seen,depth+1)\n\
				table.insert(r,']')\n\
			end\n\
			table.insert(r,'=')\n\
			serialize_r(v1,opts,r,seen,depth+1)\n\
			table.insert(r,',')\n\
		end\n\
		if opts.pretty then\n\
			table.insert(r,'\\n'..string.rep(' ',depth-1))\n\
		end\n\
		table.insert(r,'}')\n\
		return\n\
	end\n\
	if opts.err_type then\n\
		error('serialize: unsupported type ' .. vt, 2)\n\
	else\n\
		table.insert(r,'\"'..tostring(v)..'\"')\n\
	end\n\
end\n\
serialize_defaults = {\n\
	maxdepth=10,\n\
	err_type=true,\n\
	err_cycle=true,\n\
	pretty=false,\n\
}\n\
function serialize(v,opts)\n\
	if opts then\n\
		for k,v in pairs(serialize_defaults) do\n\
			if not opts[k] then\n\
				opts[k]=v\n\
			end\n\
		end\n\
	else\n\
		opts=serialize_defaults\n\
	end\n\
	local r={}\n\
	serialize_r(v,opts,r)\n\
	return table.concat(r)\n\
end\n"

#define PTP_CHDK_LUA_SERIALIZE_SIMPLEQUOTE "\n\
serialize_r = function(v,opts,r,seen,depth)\n\
	local vt = type(v)\n\
	if vt == 'nil' or  vt == 'boolean' or vt == 'number' then\n\
		table.insert(r,tostring(v))\n\
		return\n\
	end\n\
	if vt == 'string' then\n\
		table.insert(r,string.format('%q',v))\n\
		return\n\
	end\n\
	if vt == 'table' then\n\
		if not depth then\n\
			depth = 1\n\
		end\n\
		if depth >= opts.maxdepth then\n\
			error('serialize: max depth')\n\
		end\n\
		if not seen then\n\
			seen={}\n\
		elseif seen[v] then\n\
			if opts.err_cycle then\n\
				error('serialize: cycle')\n\
			else\n\
				table.insert(r,'\"cycle:'..tostring(v)..'\"')\n\
				return\n\
			end\n\
		end\n\
		seen[v] = true;\n\
		table.insert(r,'{')\n\
		for k,v1 in pairs(v) do\n\
			if opts.pretty then\n\
				table.insert(r,'\\n'..string.rep(' ',depth))\n\
			end\n\
			if type(k) == 'string' and string.match(k,'^[_%a][%a%d_]*$') then\n\
				table.insert(r,k)\n\
			else\n\
				table.insert(r,'[')\n\
				serialize_r(k,opts,r,seen,depth+1)\n\
				table.insert(r,']')\n\
			end\n\
			table.insert(r,'=')\n\
			serialize_r(v1,opts,r,seen,depth+1)\n\
			table.insert(r,',')\n\
		end\n\
		if opts.pretty then\n\
			table.insert(r,'\\n'..string.rep(' ',depth-1))\n\
		end\n\
		table.insert(r,'}')\n\
		return\n\
	end\n\
	if opts.err_type then\n\
		error('serialize: unsupported type ' .. vt, 2)\n\
	else\n\
		table.insert(r,'\"'..tostring(v)..'\"')\n\
	end\n\
end\n\
serialize_defaults = {\n\
	maxdepth=10,\n\
	err_type=true,\n\
	err_cycle=true,\n\
	pretty=false,\n\
}\n\
function serialize(v,opts)\n\
	if opts then\n\
		for k,v in pairs(serialize_defaults) do\n\
			if not opts[k] then\n\
				opts[k]=v\n\
			end\n\
		end\n\
	else\n\
		opts=serialize_defaults\n\
	end\n\
	local r={}\n\
	serialize_r(v,opts,r)\n\
	return table.concat(r)\n\
end\n"

#define PTP_CHDK_LUA_SERIALIZE_MSGS \
PTP_CHDK_LUA_SERIALIZE\
"usb_msg_table_to_string=serialize\n"

#define PTP_CHDK_LUA_SERIALIZE_MSGS_SIMPLEQUOTE \
PTP_CHDK_LUA_SERIALIZE_SIMPLEQUOTE\
"usb_msg_table_to_string=serialize\n"

#define PTP_CHDK_LUA_EXTEND_TABLE \
"function extend_table(target,source,deep)\n\
	if type(target) ~= 'table' then\n\
		error('extend_table: target not table')\n\
	end\n\
	if source == nil then\n\
		return target\n\
	end\n\
	if type(source) ~= 'table' then \n\
		error('extend_table: source not table')\n\
	end\n\
	if source == target then\n\
		error('extend_table: source == target')\n\
	end\n\
	if deep then\n\
		return extend_table_r(target, source)\n\
	else \n\
		for k,v in pairs(source) do\n\
			target[k]=v\n\
		end\n\
		return target\n\
	end\n\
end\n"

#define PTP_CHDK_LUA_MSG_BATCHER	\
PTP_CHDK_LUA_SERIALIZE_MSGS \
PTP_CHDK_LUA_EXTEND_TABLE \
"function msg_batcher(opts)\n\
	local t = extend_table({\n\
		batchsize=50,\n\
		batchgc='step',\n\
		timeout=100000,\n\
	},opts)\n\
	t.data={}\n\
	t.n=0\n\
	if t.dbgmem then\n\
		t.init_free = get_meminfo().free_block_max_size\n\
		t.init_count = collectgarbage('count')\n\
	end\n\
	t.write=function(self,val)\n\
		self.n = self.n+1\n\
		self.data[self.n]=val\n\
		if self.n >= self.batchsize then\n\
			return self:flush()\n\
		end\n\
		return true\n\
	end\n\
	t.flush = function(self)\n\
		if self.n > 0 then\n\
			if self.dbgmem then\n\
				local count=collectgarbage('count')\n\
				local free=get_meminfo().free_block_max_size\n\
				self.data._dbg=string.format(\"count %%d (%%d) free %%d (%%d)\",\n\
					count, count - self.init_count, free, self.init_free-free)\n\
			end\n\
			if not write_usb_msg(self.data,self.timeout) then\n\
				return false\n\
			end\n\
			self.data={}\n\
			self.n=0\n\
			if self.batchgc then\n\
				collectgarbage(self.batchgc)\n\
			end\n\
			if self.batchpause then\n\
				sleep(self.batchpause)\n\
			end\n\
		end\n\
		return true\n\
	end\n\
	return t\n\
end\n"

#define PTP_CHDK_LUA_LS_SIMPLE \
PTP_CHDK_LUA_MSG_BATCHER  \
"function ls_simple(path)\n\
	local b=msg_batcher()\n\
	local t,err=os.listdir(path)\n\
	if not t then\n\
		return false,err\n\
	end\n\
	for i,v in ipairs(t) do\n\
		if not b:write(v) then\n\
			return false\n\
		end\n\
	end\n\
	return b:flush()\n\
end\n"

#define PTP_CHDK_LUA_JOINPATH \
"function joinpath(...)\n\
	local parts={...}\n\
	if #parts < 2 then\n\
		error('joinpath requires at least 2 parts',2)\n\
	end\n\
	local r=parts[1]\n\
	for i = 2, #parts do\n\
		local v = string.gsub(parts[i],'^/','')\n\
		if not string.match(r,'/$') then\n\
			r=r..'/'\n\
		end\n\
		r=r..v\n\
	end\n\
	return r\n\
end\n"

#define PTP_CHDK_LUA_LS \
PTP_CHDK_LUA_MSG_BATCHER \
PTP_CHDK_LUA_JOINPATH \
"function ls_single(opts,b,path,v)\n\
	if not opts.match or string.match(v,opts.match) then\n\
		if opts.stat then\n\
			local st,msg=os.stat(joinpath(path,v))\n\
			if not st then\n\
				return false,msg\n\
			end\n\
			if opts.stat == '/' then\n\
				if st.is_dir then\n\
					b:write(v .. '/')\n\
				else\n\
					b:write(v)\n\
				end\n\
			elseif opts.stat == '*' then\n\
				st.name=v\n\
				b:write(st)\n\
			end\n\
		else\n\
			b:write(v)\n\
		end\n\
	end\n\
	return true\n\
end\n\
\n\
function ls(path,opts_in)\n\
	local opts={\n\
		msglimit=50,\n\
		msgtimeout=100000,\n\
		dirsonly=true\n\
	}\n\
	if opts_in then\n\
		for k,v in pairs(opts_in) do\n\
			opts[k]=v\n\
		end\n\
	end\n\
	local st, err = os.stat(path)\n\
	if not st then\n\
		return false, err\n\
	end\n\
	\n\
	local b=msg_batcher{\n\
		batchsize=opts.msglimit,\n\
		timeout=opts.msgtimeout\n\
	}\n\
	\n\
	if not st.is_dir then\n\
		if opts.dirsonly then\n\
			return false, 'not a directory'\n\
		end\n\
		if opts.stat == '*' then\n\
			st.name=path\n\
			b:write(st)\n\
		else\n\
			b:write(path)\n\
		end\n\
		b:flush()\n\
		return true\n\
	end\n\
	\n\
	if os.idir then\n\
		for v in os.idir(path,opts.listall) do\n\
			local status,err=ls_single(opts,b,path,v)\n\
			if not status then\n\
				return false, err\n\
			end\n\
		end\n\
	else\n\
		local t,msg=os.listdir(path,opts.listall)\n\
		if not t then\n\
			return false,msg\n\
		end\n\
		for i,v in ipairs(t) do\n\
			local status,err=ls_single(opts,b,path,v)\n\
			if not status then\n\
				return false, err\n\
			end\n\
		end\n\
	end\n\
	b:flush()\n\
	return true\n\
end\n"

#define PTP_CHDK_LUA_RLIB_SHOOT_COMMON \
"function rlib_shoot_init_exp(opts)	\n\
	if opts.tv then\n\
		set_tv96_direct(opts.tv)\n\
	end\n\
	if opts.sv then\n\
		set_sv96(opts.sv)\n\
	end\n\
	if opts.svm then\n\
		if type(sv96_market_to_real) ~= 'function' then\n\
			error('svm not supported')\n\
		end\n\
		set_sv96(sv96_market_to_real(opts.svm))\n\
	end\n\
	if opts.isomode then\n\
		set_iso_mode(opts.isomode)\n\
	end\n\
	if opts.av then\n\
		set_av96_direct(opts.av)\n\
	end\n\
	if opts.nd then\n\
		set_nd_filter(opts.nd)\n\
	end\n\
	if opts.sd then\n\
		set_focus(opts.sd)\n\
	end\n\
end\n"

#define PTP_CHDK_LUA_RLIB_SHOOT \
PTP_CHDK_LUA_RLIB_SHOOT_COMMON \
"function rlib_shoot(opts)\n\
	local rec,vid = get_mode()\n\
	if not rec then\n\
		return false,'not in rec mode'\n\
	end\n\
\n\
	rlib_shoot_init_exp(opts)\n\
\n\
	local save_raw\n\
	if opts.raw then\n\
		save_raw=get_raw()\n\
		set_raw(opts.raw)\n\
	end\n\
	local save_dng\n\
	if opts.dng then\n\
		save_dng=get_config_value(226)\n\
		set_config_value(226,opts.dng)\n\
	end\n\
	shoot()\n\
	local r\n\
	if opts.info then\n\
		r = {\n\
			dir=get_image_dir(),\n\
			exp=get_exp_count(),\n\
			raw=(get_raw() == 1),\n\
		}\n\
		if r.raw then\n\
			r.raw_in_dir = (get_config_value(35) == 1)\n\
			r.raw_pfx = get_config_value(36)\n\
			r.raw_ext = get_config_value(37)\n\
			r.dng = (get_config_value(226) == 1)\n\
			if r.dng then\n\
				r.use_dng_ext = (get_config_value(234) == 1)\n\
			end\n\
		end\n\
	else\n\
		r=true\n\
	end\n\
	if save_raw then\n\
		set_raw(save_raw)\n\
	end\n\
	if save_dng then\n\
		set_config_value(226,save_dng)\n\
	end\n\
	return r\n\
end\n"



// bit flags for script start
#define PTP_CHDK_SCRIPT_FL_NOKILL           0x100 // if script is running return error instead of killing
#define PTP_CHDK_SCRIPT_FL_FLUSH_CAM_MSGS   0x200 // discard existing cam->host messages before starting
#define PTP_CHDK_SCRIPT_FL_FLUSH_HOST_MSGS  0x400 // discard existing host->cam messages before starting

// bit flags for script status
#define PTP_CHDK_SCRIPT_STATUS_RUN   0x1 // script running
#define PTP_CHDK_SCRIPT_STATUS_MSG   0x2 // messages waiting
// bit flags for scripting support
#define PTP_CHDK_SCRIPT_SUPPORT_LUA  0x1


// bit flags for remote capture
// used to select and also to indicate available data in PTP_CHDK_RemoteCaptureIsReady
/*
Full jpeg file. Note supported on all cameras, use Lua get_usb_capture_support to check
*/
#define PTP_CHDK_CAPTURE_JPG    0x1 

/*
Raw framebuffer data, in camera native format.
A subset of rows may be requested in init_usb_capture.
*/
#define PTP_CHDK_CAPTURE_RAW    0x2

/*
DNG header. 
The header will be DNG version 1.3
Does not include image data, clients wanting to create a DNG file should also request RAW
Raw data for all known cameras will be packed, little endian. Client is responsible for
reversing the byte order if creating a DNG.
Can requested without RAW to get sensor dimensions, exif values etc.

ifd 0 specifies a 128x96 RGB thumbnail, 4 byte aligned following the header
client is responsible for generating thumbnail data.

ifd 0 subifd 0 specifies the main image
The image dimensions always contain the full sensor dimensions, if a sub-image was requested
with init_usb_capture, the client is responsible for padding the data to the full image or
adjusting dimensions.

Bad pixels will not be patched, but DNG opcodes will specify how to patch them
*/
#define PTP_CHDK_CAPTURE_DNGHDR 0x4  

// status from PTP_CHDK_RemoteCaptureIsReady if capture not enabled
#define PTP_CHDK_CAPTURE_NOTSET 0x10000000

// message types
enum ptp_chdk_script_msg_type {
    PTP_CHDK_S_MSGTYPE_NONE = 0, // no messages waiting
    PTP_CHDK_S_MSGTYPE_ERR,      // error message
    PTP_CHDK_S_MSGTYPE_RET,      // script return value
    PTP_CHDK_S_MSGTYPE_USER,     // message queued by script
// TODO chdk console data ?
};

// error subtypes for PTP_CHDK_S_MSGTYPE_ERR and script startup status
enum ptp_chdk_script_error_type {
    PTP_CHDK_S_ERRTYPE_NONE = 0,
    PTP_CHDK_S_ERRTYPE_COMPILE,
    PTP_CHDK_S_ERRTYPE_RUN,
    // the following are for ExecuteScript status only, not message types
    PTP_CHDK_S_ERR_SCRIPTRUNNING = 0x1000, // script already running with NOKILL
};

// message status
enum ptp_chdk_script_msg_status {
    PTP_CHDK_S_MSGSTATUS_OK = 0, // queued ok
    PTP_CHDK_S_MSGSTATUS_NOTRUN, // no script is running
    PTP_CHDK_S_MSGSTATUS_QFULL,  // queue is full
    PTP_CHDK_S_MSGSTATUS_BADID,  // specified ID is not running
};

#endif // __CHDK_PTP_H