Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. #!/usr/bin/perl
  2. # -------------------------------------------------------
  3. #   RICOH THETA Remote shutter
  4. # -------------------------------------------------------
  5. #  RICOH THETA HACKS! - MobileHackerz
  6. #  http://mobilehackerz.jp/contents/Review/RICOH_THETA
  7. #
  8. # This program is free software. It comes without any warranty, to
  9. # the extent permitted by applicable law. You can redistribute it
  10. # and/or modify it under the terms of the Do What The Fuck You Want
  11. # To Public License, Version 2, as published by Sam Hocevar. See
  12. # http://www.wtfpl.net/txt/copying/ for more details.
  13.  
  14. use IO::Socket;
  15. #use Encode;
  16.  
  17. # ----- TARGET THETA
  18. my $Addr = "192.168.1.1";
  19. my $Port = 15740;
  20.  
  21. # ----- My profile
  22. my $Name = "THETA_Shutter";
  23. my $GUID = "8a7ab04f-ebda-4f33-8649-8bf8c1cdc838";
  24.  
  25.  
  26. my ($command_sock, $event_sock, $result, $session_id, $transaction_id, $payload, $data, $handle);
  27.  
  28. # Init_Command
  29. $command_sock = &PTPIP_Open_Connection;
  30. &PTPIP_Init_Command_Request($command_sock);
  31. ($result, $session_id) = &PTPIP_Wait_Init_Command_Ack($command_sock);
  32. if ($result == 0) { die "No Init_Command_Ack"; }
  33.  
  34. # Init_Event
  35. $event_sock = &PTPIP_Open_Connection;
  36. &PTPIP_Init_Event_Request($event_sock,$session_id);
  37. ($result) = &PTPIP_Wait_Event_Request_Ack($event_sock);
  38. if ($result == 0) { die "No Init_Event_Ack"; }
  39. $transaction_id = 0;
  40.  
  41. # PTP_OC_OpenSession
  42. &PTPIP_Cmd_Request($command_sock, $transaction_id++, "",  0x1002, $session_id );
  43. ($result,$payload,$data) = &PTPIP_Wait_Cmd_Response($command_sock);
  44. if ($result == 0) { die "No Cmd_Response"; }
  45.  
  46. #&InitiateCapture(-2000);
  47. &InitiateCapture(0);
  48. #&InitiateCapture(2000);
  49.  
  50. &PTPIP_Close_Connection($event_sock);
  51. &PTPIP_Close_Connection($command_sock);
  52. exit;
  53.  
  54.  
  55. # -------------------------------------------------------
  56. #   Initiate Capture
  57. # -------------------------------------------------------
  58. # EV shift: 2000,1700,1300,1000,700,300,0,-300,-700,-1000,-1300,-1700,-2000
  59.  
  60. sub InitiateCapture {
  61.     my $evshift = shift;
  62.     my ($result, $payload, $data);
  63.     my ($event , @params, $loop, $handle);
  64.  
  65.     # PTP_OC_SetDevicePropValue (EV shift)
  66.     $payload = pack("v",($evshift));
  67.     &PTPIP_Cmd_Request($command_sock, $transaction_id++, $payload, 0x1016, 0x5010);
  68.     ($result,$payload,$data) = &PTPIP_Wait_Cmd_Response($command_sock);
  69.     if ($result == 0) { die "No Cmd_Response"; }
  70.  
  71.     # PTP_OC_InitiateCapture
  72.     &PTPIP_Cmd_Request($command_sock, $transaction_id++, "", 0x100E, 0, 0 );
  73.     ($result,$payload,$data) = &PTPIP_Wait_Cmd_Response($command_sock);
  74.     if ($result == 0) { die "No Cmd_Response"; }
  75.  
  76.     # Wait PTP_EC_CaptureComplete
  77.     $handle = 0;
  78.     for($loop=0;$loop<20;$loop++) {
  79.         ($event,@params) = &PTPIP_Wait_Event($event_sock,0.5);
  80.         if ($event == 0x400D) {
  81.             # CaptureComplete
  82.             last;
  83.         } elsif ($event == 0x4002) {
  84.             # Object Added
  85.             $handle = $params[0];
  86.         }
  87.     }
  88.  
  89.     # PTP_OC_SetDevicePropValue (EV shift = 0)
  90.     $payload = pack("v",0);
  91.     &PTPIP_Cmd_Request($command_sock, $transaction_id++, $payload, 0x1016, 0x5010);
  92.     ($result,$payload,$data) = &PTPIP_Wait_Cmd_Response($command_sock);
  93.     if ($result == 0) { die "No Cmd_Response"; }
  94.     $handle;
  95. }
  96.  
  97.  
  98. # -------------------------------------------------------
  99. #   Init_Command
  100. # -------------------------------------------------------
  101.  
  102. sub PTPIP_Init_Command_Request {
  103.     my $sock = shift;
  104.  
  105.     my $payload = "";
  106.     $payload .= pack("H8H4H4H4H12",split('-',$GUID));  # GUID
  107.     $payload .= Encode_UTF16LE($Name."\x00");
  108.     $payload .= pack("V",1);
  109.  
  110.     print $sock &PTPIP_pack_command( 1, $payload);
  111. }
  112.  
  113. sub PTPIP_Wait_Init_Command_Ack {
  114.     my $sock = shift;
  115.     my ($result,$session_id,$target_guid,$target_name,$unknown1);
  116.     my @error_response = (0,0);
  117.  
  118.     my ($cmd,$payload) = &PTPIP_Recv_Response($sock);
  119.     if ($cmd != 2) { return @error_response; }
  120.  
  121.     $session_id  = unpack("V",$payload);
  122.     $payload     = substr($payload,4);
  123.     my (@guid)   = unpack("H8H4H4H4H12",$payload);
  124.     $target_guid = join('-',@guid);
  125.     $payload     = substr($payload,16);
  126.     $target_name = Decode_UTF16LE(substr($payload,0,-4));
  127.     $payload     = substr($payload,-4);
  128.     $unknown1    = unpack("V",$payload);
  129.  
  130.     print "Target GUID :".$target_guid."\n";
  131.     print "Target Name :".$target_name."\n";
  132.  
  133.     (1, $session_id);
  134. }
  135.  
  136. # -------------------------------------------------------
  137. #   Init_Event
  138. # -------------------------------------------------------
  139.  
  140. sub PTPIP_Init_Event_Request {
  141.     my $sock = shift;
  142.     my $session_id = shift;
  143.  
  144.     my $payload = "";
  145.     $payload .= pack("V",$session_id);
  146.  
  147.     print $sock &PTPIP_pack_command( 3, $payload);
  148. }
  149.  
  150. sub PTPIP_Wait_Event_Request_Ack {
  151.     my $sock = shift;
  152.     my @error_response = (0);
  153.     my ($cmd,$payload) = &PTPIP_Recv_Response($sock);
  154.     if ($cmd != 4) { return @error_response; }
  155.  
  156.     1;
  157. }
  158.  
  159. # -------------------------------------------------------
  160. #   Wait_Event
  161. # -------------------------------------------------------
  162.  
  163. sub PTPIP_Wait_Event {
  164.     my $sock = shift;
  165.     my $wait = shift;
  166.     my ($rin,$event_id,$transaction_id,@params);
  167.     my @error_response = (0);
  168.    
  169.     $rin = "";
  170.     vec($rin, fileno($sock), 1)=1;
  171.     if (select($rin,undef,undef,$wait)) {
  172.         my ($cmd,$payload) = &PTPIP_Recv_Response($sock);
  173.         if ($cmd != 8) { return @error_response; }
  174.  
  175.         $event_id       = unpack("v",$payload);
  176.         $payload        = substr($payload,2);
  177.         @params         = unpack("V*",$payload);
  178.         $transaction_id = shift(@params);
  179.  
  180.         ($event_id, @params);
  181.     } else {
  182.         # no event
  183.         @error_response;
  184.     }
  185. }
  186.  
  187.  
  188. # -------------------------------------------------------
  189. #   Cmd_Request
  190. # -------------------------------------------------------
  191.  
  192. sub PTPIP_Cmd_Request {
  193.     my $sock = shift;
  194.     my $transaction_id = shift;
  195.     my $send_payload = shift;
  196.     my $cmd  = shift;
  197.     my @args = @_;
  198.  
  199.     my $payload = "";
  200.     $payload .= pack("V",1);
  201.     $payload .= pack("v",$cmd);
  202.     $payload .= pack("V",$transaction_id);
  203.     $payload .= pack("V*",@args);
  204.  
  205.     print $sock &PTPIP_pack_command( 6, $payload);
  206.  
  207.     if ($send_payload ne "") {
  208.         # Start Data Packet
  209.         $payload = "";
  210.         $payload .= pack("V",$transaction_id);
  211.         $payload .= pack("V",length($send_payload));
  212.         $payload .= pack("V",0);
  213.         print $sock &PTPIP_pack_command( 9, $payload);
  214.         #
  215.         while(length($send_payload)>0) {
  216.             my $buffer = substr($send_payload,0,200);
  217.             $send_payload = substr($send_payload,200);
  218.             $payload = "";
  219.             $payload .= pack("V",$transaction_id);
  220.             $payload .= $buffer;
  221.             if ($send_payload ne "") {
  222.                 # Data Packet
  223.                 print $sock &PTPIP_pack_command(10, $payload);
  224.             } else {
  225.                 # End Data Packet
  226.                 print $sock &PTPIP_pack_command(12, $payload);
  227.             }
  228.         }
  229.     }
  230. }
  231.  
  232. sub PTPIP_Wait_Cmd_Response {
  233.     my $sock = shift;
  234.     my @error_response = (0);
  235.     my $transaction_id;
  236.     my $data_payload = "";
  237.     my $data_payload_size;
  238.  
  239.     my ($cmd,$payload) = &PTPIP_Recv_Response($sock);
  240.  
  241.     # with Data?
  242.     if ($cmd == 9) {
  243.         # Start Data Packet
  244.         ($transaction_id,$data_payload_size) = unpack("VV",$payload);
  245.         $payload        = substr($payload,8);
  246.         $data_payload   = "";
  247.         my $continue_flag  = 1;
  248.         while($continue_flag) {
  249.             ($cmd,$payload) = &PTPIP_Recv_Response($sock);
  250.             if (($cmd != 10) && ($cmd != 12)) {
  251.                 # not Data_Packet and End_Data_Packet
  252.                 return @error_response;
  253.             }
  254.  
  255.             my ($temp_transaction_id) = unpack("V",$payload);
  256.             if ($transaction_id != $temp_transaction_id) { return @error_response; }
  257.             $payload       = substr($payload,4);
  258.             $data_payload .= $payload;
  259.             if (length($data_payload)>=$data_payload_size) { $continue_flag = 0; }
  260.             if ($cmd == 12) { $continue_flag = 0; } # End_Data_Packet
  261.         }
  262.  
  263.         # Cmd Response
  264.         ($cmd,$payload) = &PTPIP_Recv_Response($sock);
  265.     }
  266.  
  267.     # Response?
  268.     if ($cmd == 7) {
  269.         # Cmd Response
  270.         $transaction_id = unpack("V",$payload);
  271.         $payload        = substr($payload,4);
  272.         (1,$payload,$data_payload);
  273.     } else {
  274.         return @error_response;
  275.     }
  276. }
  277.  
  278. # -------------------------------------------------------
  279. #   PTPIP utils
  280. # -------------------------------------------------------
  281.  
  282. sub PTPIP_Open_Connection {
  283.     my $sock = new IO::Socket::INET(PeerAddr=>$Addr,PeerPort=>$Port,Proto=>'tcp',TimeOut=>2);
  284.     die "IO::Socket : $!" unless $sock;
  285.  
  286.     $sock;
  287. }
  288.  
  289. sub PTPIP_Close_Connection {
  290.     my $sock = shift;
  291.     close($sock);
  292. }
  293.  
  294. sub PTPIP_pack_command {
  295.     my $cmd = shift;
  296.     my $payload = shift;
  297. #   print "snd:$cmd:".unpack("H*",$payload)."\n";
  298.     pack("VV",(length($payload)+8),$cmd).$payload;
  299. }
  300.  
  301. sub PTPIP_Recv_Response {
  302.     my $sock = shift;
  303.     my ($buf,$len,$command_type,$packet_len);
  304.     my @error_response = (0,'');
  305.  
  306.     # packet length
  307.     $len = read($sock,$buf,4);
  308.     if ($len != 4) { return @error_response; }
  309.     $packet_len = unpack("V",$buf);
  310.     if ($packet_len > 1024) { return @error_response; }
  311.     if ($packet_len < 8   ) { return @error_response; }
  312.  
  313.     # command
  314.     $len = read($sock,$buf,4);
  315.     if ($len != 4) { return @error_response; }
  316.     $command_type = unpack("V",$buf);
  317.  
  318.     # payload
  319.     $len = read($sock,$buf,$packet_len-8);
  320.     if ($len != ($packet_len-8)) { return @error_response; }
  321. #   print "rcv:".$command_type.":".unpack("H*",$buf)."\n";
  322.  
  323.     ($command_type,$buf);
  324. }
  325.  
  326. sub Encode_UTF16LE {
  327.     my $str = shift;
  328. #   encode('UTF16LE', $str);
  329.     pack("v*",unpack("c*",$str));
  330. }
  331.  
  332. sub Decode_UTF16LE {
  333.     my $str = shift;
  334. #   decode('UTF16LE', $str)
  335.     pack("c*",unpack("v*",$str));
  336. }