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