1 /****************************************************************/
2 /* pccam600.c - Gphoto2 library for the Creative PC-CAM600 */
3 /* */
4 /* */
5 /* Author: Peter Kajberg <pbk@odense.kollegienet.dk> */
6 /* */
7 /* This library is free software; you can redistribute it */
8 /* and/or modify it under the terms of the GNU Library General */
9 /* Public License as published by the Free Software Foundation; */
10 /* either version 2 of the License, or (at your option) any */
11 /* later version. */
12 /* */
13 /* This library is distributed in the hope that it will be */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied */
15 /* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
16 /* PURPOSE. See the GNU Library General Public License for */
17 /* more details. */
18 /* */
19 /* Please notice that camera commands was sniffed by use of a */
20 /* usbsniffer under windows. This is an experimental driver and */
21 /* a work in progess(I hope :)) */
22 /* */
23 /* You should have received a copy of the GNU Library General */
24 /* Public License along with this library; if not, write to the */
25 /* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,*/
26 /* Boston, MA 02110-1301 USA */
27 /****************************************************************/
28
29 #include "config.h"
30 #include <string.h>
31
32
33 #include "pccam600.h"
34
35 #include <gphoto2/gphoto2.h>
36 #include <gphoto2/gphoto2-port.h>
37 #include <gphoto2/gphoto2-port-log.h>
38
39 #define GP_MODULE "pccam600"
40
41 #ifdef ENABLE_NLS
42 # include <libintl.h>
43 # undef _
44 # define _(String) dgettext (GETTEXT_PACKAGE, String)
45 # ifdef gettext_noop
46 # define N_(String) gettext_noop (String)
47 # else
48 # define N_(String) (String)
49 # endif
50 #else
51 # define _(String) (String)
52 # define N_(String) (String)
53 #endif
54
55 /*
56 *waits until the status value is 0 or 8.
57 *if status == 0xb0 or 0x40 we will wait some more
58 */
pccam600_wait_for_status(GPPort * port)59 static int pccam600_wait_for_status(GPPort *port){
60 unsigned char status = 1;
61 while(status != 0x00){
62 gp_port_set_timeout(port,3000);
63 CHECK(gp_port_usb_msg_read(port,0x06,0x00,0x00,(char*)&status,1));
64 if (status == 0 || status == 8)
65 return GP_OK;
66 if (status == 0xb0){
67 gp_port_set_timeout(port,200000);
68 CHECK(gp_port_usb_msg_read(port,0x06,0x00,0x00,(char*)&status,1));
69 }
70 if (status == 0x40){
71 gp_port_set_timeout(port,400000);
72 CHECK(gp_port_usb_msg_read(port,0x06,0x00,0x00,(char*)&status,1));
73 }
74 }
75 return GP_ERROR;
76 }
77
78 /*
79 *Deletes a file. The first file has index = 2.
80 */
pccam600_delete_file(GPPort * port,GPContext * context,int index)81 int pccam600_delete_file(GPPort *port, GPContext *context, int index){
82 unsigned char response[4];
83 index = index + 2;
84 gp_port_set_timeout(port,200000);
85 CHECK(gp_port_usb_msg_write(port,0x09,index,0x1001,NULL,0x00));
86 CHECK(pccam600_wait_for_status(port));
87 gp_port_set_timeout(port, 400000);
88 CHECK(gp_port_usb_msg_read(port,0x60,0x00,0x03,(char*)response,0x04));
89 CHECK(pccam600_wait_for_status(port));
90 CHECK(gp_port_usb_msg_read(port,0x60,0x00,0x04,(char*)response,0x04));
91 CHECK(pccam600_wait_for_status(port));
92 return GP_OK;
93 }
94
pccam600_get_mem_info(GPPort * port,GPContext * context,int * totalmem,int * freemem)95 int pccam600_get_mem_info(GPPort *port, GPContext *context, int *totalmem,
96 int *freemem)
97 {
98 unsigned char response[4];
99 gp_port_set_timeout(port, 400000);
100 CHECK(gp_port_usb_msg_read(port,0x60,0x00,0x03,(char*)response,0x04));
101 *totalmem = response[2]*65536+response[1]*256+response[0];
102 CHECK(pccam600_wait_for_status(port));
103 CHECK(gp_port_usb_msg_read(port,0x60,0x00,0x04,(char*)response,0x04));
104 *freemem = response[2]*65536+response[1]*256+response[0];
105 CHECK(pccam600_wait_for_status(port));
106 return GP_OK;
107 }
108
109 /*
110 *
111 */
pccam600_get_file_list(GPPort * port,GPContext * context)112 int pccam600_get_file_list(GPPort *port, GPContext *context){
113 unsigned char response[4];
114 int nr_of_blocks;
115 gp_port_set_timeout(port,500);
116 CHECK(gp_port_usb_msg_write(port,0x08,0x00,0x1021,NULL,0x00));
117 CHECK(pccam600_wait_for_status(port));
118 gp_port_set_timeout(port, 200000);
119 CHECK(gp_port_usb_msg_write(port,0x08,0x00,0x1021,NULL,0x00));
120 CHECK(pccam600_wait_for_status(port));
121 CHECK(gp_port_usb_msg_read(port,0x08,0x00,0x1000,(char*)response,0x04));
122 nr_of_blocks = response[2]*256+response[1];
123 if (nr_of_blocks == 0){
124 gp_log(GP_LOG_DEBUG,"pccam600 library: pccam600_get_file_list",
125 "nr_of_blocks is 0");
126 gp_context_error(context,_("pccam600_init: Expected > %d blocks got %d"),
127 0,nr_of_blocks);
128 return GP_ERROR;
129 }
130 return nr_of_blocks / 2;
131 }
132
pccam600_get_file(GPPort * port,GPContext * context,int index)133 int pccam600_get_file(GPPort *port, GPContext *context, int index){
134 unsigned char response[4];
135 int nr_of_blocks;
136 index = index + 2;
137 if (index < 2) {
138 gp_context_error(context,
139 _("pccam600_get_file:got index %d but expected index > %d"),
140 index,2);
141 return GP_ERROR;
142 }
143 gp_port_set_timeout(port,200000);
144 CHECK(gp_port_usb_msg_read(port,0x08,index,0x1001,(char*)response,0x04));
145 gp_port_set_timeout(port,3000);
146 CHECK(gp_port_usb_msg_write(port,0x04,0x00,0x00,NULL,0x00));
147 CHECK(pccam600_wait_for_status(port));
148 gp_port_set_timeout(port,200000);
149 CHECK(gp_port_usb_msg_read(port,0x08,index,0x1002,(char*)response,0x04));
150 CHECK(gp_port_usb_msg_read(port,0x08,index,0x1001,(char*)response,0x04));
151 nr_of_blocks = response[2]*256+response[1];
152 if (nr_of_blocks == 0){
153 gp_log(GP_LOG_DEBUG,
154 "pccam600 library: pccam600_get_file","nr_of_msg is 0");
155 gp_context_error(context,_("pccam600_init: Expected > %d blocks got %d"),
156 0,nr_of_blocks);
157 return GP_ERROR;
158 }
159 return nr_of_blocks / 2;
160 }
161
162 /*
163 *Reads bulk data from the camera in 512bytes chunks.
164 */
pccam600_read_data(GPPort * port,unsigned char * buffer)165 int pccam600_read_data(GPPort *port, unsigned char *buffer){
166 gp_port_set_timeout(port,500);
167 CHECK(gp_port_read(port,(char*)buffer,512));
168 return GP_OK;
169 }
170
171 /*
172 *
173 */
pccam600_close(GPPort * port,GPContext * context)174 int pccam600_close(GPPort *port, GPContext *context){
175 int ret;
176 gp_port_set_timeout(port,500);
177 ret = gp_port_usb_msg_write(port,0x08,0x00,0xf0,NULL,0x00);
178 if (ret < 0) {
179 gp_context_error(context,
180 _("pccam600_close: return value was %d instead of %d"),
181 ret,0);
182 return GP_ERROR;
183 }
184 CHECK(pccam600_wait_for_status(port));
185 return GP_OK;
186 }
187
188 /*
189 *Sets up the camera and then read 32 512bytes blocks.
190 *Why it is read those 32 blocks I dont know. Just
191 *doing what the windows driver does :).
192 */
pccam600_init(GPPort * port,GPContext * context)193 int pccam600_init(GPPort *port, GPContext *context){
194 unsigned char response[4];
195 unsigned char buffer[512];
196 int nr_of_blocks;
197 int ret,i;
198 gp_port_set_timeout(port,100);
199 CHECK(gp_port_usb_msg_write(port,0x0e,0x00,0x01,NULL,0x0));
200 CHECK(gp_port_usb_msg_write(port,0x08,0x00,0xff,NULL,0x0));
201 CHECK(pccam600_wait_for_status(port));
202 gp_port_set_timeout(port,100000);
203 CHECK(gp_port_usb_msg_read(port,0x08,0x00,0xff,(char*)response,0x1));
204 gp_port_set_timeout(port,500);
205 CHECK(gp_port_usb_msg_write(port,0x08,0x00,0x1020,NULL,0x0));
206 CHECK(pccam600_wait_for_status(port));
207 gp_port_set_timeout(port,200000);
208 CHECK(gp_port_usb_msg_read(port,0x08,0x00,0x1000,(char*)response,0x4));
209 nr_of_blocks = response[2]*256+response[1];
210
211 if (nr_of_blocks == 0) {
212 gp_context_error(context,_("pccam600_init: Expected %d blocks got %d"),64,nr_of_blocks);
213 return GP_ERROR;
214 }
215
216 nr_of_blocks = 512 / nr_of_blocks;
217 gp_log(GP_LOG_DEBUG,"pccam600 library: init","nr_of_blocks %d",nr_of_blocks);
218 if (nr_of_blocks == 0) {
219 gp_context_error(context,_("pccam600_init: Expected %d blocks got %d"),64,nr_of_blocks);
220 return GP_ERROR;
221 }
222 gp_port_set_timeout(port,500);
223 for (i = 0; i<nr_of_blocks; i++){
224 ret = gp_port_read(port, (char*)buffer,512);
225 if (ret < 0){
226 gp_log(GP_LOG_DEBUG,
227 "pccam600 library: init"," gp_port_read returned %d:",
228 ret);
229 gp_context_error(context,_("pccam600 init:"
230 " Unexpected error: gp_port_read returned %d instead of %d"),
231 ret,0);
232 return GP_ERROR;
233 }
234 }
235 return GP_OK;
236
237 }
238