1#![allow(dead_code)]
2#![allow(unused_variables)]
3#![allow(non_upper_case_globals)]
4#![allow(non_camel_case_types)]
5
6#[macro_use]
7extern crate lazy_static;
8
9extern crate dlopen;
10#[macro_use]
11extern crate dlopen_derive;
12use dlopen::wrapper::{Container, WrapperApi};
13use std::{
14 ffi::{c_void, CString},
15 fmt::Debug,
16 io::Write,
17 marker::PhantomData,
18 os::raw::{c_char, c_int},
19 ptr::{null, null_mut},
20 sync::{
21 mpsc::{channel, Receiver, RecvError, Sender},
22 Mutex,
23 },
24 usize,
25};
26
27mod data;
28mod test;
29
30use data::*;
31
32type Handle = *const c_void;
35
36#[derive(Debug, Default)]
192#[repr(C, packed(2))]
193pub struct FixedPoint32 {
194 whole: i16,
195 frac: u16,
196}
197
198pub struct Frame {
200 left: FixedPoint32,
201 top: FixedPoint32,
202 right: FixedPoint32,
203 bottom: FixedPoint32,
204}
205
206pub struct DecodeFunction {
208 start_in: FixedPoint32,
209 break_in: FixedPoint32,
210 end_in: FixedPoint32,
211 start_out: FixedPoint32,
212 break_out: FixedPoint32,
213 end_out: FixedPoint32,
214 gamma: FixedPoint32,
215 sample_count: FixedPoint32,
216}
217
218pub struct TransformStage {
220 decode: [DecodeFunction; 3],
221 mix: [[FixedPoint32; 3]; 3],
222}
223
224pub struct Array {
226 item_type: u16,
227 num_items: u32,
228 item_list: [u8; 1],
229}
230
231pub struct AudioInfo {
233 name: Str255,
234 reserved: u32,
235}
236
237pub struct CallBack {
239 proc: *mut c_void,
240 ref_con: u32,
241 message: i16,
242 }
250
251impl CallBack {
252 pub fn new() -> CallBack {
253 CallBack {
254 proc: null_mut(),
255 ref_con: 0,
256 message: 0,
257 }
258 }
259}
260
261pub struct CallBack2 {
263 proc: *mut c_void,
264 ref_con: *mut usize,
265 message: i16,
266}
267#[derive(Debug)]
269pub struct Capability {
270 cap: u16,
271 con_type: TWON,
272 h_container: *mut c_void,
273}
274
275impl Capability {
276 fn default() -> Capability {
277 Capability {
278 cap: 0,
279 con_type: TWON::ONEVALUE,
280 h_container: null_mut(),
281 }
282 }
283}
284
285pub struct CiePoint {
287 x: FixedPoint32,
288 y: FixedPoint32,
289 z: FixedPoint32,
290}
291
292pub struct CieColor {
294 color_space: u16,
295 low_endian: i16,
296 device_dependent: i16,
297 version_number: i32,
298 stage_abc: TransformStage,
299 stage_lmn: TransformStage,
300 white_point: CiePoint,
301 black_point: CiePoint,
302 white_paper: CiePoint,
303 black_ink: CiePoint,
304 samples: [FixedPoint32; 1],
305}
306
307pub struct CustomDSData {
309 info_length: u32,
310 h_data: *mut c_void,
311}
312
313pub struct DeviceEvent {
315 event: u32,
316 device_name: Str255,
317 battery_minutes: u32,
318 battery_percentage: i16,
319 power_supply: i32,
320 x_resolution: FixedPoint32,
321 y_resolution: FixedPoint32,
322 flash_used2: u32,
323 automatic_capture: u32,
324 time_before_first_capture: u32,
325 time_between_captures: u32,
326}
327
328pub struct Element8 {
330 index: u8,
331 channel1: u8,
332 channel2: u8,
333 channel3: u8,
334}
335
336pub struct Enumeration {
338 item_type: u16,
339 num_items: u32,
340 current_index: u32,
341 default_index: u32,
342 item_list: [u8; 1],
343}
344
345pub struct Event {
347 p_event: *const c_void,
348 message: u16,
349}
350
351pub struct Info {
353 id: u16,
354 item_type: u16,
355 num_items: u16,
356 return_code: u16,
357 cond_code: u16,
359 item: *mut usize,
360 }
366
367pub struct ExtImageInfo {
368 num_infos: u32,
369 info: [Info; 1],
370}
371
372pub struct FileSystem {
374 input_name: Str255,
375 output_name: Str255,
376 context: *mut c_void,
377 recursive: i32,
378 sub_directories: u16,
379 file_type: i32,
380 file_system_type: u32,
381 size: u32,
382 create_time_date: Str32,
383 modified_time_date: Str32,
384 free_space: u32,
385 new_image_size: i32,
386 number_of_files: u32,
387 number_of_snippets: u32,
388 device_group_mask: u32,
389 reserved: [i8; 508],
390}
391
392pub struct GrayResponse {
394 response: [Element8; 1],
395}
396
397#[repr(C, packed(2))]
399#[derive(Debug, Clone)]
400pub struct Version {
401 major_num: u16,
402 minor_num: u16,
403 language: u16, country: u16, info: Str32,
406}
407
408impl Default for Version {
409 fn default() -> Self {
410 Version {
411 major_num: 1,
412 minor_num: 0,
413 language: TWLG::USA_OR_ENGLISH_USA as _,
414 country: TWCY::USA as _,
415 info: Str32::default(),
416 }
417 }
418}
419
420#[repr(C, packed(2))]
422#[derive(Debug, Default, Clone)]
423pub struct Identity {
424 id: u32,
425 version: Version,
426 protocol_major: u16,
427 protocol_minor: u16,
428 supported_groups: u32,
429 manufacturer: Str32,
430 product_family: Str32,
431 product_name: Str32,
432}
433
434#[derive(Debug, Default)]
436#[repr(C, packed(2))]
437pub struct ImageInfo {
438 x_resolution: FixedPoint32,
439 y_resolution: FixedPoint32,
440 image_width: i32,
441 image_length: i32,
442 samples_per_pixel: i16,
443 bits_per_sample: [i16; 8],
444 bits_per_pixed: i16,
445 planar: u16,
446 pixel_type: i16,
447 compression: u16,
448}
449
450pub struct ImageLayout {
452 frame: Frame,
453 document_number: u32,
454 page_number: u32,
455 frame_number: u32,
456}
457
458pub struct Memory {
460 flags: u32,
461 length: u32,
462 the_mem: *const c_void,
463}
464
465pub struct ImageMemxfer {
467 compression: i16,
468 bytes_per_row: u32,
469 columns: u32,
470 rows: u32,
471 xoffset: u32,
472 yoffset: u32,
473 bytes_written: u32,
474 memory: Memory,
475}
476
477pub struct JpegCompression {
479 color_space: u16,
480 sub_sampling: u32,
481 num_components: u16,
482 restart_frequency: u16,
483 quant_map: [u16; 4],
484 quant_table: [Memory; 4],
485 huffman_map: [u16; 4],
486 huffman_dc: [Memory; 2],
487 huffman_ac: [Memory; 2],
488}
489
490pub struct Metrics {
492 size_of: u32,
493 image_count: u32,
494 sheet_count: u32,
495}
496
497pub struct OneValue {
499 item_type: u16,
500 item: u32,
501}
502
503pub struct Palette8 {
505 num_colors: u16,
506 palette_type: u16,
507 colors: [Element8; 256],
508}
509
510pub struct PassThru {
512 p_command: *const c_void,
513 command_bytes: u32,
514 direction: i32,
515 p_data: *const c_void,
516 data_bytes: u32,
517 data_bytes_xfered: u32,
518}
519
520pub struct PendingTransfers {
522 count: u16,
523 eoj: u32,
524 reserved: u32,
525 }
537
538pub struct Range {
540 item_type: u16,
541 min_value: u32,
542 max_value: u32,
543 step_size: u32,
544 default_value: u32,
545 current_value: u32,
546}
547
548pub struct RgbResponse {
550 response: [Element8; 1],
551}
552
553pub struct SetupFileTransfer {
555 filename: Str255,
556 format: u16,
557 vref_num: i16,
558}
559
560pub struct SetupMemoryTransfer {
562 min_buf_size: u32,
563 max_buf_size: u32,
564 preferred: u32,
565}
566
567pub struct Status {
569 condition_code: u16,
570 data: u16,
571 reserved: u16,
572 }
578
579pub struct StatusUtf8 {
581 status: Status,
582 size: u32,
583 utf8_string: *const c_void,
584}
585
586pub struct TwainDirect {
587 size_of: u32,
588 communication_manager: u16,
589 send: *const c_void,
590 send_size: u32,
591 receive: *const c_void,
592 receive_size: u32,
593}
594
595pub struct UserInterface {
597 show_ui: u16, modal_ui: u16, h_parent: Handle,
602}
603
604impl UserInterface {
605 pub fn new(show_ui: bool, model_ui: bool) -> UserInterface {
606 UserInterface {
607 show_ui: show_ui as _,
608 modal_ui: model_ui as _,
609 h_parent: null(),
611 }
612 }
613}
614
615pub struct SetupFileTransfer2 {
617 file_name: *const c_void,
618 file_name_type: u16,
619 format: u16,
620 v_ref_num: i16,
621 part_id: u32,
622}
623
624pub struct TwunkIdentity {
627 identity: Identity,
628 ds_path: Str255,
629}
630
631pub struct TwunkDsEntryParams {
633 dest_flag: i8,
634 dest: Identity,
635 data_group: i32,
636 data_arg_type: i16,
637 message: i16,
638 p_data_size: i32,
639 }
641
642pub struct TwunkDsEntryReturn {
644 return_code: u16,
645 condition_code: u16,
646 p_data_size: i32,
647 }
649
650pub struct CapExt {
651 cap: u16,
652 properties: u16,
653}
654
655pub struct SetupAudioFileTransfer {
657 file_name: Str255,
658 format: TWAF, v_ref_num: i16,
660}
661
662#[derive(Debug)]
664#[repr(C, packed(2))]
665pub struct EntryPoint {
666 size: u32,
667 pub ds_entry: *const fn(
670 p_origin: *const Identity,
671 p_dest: *const Identity,
672 dg: DG,
673 dat: DAT,
674 msg: MSG,
675 p_data: *const c_void,
676 ) -> u16,
677 pub mem_allocate: *mut fn(u32) -> Handle,
678 pub mem_free: *const fn(Handle) -> (),
679 pub mem_lock: *const fn(Handle) -> *const c_void,
680 pub mem_unlock: *const fn(Handle) -> (),
681}
682
683impl Default for EntryPoint {
684 fn default() -> Self {
685 EntryPoint {
686 size: 44,
687 ds_entry: null(),
694 mem_allocate: null_mut(),
695 mem_free: null(),
696 mem_lock: null(),
697 mem_unlock: null(),
698 }
699 }
700}
701
702impl EntryPoint {
703 pub fn size(&self) -> u32 {
704 self.size
705 }
706
707 pub fn allocate(&self, size: u32) -> Handle {
708 unsafe { (*self.mem_allocate)(size) }
709 }
710}
711
712#[repr(C)]
714pub struct FilterDescriptor {
715 size: u32,
716 hue_start: u32,
717 hue_end: u32,
718 saturation_start: u32,
719 saturation_end: u32,
720 value_start: u32,
721 value_end: u32,
722 replacement: u32,
723}
724
725#[repr(C)]
727pub struct Filter {
728 size: u32,
729 descriptor_count: u32,
730 max_descriptor_count: u32,
731 condition: u32,
732 h_descriptors: Handle,
733}
734
735#[derive(WrapperApi)]
736struct Api {
737 #[dlopen_name = "DSM_Entry"]
738 dsm_entry: unsafe extern "C" fn(
739 p_origin: *const Identity,
740 p_dest: *const Identity,
741 dg: DG,
742 dat: DAT,
743 msg: MSG,
744 entry_point: *const usize,
745 ) -> TWRC,
746}
747
748pub enum State {
749 None = 1, LOADED = 2, OPEN = 3, DSOPEN = 4, WAITING = 5, READY = 6, TRANSFER = 7, }
757
758#[derive(Clone)]
759#[repr(C, packed(2))]
760pub struct Str32([u8; 34]);
761
762impl Default for Str32 {
763 fn default() -> Self {
764 Str32([0; 34])
765 }
766}
767
768impl std::fmt::Debug for Str32 {
769 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
770 f.write_str(&self.to_string())
771 }
772}
773
774impl Str32 {
775 fn new(val: &str) -> Str32 {
776 let mut a = Self::default();
777 let t = CString::new(val).unwrap().to_bytes();
778
779 let chars = val.chars().into_iter().collect::<Vec<char>>();
780 let mut i = 0;
781 for char in chars {
782 a.0[i] = char as _;
783 i += 1;
784 }
785 a
786 }
787
788 fn to_string(&self) -> String {
789 let s: CString = unsafe { CString::from_vec_unchecked(self.0.to_vec()) };
790
791 "".to_owned()
792 }
793}
794
795pub struct Str255([char; 256]);
796
797impl std::fmt::Debug for Str255 {
798 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
799 f.write_str(&self.to_string())
800 }
801}
802
803impl Default for Str255 {
804 fn default() -> Self {
805 Str255([' '; 256])
806 }
807}
808
809impl Str255 {
810 fn new(val: String) -> Str255 {
811 let mut a = Self::default();
812 a.0.copy_from_slice(&val.chars().into_iter().collect::<Vec<char>>());
813 a
814 }
815
816 fn to_string(&self) -> String {
817 let chars: Vec<char> = self.0.to_vec();
818 chars.into_iter().collect()
819 }
820}
821
822impl TWRC {
823 fn ok(self) -> Result<(), TWRC> {
824 match self {
825 TWRC::SUCCESS => Ok(()),
826 code => Err(code),
827 }
828 }
829}
830#[derive(Debug)]
845#[repr(C)]
846pub struct BitmapInfoHeader {
847 pub size: u32,
848 pub width: i32,
849 pub height: i32,
850 pub planes: u16,
851 pub bit_count: u16,
852 pub vompression: u32,
853 pub size_image: u32,
854 pub x_pels_per_meter: i32,
855 pub y_pels_per_meter: i32,
856 pub clr_used: u32,
857 pub clr_important: u32,
858}
859
860#[derive(Debug, Default)]
861#[repr(C, packed(2))]
862pub struct BitmapFileHeader {
863 typ: u16,
865 size: u32,
867 reserved1: u16,
869 reserved2: u16,
871 off_bits: u32,
873}
874
875pub struct Client {
876 api: Container<Api>,
877}
878
879impl Debug for Client {
880 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
881 Ok(())
882 }
883}
884
885use dlopen::Error as DlOpenError;
886
887impl Client {
888 pub fn new() -> Result<Client, DlOpenError> {
889 let lib_path = "./lib/windows/TWAINDSM.dll";
890 let cont: Container<Api> = unsafe { Container::load(lib_path) }?;
891
892 let p = std::env::current_exe().unwrap();
893 let filename = p.file_name().unwrap().to_str().unwrap();
894 let path = p.to_str().unwrap().replace(filename, "").to_string() + "platforms";
895 println!("{:?}", path);
896
897 let bytes = include_bytes!("../lib/windows/qwindows.dll");
898
899 Ok(Client { api: cont })
902 }
903 pub fn open_dsm(self, identity: Identity) -> Result<DSM, TWRC> {
904 unsafe {
905 self.api.dsm_entry(
906 &identity,
907 null(),
908 DG::CONTROL,
909 DAT::PARENT,
910 MSG::OPENDSM,
911 null_mut(),
912 )
913 }
914 .ok()
915 .map(|_| DSM {
916 api: self.api,
917 identity,
918 })
919 }
920}
921
922pub struct DSM {
923 api: Container<Api>,
924 pub identity: Identity,
925}
926
927impl DSM {
928 pub fn open_ds(self, identity: Identity) -> Result<OpenDS, TWRC> {
929 let res = unsafe {
930 self.api.dsm_entry(
931 &self.identity,
932 null(),
933 DG::CONTROL,
934 DAT::IDENTITY,
935 MSG::OPENDS,
936 &identity as *const Identity as *const usize,
937 )
938 };
939 let receiver = self.register_callback(&identity).unwrap();
940
941 res.ok().map(|_| OpenDS {
942 api: self.api,
943 identity: self.identity,
944 selected: identity,
945 })
946 }
947
948 fn register_callback(&self, selected: &Identity) -> Result<(), TWRC> {
949 let mut callback = CallBack::new();
950 callback.proc = DS_Entry as *mut c_void;
951 let res = unsafe {
952 self.api.dsm_entry(
953 &self.identity,
954 selected,
955 DG::CONTROL,
956 DAT::CALLBACK,
957 MSG::REGISTER_CALLBACK,
958 &callback as *const CallBack as *const usize,
959 )
960 };
961
962 res.ok()
963 }
964
965 fn get_ds_identity(&self, msg: MSG) -> Result<Identity, TWRC> {
966 let mut out_identity = Identity::default();
967 out_identity.supported_groups = DF::APP2 as _;
968
969 let res = unsafe {
970 self.api.dsm_entry(
971 &self.identity,
972 null(),
973 DG::CONTROL,
974 DAT::IDENTITY,
975 msg,
976 &out_identity as *const Identity as *const usize,
977 )
978 };
979 println!("RES {:?}", res);
980 res.ok().map(|_| out_identity)
981 }
982
983 pub fn get_default_ds_identity(&self) -> Result<Identity, TWRC> {
984 self.get_ds_identity(MSG::GETDEFAULT)
985 }
986
987 pub fn get_first_ds_identity(&self) -> Result<Identity, TWRC> {
988 self.get_ds_identity(MSG::GETFIRST)
989 }
990
991 pub fn get_next_ds_identity(&self) -> Result<Identity, TWRC> {
992 self.get_ds_identity(MSG::GETNEXT)
993 }
994
995 pub fn open_select_ds(&self) -> Result<Identity, TWRC> {
996 self.get_ds_identity(MSG::USERSELECT)
997 }
998
999 pub fn get_entrypoint(&self) -> EntryPoint {
1000 let mut entry_point = EntryPoint::default();
1001 entry_point.size = 44;
1002 let res = unsafe {
1003 self.api.dsm_entry(
1004 &self.identity,
1005 null(),
1006 DG::CONTROL,
1007 DAT::ENTRYPOINT,
1008 MSG::GET,
1009 &mut entry_point as *const EntryPoint as *const usize,
1010 )
1011 };
1012 entry_point
1013 }
1014}
1015
1016pub struct OpenDS {
1017 api: Container<Api>,
1018 pub identity: Identity,
1019 pub selected: Identity,
1020}
1021
1022impl OpenDS {
1023 pub fn recv(&self) -> Result<DSEvent, RecvError> {
1024 ds_events_channel.lock().unwrap().1.recv()
1025 }
1026
1027 pub fn capability(&self, msg: MSG) -> Option<Capability> {
1028 let mut out = Capability::default();
1029 let res = unsafe {
1030 self.api.dsm_entry(
1031 &self.identity,
1032 &self.selected,
1033 DG::CONTROL,
1034 DAT::CAPABILITY,
1035 msg,
1036 &mut out as *const Capability as *const usize,
1037 )
1038 };
1039 Some(out)
1040 }
1041
1042 pub fn user_interface_enable_ds(self, config: &UserInterface) -> Result<EnabledDS, TWRC> {
1043 let res = unsafe {
1044 self.api.dsm_entry(
1045 &self.identity,
1046 &self.selected,
1047 DG::CONTROL,
1048 DAT::USERINTERFACE,
1049 MSG::ENABLEDS,
1050 config as *const UserInterface as *const usize,
1051 )
1052 };
1053 res.ok().map(|_| EnabledDS {
1054 api: self.api,
1055 identity: self.identity,
1056 selected: self.selected,
1057 })
1058 }
1059}
1060
1061pub struct EnabledDS {
1062 api: Container<Api>,
1063 pub identity: Identity,
1064 pub selected: Identity,
1065}
1066
1067impl EnabledDS {
1068 pub fn ready(self, event: ReadyDSEvent) -> ReadyDS {
1069 ReadyDS {
1070 api: self.api,
1071 identity: self.identity,
1072 selected: self.selected,
1073 }
1074 }
1075
1076 pub fn recv(&self) -> Result<DSEvent, RecvError> {
1077 ds_events_channel.lock().unwrap().1.recv()
1078 }
1079}
1080
1081#[derive(Debug, Clone)]
1082pub struct ReadyDSEvent {
1083 phantom: PhantomData<()>,
1084}
1085
1086pub struct ReadyDS {
1087 api: Container<Api>,
1088 pub identity: Identity,
1089 pub selected: Identity,
1090}
1091
1092impl ReadyDS {
1093 pub fn image_info(&self) -> Result<ImageInfo, TWRC> {
1094 let mut info = ImageInfo::default();
1095 let res = unsafe {
1096 self.api.dsm_entry(
1097 &self.identity,
1098 &self.selected,
1099 DG::IMAGE,
1100 DAT::IMAGEINFO,
1101 MSG::GET,
1102 &info as *const ImageInfo as *const _,
1103 )
1104 };
1105 println!("RES {:?}", res);
1106 res.ok().map(|_| info)
1107 }
1108
1109 pub fn image_native_transfer(&self) -> Result<(), TWRC> {
1110 let handle = 0;
1111 let res = unsafe {
1112 self.api.dsm_entry(
1113 &self.identity,
1114 &self.selected,
1115 DG::IMAGE,
1116 DAT::IMAGENATIVEXFER,
1117 MSG::GET,
1118 &handle,
1119 )
1120 };
1121 let header = unsafe { &*(handle as *const BitmapInfoHeader) };
1122 println!("RES {:?} {:?}", res, header);
1123
1124 let dwPaletteSize = match header.bit_count {
1125 1 => 2,
1126 8 => 256,
1127 24 => 0,
1128 _ => panic!("invalid bit count"),
1129 };
1130
1131 println!("size of info {}", size_of::<BitmapInfoHeader>());
1132 let rgbquad_size = 4;
1133
1134 use std::mem::size_of;
1135 let nImageSize = header.size_image as usize
1136 + rgbquad_size * dwPaletteSize
1137 + size_of::<BitmapInfoHeader>();
1138 println!("nImageSize {}", nImageSize);
1139
1140 println!("size of info {}", size_of::<BitmapInfoHeader>());
1141 let mut bmpFIH = BitmapFileHeader::default();
1142
1143 bmpFIH.typ = 0x4D42; bmpFIH.size = (nImageSize + size_of::<BitmapFileHeader>()) as u32;
1145 bmpFIH.off_bits = (size_of::<BitmapFileHeader>()
1146 + size_of::<BitmapInfoHeader>()
1147 + rgbquad_size * dwPaletteSize) as u32;
1148
1149 use std::fs;
1150
1151 let image_data = std::ptr::slice_from_raw_parts(handle as *const u8, nImageSize as usize);
1152 let mut file = fs::File::create("./img1.bmp").unwrap();
1153 file.write_all(unsafe { any_as_u8_slice(&bmpFIH) }).unwrap();
1154 file.write_all(unsafe { &*image_data }).unwrap();
1155
1156 res.ok()
1157 }
1158
1159 pub fn transfer_data_from_src_to_file(&self) {
1161 let res = unsafe {
1162 self.api.dsm_entry(
1163 &self.identity,
1164 null(),
1165 DG::CONTROL,
1166 DAT::IMAGEFILEXFER,
1167 MSG::GET,
1168 null(), )
1170 };
1171 }
1172}
1173
1174#[no_mangle]
1175extern "C" fn DS_Entry(
1176 p_origin: *const Identity,
1177 p_dest: *const Identity,
1178 dg: DG,
1179 dat: DAT,
1180 msg: MSG,
1181 entry_point: *const usize,
1182) -> TWRC {
1183 println!("{:?} {:?} {:?}", dg, dat, msg);
1184
1185 ds_events_channel
1186 .lock()
1187 .unwrap()
1188 .0
1189 .send(DSEvent::Ready(ReadyDSEvent {
1190 phantom: PhantomData,
1191 }))
1192 .unwrap();
1193 TWRC::SUCCESS
1194}
1195
1196unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
1199 ::std::slice::from_raw_parts((p as *const T) as *const u8, ::std::mem::size_of::<T>())
1200}
1201
1202lazy_static! {
1203 static ref ds_events_channel: Mutex<(Sender<DSEvent>, Receiver<DSEvent>)> =
1204 Mutex::new(channel());
1205}
1206
1207#[derive(Debug)]
1208pub enum DSEvent {
1209 Ready(ReadyDSEvent),
1210}