1 /*
2 * multican 0.0.5, USB remote control tool for Canon cameras.
3 *
4 * Copyright (C) 2006 Jindrich Novy (jnovy@users.sourceforge.net)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #define _GNU_SOURCE
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <sys/endian.h>
26 #include <usb.h>
27
28 #include "usbio.h"
29
30 unsigned usb_sequence = 0;
31 int tolerate_error = 0, retries = 5000;
32 unsigned char usb_packet[0x1400];
33
usb_hexdump(char * bytes,int size)34 void usb_hexdump( char *bytes, int size ) {
35 int n, i;
36
37 fputs(" 0 1 2 3 4 5 6 7| 8 9 A B C D E F 01234567|89ABCDEF\n", stderr);
38 for ( n=0; n<size; n+=i ) {
39 fprintf(stderr, "0x%04X: ", n);
40 for ( i=0; n+i<size && i<0x10; i++ ) {
41 unsigned char b = bytes[n+i];
42 fprintf(stderr, "%02X%c", b, i!=7?' ':'|');
43 }
44 for ( ; i<0x10; i++ )
45 fputs(" ", stderr);
46 for ( i=0; n+i<size && i<0x10; i++ ) {
47 unsigned b = bytes[n+i];
48 if ( i==8 )
49 putc('|', stderr);
50 putc(b>=0x20 && b<0x7f ? b : '.', stderr);
51 }
52 putc('\n', stderr);
53 }
54 putc('\n', stderr);
55 }
56
get_le32(char * b)57 unsigned get_le32( char *b ) {
58 unsigned char A, B, C, D;
59 #if __BYTE_ORDER == __LITTLE_ENDIAN
60 A = b[0];
61 B = b[1];
62 C = b[2];
63 D = b[3];
64 #elif __BYTE_ORDER == __BIG_ENDIAN
65 A = b[3];
66 B = b[2];
67 C = b[1];
68 D = b[0];
69 #else
70 # error "Endianess of your machine is not supported."
71 #endif
72 return A | (B<<8) | ((C)<<16) | ((D)<<24);
73 }
74
75 /* Works only for little endian machines at the time! */
put_le32(char * b,unsigned v)76 void put_le32( char *b, unsigned v ) {
77 #if __BYTE_ORDER == __LITTLE_ENDIAN
78 b[0] = v&0xff;
79 b[1] = (v>>8)&0xff;
80 b[2] = (v>>16)&0xff;
81 b[3] = (v>>24)&0xff;
82 #elif __BYTE_ORDER == __BIG_ENDIAN
83 b[3] = v&0xff;
84 b[2] = (v>>8)&0xff;
85 b[1] = (v>>16)&0xff;
86 b[0] = (v>>24)&0xff;
87 #else
88 # error "Endianess of you machine is not supported."
89 #endif
90 }
91
usb_read_byte(usb_dev_handle * h,int value,char * byte)92 void usb_read_byte( usb_dev_handle *h, int value, char *byte ) {
93 int ret;
94 #if DEBUG
95 fprintf(stderr, "usb_read_byte: value=%d (0x%x)", value, value);
96 #endif
97 while ( (ret=USB_READ_BYTE(h, value, byte)) == 0 ) {
98 #if DEBUG
99 fprintf(stderr, "Read nothing, trying again.\n");
100 #endif
101 }
102
103 if ( ret < 0 ) {
104 fprintf(stderr, "Read failed, exiting...\n");
105 exit(1);
106 }
107 #if DEBUG
108 fprintf(stderr,", byte=%c (0x%02x)\n", *(unsigned char*)byte, *(unsigned char*)byte);
109 #endif
110 }
111
usb_read_bytes(usb_dev_handle * h,int value,char * bytes,int size)112 void usb_read_bytes( usb_dev_handle *h, int value, char *bytes, int size ) {
113 int ret;
114 #if DEBUG
115 fprintf(stderr, "usb_read_bytes: value=%d (0x%x), size=%d (0x%x):\n", value, value, size, size);
116 #endif
117 while ( (ret=USB_READ_BYTES(h, value, bytes, size)) < size ) {
118 #if DEBUG
119 fprintf(stderr, "Partial read, trying again.\n");
120 #endif
121 }
122
123 if ( ret < 0 ) {
124 fprintf(stderr, "Read failed, exiting...\n");
125 exit(1);
126 }
127 #if DEBUG
128 usb_hexdump(bytes, size);
129 #endif
130 }
131
usb_write_byte(usb_dev_handle * h,int value,char * byte)132 void usb_write_byte( usb_dev_handle *h, int value, char *byte ) {
133 int ret = 0, retr = 0;
134 #if DEBUG
135 fprintf(stderr, "usb_write_byte: value=%d (0x%x), byte=%c (0x%02x)\n", value, value, *byte, *byte);
136 #endif
137
138 while ( (ret=USB_WRITE_BYTE(h, value, byte)) == 0 ) {
139 #if DEBUG
140 fprintf(stderr, "Wrote partially, trying again.\n");
141 #endif
142 if ( tolerate_error && ++retr >= retries ) {
143 fprintf(stderr,"Writing sequence tried %d times, giving up...\n", retr);
144 return;
145 }
146 }
147
148 if ( ret < 0 ) {
149 fprintf(stderr, "Write failed, exiting...\n");
150 exit(1);
151 }
152 }
153
usb_write_bytes(usb_dev_handle * h,int value,char * bytes,int size)154 void usb_write_bytes( usb_dev_handle *h, int value, char *bytes, int size ) {
155 int ret = 0, retr = 0;
156 #if DEBUG
157 fprintf(stderr, "usb_write_bytes: value=%d (0x%x), size=%d (0x%x):\n", value, value, size, size);
158 usb_hexdump(bytes, size);
159 #endif
160 while ( (ret=USB_WRITE_BYTES(h, value, bytes, size)) < size ) {
161 #if DEBUG
162 fprintf(stderr, "Wrote partially, trying again.\n");
163 #endif
164 if ( tolerate_error && ++retr >= retries ) {
165 fprintf(stderr,"Writing sequence tried %d times, giving up...\n", retr);
166 return;
167 }
168 }
169
170 if ( ret < 0 ) {
171 fprintf(stderr, "Write failed, exiting...\n");
172 exit(1);
173 }
174 }
175
usb_bulk_read_bytes(usb_dev_handle * h,int ep,char * bytes,int size)176 void usb_bulk_read_bytes( usb_dev_handle *h, int ep, char *bytes, int size ) {
177 int ret = -1, pos = 0, retr = 0;
178
179 if ( !size ) {
180 fprintf(stderr, "warning: bulk_read request of 0 bytes!\n");
181 return;
182 }
183
184 memset(bytes, 0, size);
185 while ( pos != size && (ret = usb_bulk_read( h, ep, (char*)&bytes[pos], size-pos, USB_TIMEOUT )) >= 0 ) {
186 pos += ret;
187 #if DEBUG
188 fprintf(stderr, "usb_bulk_read: ep=%d (0x%x), size=%d (0x%x):\n", ep, ep, ret, ret);
189 #endif
190 retr++;
191 if ( tolerate_error && retr >= retries ) break;
192 }
193
194 if ( pos != size || ret < 0 ) {
195 fprintf(stderr, "Error in usb_bulk_read() request.\n");
196 if ( !tolerate_error ) {
197 exit(1);
198 } else {
199 fprintf(stderr, "Tolerating the above error for now.\n");
200 }
201 }
202 #if DEBUG
203 usb_hexdump(bytes, size);
204 #endif
205 }
206
usb_send_packet(camera * c,unsigned char cmd1,unsigned char cmd2,unsigned cmd3,char * arguments,int argsize)207 void usb_send_packet( camera *c, unsigned char cmd1, unsigned char cmd2, unsigned cmd3, char *arguments, int argsize ) {
208 #ifdef DEBUG
209 fprintf(stderr, "usb_send_packet: cmd1=%d (0x%x), cmd2=%d (0x%x), cmd3=%d (0x%x):\n", cmd1, cmd1, cmd2, cmd2, cmd3, cmd3);
210 #endif
211 memset(usb_packet, 0, 0x50);
212 put_le32(usb_packet, 0x10+argsize);
213 put_le32(usb_packet+0x48, 0x10+argsize);
214 usb_packet[0x40] = 0x2;
215 usb_packet[0x44] = cmd1;
216 usb_packet[0x47] = cmd2;
217 put_le32(usb_packet+4, cmd3);
218
219 if ( CANON_CLASS(c) >= 6 && !IS_TYPE(c,"1D") ) {
220 usb_packet[0x46] = cmd3==0x202 ? 0x20 : 0x10;
221 }
222
223 put_le32(usb_packet+0x4c, usb_sequence++);
224
225 if (argsize < 0 || argsize+0x50 > sizeof(usb_packet)) {
226 fprintf(stderr, "Invalid argsize = %d (0x%x).\n\n", argsize, argsize);
227 exit(1);
228 }
229
230 if ( argsize > 0 ) {
231 memcpy(usb_packet+0x50, arguments, argsize);
232 }
233
234 usb_write_bytes(c->h, 0x10, usb_packet, 0x50+argsize);
235 }
236
usb_receive_packet(camera * c,char * bytes,int size)237 void usb_receive_packet( camera *c, char *bytes, int size ) {
238 #ifdef DEBUG
239 fprintf(stderr, "usb_receive_packet: ep=%d (0x%x), size=%d (0x%x):\n", c->bulk_in, c->bulk_in, size, size);
240 #endif
241 usb_bulk_read_bytes(c->h, c->bulk_in, bytes, size);
242
243 {
244 int i;
245 unsigned code = get_le32(&bytes[0x50]);
246 #ifdef DEBUG
247 unsigned cmd3 = ((bytes[5]-1)<<8)+bytes[4];
248
249 if (cmd3==0x202) { /* Format of response block is different in case cmd3==0x202*/
250 fprintf(stderr,"usb_receive_packet sanity check: unformatted binary data of size=%d follows\n", get_le32(&bytes[6]));
251 } else {
252 fprintf(stderr,"usb_receive_packet sanity check: cmd1=0x%02x, cmd2=0x%02x, cmd3=0x%03x, 2==%d, size=0x%04x\n",
253 bytes[0x44],
254 bytes[0x47]-0x10,
255 cmd3,
256 bytes[0x40],
257 get_le32(&bytes[0x48])+0x40);
258 }
259 #endif
260 if ( !code ) return;
261
262 for ( i=0; canon_status[i].code; i++ )
263 if ( canon_status[i].code == code ) {
264 fprintf(stderr, "usb_receive_packet status code: 0x%08x -> %s.\n", code, canon_status[i].text);
265 return;
266 }
267 fprintf(stderr, "usb_receive_packet exit code: 0x%08x -> UNKNOWN !!!\n", code);
268 }
269 }
270