1 /* jl2005c.c
2  *
3  * Copyright (C) 2006-2010 Theodore Kilgore <kilgota@auburn.edu>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  */
20 
21 #define _DEFAULT_SOURCE
22 
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <string.h>
29 #include <math.h>
30 
31 #include <gphoto2/gphoto2.h>
32 #include <gphoto2/gphoto2-port.h>
33 #include "gphoto2-endian.h"
34 
35 #include "jl2005c.h"
36 
37 #define GP_MODULE "jl2005c"
38 
39 /* do not sleep during fuzzing */
40 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
41 # define usleep(x)
42 #endif
43 
44 int
jl2005c_init(Camera * camera,GPPort * port,CameraPrivateLibrary * priv)45 jl2005c_init (Camera *camera, GPPort *port, CameraPrivateLibrary *priv)
46 {
47 	char response;
48 	int model_string = 0;
49 	/* Needs to be big enough to hold (0xfff + 3) * 0x10 */
50 	unsigned char info[0x4020];
51 	const char camera_id[] = {0x4a, 0x4c, 0x32, 0x30, 0x30, 0x35};
52 	int alloc_table_size;
53 	int attempts = 0;
54 restart:
55 	alloc_table_size = 0;
56 	memset(info, 0, sizeof(info));
57 	GP_DEBUG("Running jl2005c_init\n");
58 	if (priv->init_done) {
59 		gp_port_close(port);
60 		usleep (100000);
61 		gp_port_open(port);
62 	}
63 
64 	set_usb_in_endpoint	(camera, 0x84);
65 	gp_port_write (port, "\x08\x00", 2);
66 	usleep (10000);
67 	gp_port_write (port, "\x95\x60", 2);
68 	jl2005c_read_data (port, &response, 1);
69 	model_string = response;
70 	gp_port_write (port, "\x95\x61", 2);
71 	jl2005c_read_data (port, &response, 1);
72 	model_string += (response & 0xff) << 8;
73 	gp_port_write (port, "\x95\x62", 2);
74 	jl2005c_read_data (port, &response, 1);
75 	model_string += (response & 0xff) << 16;
76 	gp_port_write (port,"\x95\x63" , 2);
77 	jl2005c_read_data (port, &response, 1);
78 	model_string += (response & 0xff) << 24;
79 	GP_DEBUG("Model string is %08x\n", model_string);
80 	gp_port_write (port, "\x95\x64", 2);
81 	jl2005c_read_data (port, &response, 1);
82 	gp_port_write (port, "\x95\x65", 2);
83 	jl2005c_read_data (port, &response, 1);
84 	/* Number of pix returned here, but not reliably reported */
85 	priv->nb_entries = response & 0xff;
86 	GP_DEBUG("%d frames in the camera (unreliable!)\n", priv->nb_entries);
87 	gp_port_write (port, "\x95\x66", 2);
88 	jl2005c_read_data (port, &response, 1);
89 	gp_port_write (port, "\x95\x67", 2);
90 	jl2005c_read_data (port, &response, 1);
91 	gp_port_write (port, "\x95\x68", 2);
92 	jl2005c_read_data (port, &response, 1);
93 	gp_port_write (port, "\x95\x69", 2);
94 	jl2005c_read_data (port, &response, 1);
95 	gp_port_write (port, "\x95\x6a", 2);
96 	jl2005c_read_data (port, &response, 1);
97 	gp_port_write (port, "\x95\x6b", 2);
98 	jl2005c_read_data (port, &response, 1);
99 	gp_port_write (port, "\x95\x6c", 2);
100 	jl2005c_read_data (port, &response, 1);
101 	priv->data_to_read = (response & 0xff) * 0x100;
102 	gp_port_write (port, "\x95\x6d", 2);
103 	jl2005c_read_data (port, &response, 1);
104 	priv->data_to_read += (response&0xff);
105 	priv->total_data_in_camera = priv->data_to_read;
106 	GP_DEBUG ("blocks_to_read = 0x%lx = %lu\n", priv->data_to_read,
107 							priv->data_to_read);
108 	gp_port_write (port, "\x95\x6e", 2);
109 	jl2005c_read_data (port, &response, 1);
110 	alloc_table_size = (response & 0xff) * 0x200;
111 	GP_DEBUG("alloc_table_size = 0x%02x * 0x200 = 0x%x\n",
112 				response & 0xff, (response & 0xff) * 0x200);
113 	gp_port_write (port, "\x95\x6f", 2);
114 	jl2005c_read_data (port, &response, 1);
115 	gp_port_write (port, "\x0a\x00", 2);
116 	usleep (10000);
117 	/* Switch the inep over to 0x82. It stays there ever after. */
118 	set_usb_in_endpoint	(camera, 0x82);
119 
120 	/* Read the first block of the allocation table. */
121 	jl2005c_read_data (port, (char *)info, 0x200);
122 	if (strncmp(camera_id, (char*)info, 6)) {
123 		GP_DEBUG("Error downloading alloc table\n");
124 		GP_DEBUG("Init attempted %d times\n", attempts + 1);
125 		attempts++;
126 		if (attempts == 3) {
127 			GP_DEBUG("Third try. Giving up\n");
128 			gp_port_write(port, "\x07\x00", 2);
129 			return GP_ERROR;
130 		}
131 		goto restart;
132 	}
133 
134 	/* Now check the number of photos. That is found in byte 13 of line 0
135 	 * of the allocation table.
136 	 */
137 	priv->nb_entries = (info[12] & 0xff) * 0x100 | (info[13] & 0xff);
138 	GP_DEBUG("Number of entries is recalculated as %d\n",
139 						priv->nb_entries);
140 
141 	/* Just in case there was a problem, we now recalculate the total
142 	 * alloc_table_size. */
143 	alloc_table_size = priv->nb_entries * 0x10 + 0x30;
144 	if (alloc_table_size%0x200)
145 		alloc_table_size += 0x200 - (alloc_table_size%0x200);
146 	/* However, we have already just now downloaded 0x200 bytes, so
147 	 * when downloading the rest of the table we correct for that and
148 	 * just download whatever remains of the information block.
149 	 */
150 	if (alloc_table_size > 0x200)
151 		gp_port_read(port, (char *)info + 0x200,
152 						alloc_table_size - 0x200);
153 	memmove(priv->table, info + 0x30, alloc_table_size - 0x30);
154 	priv->model = info[6];
155 	GP_DEBUG("Model is %c\n", priv->model);
156 	switch (priv->model) {
157 	case 0x43:
158 	case 0x44:
159 		priv->blocksize = 0x200;
160 		break;
161 	case 0x42:
162 		priv->blocksize = 0x80;
163 		break;
164 	default:
165 		GP_DEBUG("Unknown model, unknown blocksize\n");
166 		return GP_ERROR_NOT_SUPPORTED;
167 	}
168 	GP_DEBUG("camera's blocksize = 0x%x = %d\n", priv->blocksize,
169 						     priv->blocksize);
170 	/* Now a more responsible calculation of the amount of data in the
171 	 * camera, based upon the allocation table. */
172 	priv->data_to_read = info[10] * 0x100 | info[11];
173 	priv->data_to_read -= info[8] * 0x100 | info[9];
174 	priv->data_to_read *= priv->blocksize;
175 	priv->total_data_in_camera = priv->data_to_read;
176 	GP_DEBUG ("data_to_read = 0x%lx = %lu\n", priv->data_to_read,
177 							priv->data_to_read);
178 	GP_DEBUG ("total_data_in_camera = 0x%lx = %lu\n", priv->data_to_read,
179 							  priv->data_to_read);
180 	priv->can_do_capture = 0;
181 	if (info[7] & 0x04)
182 		priv->can_do_capture = 1;
183 	priv->bytes_read_from_camera = 0;
184 	priv->bytes_put_away = 0;
185 	priv->init_done = 1;
186 	GP_DEBUG("Leaving jl2005c_init\n");
187 	return GP_OK;
188 }
189 
jl2005c_open_data_reg(Camera * camera,GPPort * port)190 int jl2005c_open_data_reg (Camera *camera, GPPort *port)
191 {
192 	gp_port_write (port, "\x0b\x00",2);
193 	usleep (10000);
194 	GP_DEBUG("Opening data register.\n");
195 	camera->pl->data_reg_opened = 1;
196 	return GP_OK;
197 }
198 
199 int
jl2005c_get_pic_data_size(CameraPrivateLibrary * priv,Info * table,int n)200 jl2005c_get_pic_data_size (CameraPrivateLibrary *priv, Info *table, int n)
201 {
202 	int size;
203 	GP_DEBUG("table[16 * n + 7] = %02X\n", table[16 * n + 7]);
204 	size = table[0x10 * n + 6] * 0x100 | table[0x10 * n + 7];
205 	size *= priv->blocksize;
206 	GP_DEBUG("size = 0x%x = %d\n", size, size);
207 	return (size);
208 }
209 
210 unsigned long
jl2005c_get_start_of_photo(CameraPrivateLibrary * priv,Info * table,unsigned int n)211 jl2005c_get_start_of_photo(CameraPrivateLibrary *priv, Info *table,
212 							unsigned int n)
213 {
214 	unsigned long start;
215 	start = table[0x10 * n + 0x0c] * 0x100 | table[0x10 * n + 0x0d];
216 	start -= table[0x0c] * 0x100 | table[0x0d];
217 	start *= priv->blocksize;
218 	return start;
219 }
220 
221 
222 int
set_usb_in_endpoint(Camera * camera,int inep)223 set_usb_in_endpoint	(Camera *camera, int inep)
224 {
225 	GPPortSettings settings;
226 	gp_port_get_settings ( camera ->port, &settings);
227 	if(settings.usb.inep != inep)
228 		settings.usb.inep = inep;
229 	GP_DEBUG("inep reset to %02X\n", inep);
230 	return gp_port_set_settings ( camera->port, settings);
231 }
232 
233 int
jl2005c_read_data(GPPort * port,char * data,int size)234 jl2005c_read_data (GPPort *port, char *data, int size)
235 {
236 	/* These cameras tend to be slow. */
237 	usleep (10000);
238 	gp_port_read (port, data, size);
239 	usleep (10000);
240 	return GP_OK;
241 }
242 
jl2005c_reset(Camera * camera,GPPort * port)243 int jl2005c_reset (Camera *camera, GPPort *port)
244 {
245 	int downloadsize = MAX_DLSIZE;
246 	/* If any data has been downloaded, these cameras want all data to be
247 	 * dumped before exit. If that is not yet done, then do it now! */
248 	if(camera->pl->data_reg_opened) {
249 		while (camera->pl->bytes_read_from_camera <
250 				    camera->pl->total_data_in_camera ) {
251 			if (!camera->pl->data_cache )
252 				camera->pl->data_cache = malloc (MAX_DLSIZE);
253 			downloadsize = MAX_DLSIZE;
254 			if (camera->pl->bytes_read_from_camera + MAX_DLSIZE >=
255 				    camera->pl->total_data_in_camera )
256 				downloadsize = camera->pl->total_data_in_camera -
257 					camera->pl->bytes_read_from_camera;
258 			if (downloadsize)
259 				jl2005c_read_data (camera->port,
260 					    (char *) camera->pl->data_cache,
261 					    downloadsize);
262 			camera->pl->bytes_read_from_camera += downloadsize;
263 		}
264 	}
265 	gp_port_write(port, "\x07\x00", 2);
266 	camera->pl->data_reg_opened = 0;
267 	return GP_OK;
268 }
269 
jl2005c_delete_all(Camera * camera,GPPort * port)270 int jl2005c_delete_all (Camera *camera, GPPort *port)
271 {
272 	gp_port_write(port, "\x09\x00", 2);
273 	usleep(10000);
274 	gp_port_write(port, "\x07\x00", 2);
275 	return GP_OK;
276 }
277