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