/**************************************************** * kodak dc3200 digital camera driver library * * for gphoto2 * * * * author: donn morrison - dmorriso@gulf.uvic.ca * * date: dec 2000 - jan 2002 * * license: gpl * * version: 1.6 * * * ****************************************************/ #include "config.h" #include "library.h" #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h> #include <termios.h> #include <stdio.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <errno.h> #include "dc3200.h" #ifdef ENABLE_NLS # include <libintl.h> # undef _ # define _(String) dgettext (GETTEXT_PACKAGE, String) # ifdef gettext_noop # define N_(String) gettext_noop (String) # else # define N_(String) (String) # endif #else # define _(String) (String) # define N_(String) (String) #endif /* * FIXME: Use properly sized integer types. The dc3200 code used lots * of u_char, u_long, u_int, which may be wrong on non-32bit systems. */ /* #define DEBUG */ /* * dc3200_set_speed * * handshakes a baud rate with the camera * */ int dc3200_set_speed(Camera *camera, int baudrate) { int baudcode = C9600; unsigned char resp[INI_PACKET_LEN], msg[INI_PACKET_LEN]; int resp_len = INI_PACKET_LEN, msg_len = INI_PACKET_LEN; msg[0] = 0xAF; msg[1] = 0x00; switch(baudrate) { case 9600: baudcode = C9600; break; case 19200: baudcode = C19200; break; case 38400: baudcode = C38400; break; case 57600: baudcode = C57600; break; case 115200: baudcode = C115200; break; default: printf("unsupported baudrate: %d.\n", baudrate); return GP_ERROR; } msg[2] = baudcode; /* send our preferred baud rate */ if(dc3200_send_command(camera, msg, msg_len, resp, &resp_len) == GP_ERROR) return GP_ERROR; /* the camera responds with our preferred baud rate or its * maximum baud rate, whichever is lowest */ /* compile a confirmation packet */ msg[0] = 0x9F; msg[1] = 0x00; if(resp_len == 2) { msg_len = 2; } else { /* calculate reply baud handshake */ msg[2] = (resp[2] + 1) / 2; msg_len = INI_PACKET_LEN; } if(dc3200_send_command(camera, msg, msg_len, resp, &resp_len) == GP_ERROR) return GP_ERROR; if(resp_len == 2) { /* set the handshaked baudrate * supports only 9600 */ return C9600; } else if(resp[1] == 0x01) { /* set the handshaked baudrate */ return (resp[2]*2) - 1; } else { /* unknown baud */ return GP_ERROR; } return GP_ERROR; } /* * dc3200_setup * * sends two commands essential for survival * */ int dc3200_setup(Camera *camera) { /* * some strange commands that must be * completed after initialization and * before any camera access * * version info? ... * */ unsigned char cmd1[5] = {0x01, dc3200_calc_seqnum(camera), 0x01, 0x00, 0x0F}; unsigned char cmd2[8] = {0x01, dc3200_calc_seqnum(camera), 0x80, 0x00, 0x01, 0x81, 0x00, 0x03}; unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN]; int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN; if(dc3200_send_command(camera, cmd1, sizeof(cmd1), ack, &ack_len) == GP_ERROR) return GP_ERROR; if(dc3200_check_ack(camera, ack, ack_len) == GP_ERROR) return GP_ERROR; if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR) return GP_ERROR; if(dc3200_send_ack(camera, resp[1]) == GP_ERROR) return GP_ERROR; if(dc3200_send_command(camera, cmd2, sizeof(cmd2), ack, &ack_len) == GP_ERROR) return GP_ERROR; if(dc3200_check_ack(camera, ack, ack_len) == GP_ERROR) return GP_ERROR; if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR) return GP_ERROR; if(dc3200_send_ack(camera, resp[1]) == GP_ERROR) return GP_ERROR; /* set the cmd sequence number */ camera->pl->cmd_seqnum = 0; camera->pl->rec_seqnum = 0; return GP_OK; } /* * dc3200_get_data * * retrieves data from the camera as either file * data or file/folder list data * */ /* command to retrieve directory listing unsigned char list_pkt[DEF_PACKET_LEN] = {0x01, dc3200_calc_seqnum(camera), 0x80, 0x00, 0x20, 0x03, 26 + strlen(filename), 0xc1, 0x50, 0x00, 0x00, 0x00, 0x00, 19 + strlen(filename), 0x04, 0x01, 0x00, 0x01, 0x00, 0x01, 0x60, 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 2 + strlen(filename), 0x01}; */ /* command to get the picture unsigned char get_pkt[DEF_PACKET_LEN] = {0x01, calc_seqnum(), 0x80, 0x00, 0x20, 0x03, 26 + strlen(filename), 0xC1, 0x50, 0x00, 0x00, 0x00, 0x00, 19 + strlen(filename), 0x04, 0x01, 0x00, 0x01, 0x01, 0x04, 0x60, 0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 2 + strlen(filename), 0x01}; */ int dc3200_get_data(Camera *camera, unsigned char **data, unsigned long *data_len, int command, const char *folder, const char *filename) { unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN]; int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN; unsigned long num_left = 0; unsigned long total = 0; int data_start_pos = 0; unsigned char *ptr_data = NULL; unsigned int pid = 0; /* command bytes */ unsigned char cb1=0x00,cb2=0x00,cb3=0x00; /* packet parts */ unsigned char pkt_hdr[7]; unsigned char pkt_typ[7]; unsigned char pkt_cmd[12]; unsigned char pkt_len[5]; unsigned char *packet; int packet_len; char *file = NULL; char *ptr = NULL; if(folder) { if(filename) { file = malloc(strlen(folder) + strlen(filename) + 2); if(!file) return GP_ERROR; /* concatenate the folder + filename */ strncpy(file, folder, strlen(folder)); file[strlen(folder)] = 0; /* append the filename */ if(folder[strlen(folder)-1] != '\\') strcat(file, "\\"); strncat(file, filename, strlen(filename)); } else { file = malloc(strlen(folder) + 2); if(!file) return GP_ERROR; strncpy(file, folder, strlen(folder)); file[strlen(folder)] = 0; } } else { return GP_ERROR; } /* change all /'s to \'s */ while((ptr = strchr(file, '/'))) { ptr[0] = '\\'; } /* there should not be a trailing '\', except for root folder */ if(strlen(file) > 1 && file[strlen(file)-1] == '\\') file[strlen(file)-1] = 0; switch (command) { case CMD_GET_PREVIEW: cb1 = 0x02; cb2 = 0x70; cb3 = 0x11; break; case CMD_GET_FILE: cb1 = 0x01; cb2 = 0x60; cb3 = 0x10; break; case CMD_LIST_FILES: cb1 = 0x01; cb2 = 0x60; cb3 = 0x01; break; } camera->pl->cmd_seqnum++; pkt_hdr[0] = 0x01; pkt_hdr[1] = dc3200_calc_seqnum(camera); pkt_hdr[2] = 0x80; pkt_hdr[3] = 0x00; pkt_hdr[4] = 0x20; pkt_hdr[5] = 0x03; pkt_hdr[6] = 26 + strlen(file); pkt_typ[0] = 0xC1; pkt_typ[1] = 0x50; pkt_typ[2] = 0x00; pkt_typ[3] = 0x00; pkt_typ[4] = 0x00; pkt_typ[5] = 0x00; pkt_typ[6] = 19 + strlen(file); pkt_cmd[0] = 0x04; pkt_cmd[1] = cb1; /* cmd */ pkt_cmd[2] = 0x00; pkt_cmd[3] = 0x01; /* ??? */ pkt_cmd[4] = (camera->pl->cmd_seqnum >> 8) & 0xff; pkt_cmd[5] = camera->pl->cmd_seqnum & 0xff; /* SEQ */ pkt_cmd[6] = cb2; pkt_cmd[7] = cb3; /* cmd */ pkt_cmd[8] = 0x00; pkt_cmd[9] = 0x01; /* ??? */ pkt_cmd[10] = 0x00; pkt_cmd[11] = 0x05; /* ??? */ pkt_len[0] = 0x00; pkt_len[1] = 0x00; pkt_len[2] = 0x00; pkt_len[3] = strlen(file) + 2; pkt_len[4] = 0x01; packet_len = sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd) + sizeof(pkt_len) + strlen(file) + 2; packet = malloc(packet_len); if(!packet) { free(file); return GP_ERROR; } /* clear packet */ memset(packet, 0, packet_len); /* copy pkt parts into packet */ memcpy(packet, pkt_hdr, sizeof(pkt_hdr)); memcpy(packet + sizeof(pkt_hdr), pkt_typ, sizeof(pkt_typ)); memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ), pkt_cmd, sizeof(pkt_cmd)); memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd), pkt_len, sizeof(pkt_len)); memcpy(packet + sizeof(pkt_hdr) + sizeof(pkt_typ) + sizeof(pkt_cmd) + sizeof(pkt_len), file, strlen(file)); free(file); /* send the command to list files */ if(dc3200_send_command(camera, packet, packet_len, ack, &ack_len) == GP_ERROR){ free(packet); return GP_ERROR; } free(packet); do { resp_len = DEF_PACKET_LEN; if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR) { return GP_ERROR; } if(dc3200_send_ack(camera, resp[1]) == GP_ERROR) { return GP_ERROR; } if(resp[1] == camera->pl->rec_seqnum) continue; camera->pl->rec_seqnum = resp[1]; /* * we decide what action to take based on * the number of packets we are expecting * * resp[7] holds this info * */ switch(resp[7]) { case 0xC1: /* * SINGLE PACKET */ /* get the total list length from the data header */ *data_len = bytes_to_l(resp[26], resp[27], resp[28], resp[29]); num_left = 0; data_start_pos = 31; *data_len -= 1; /* allocate a buffer to store all this data */ *data = malloc(*data_len); if(*data == NULL) { return GP_ERROR; } ptr_data = *data; /* copy this portion of the data */ memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos); /* incr the buff ptr */ ptr_data += resp_len - data_start_pos; break; case 0x41: /* * MULTIPACKET, START */ /* get the total list length from the data header */ *data_len = bytes_to_l(resp[34], resp[35], resp[36], resp[37]); num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]); total = num_left; data_start_pos = 39; *data_len -= 1; /* allocate a buffer to store all this data */ *data = malloc(*data_len); if(*data == NULL) { return GP_ERROR; } ptr_data = *data; /* copy this portion of the data */ memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos); /* incr the data ptr */ ptr_data += resp_len - data_start_pos; /* update gphoto2 frontend */ if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW) { pid = gp_context_progress_start(camera->pl->context,(int)*data_len,"%s", filename); gp_context_progress_update(camera->pl->context, pid, ptr_data - *data); if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) { free(*data); dc3200_cancel_get_data(camera); return GP_ERROR_CANCEL; } } break; case 0x01: /* * MULTIPACKET, MIDDLE */ /* calculate the number of packets remaining */ num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]); data_start_pos = 16; if(*data == NULL) { return GP_ERROR; } /* copy this portion of the data */ memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos); /* incr the buff ptr */ ptr_data += resp_len - data_start_pos; /* update gphoto2 frontend */ if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW) { gp_context_progress_update(camera->pl->context, pid, ptr_data - *data); if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) { free(*data); dc3200_cancel_get_data(camera); return GP_ERROR_CANCEL; } } break; case 0x81: /* * MULTIPACKET, END */ /* calculate the number of packets remaining */ num_left = bytes_to_l(resp[12], resp[13], resp[14], resp[15]); data_start_pos = 16; if(*data == NULL) { return GP_ERROR; } /* copy this portion of the data */ memcpy(ptr_data, resp + data_start_pos, resp_len - data_start_pos); /* incr the buff ptr */ ptr_data += resp_len - data_start_pos; /* update gphoto2 frontend */ if(command == CMD_GET_FILE || command == CMD_GET_PREVIEW) { gp_context_progress_update(camera->pl->context, pid, ptr_data - *data); if(gp_context_cancel(camera->pl->context) == GP_CONTEXT_FEEDBACK_CANCEL) { free(*data); dc3200_cancel_get_data(camera); return GP_ERROR_CANCEL; } } break; default: return GP_ERROR; } } while(num_left > 1); if(pid != 0 && (command == CMD_GET_FILE || command == CMD_GET_PREVIEW)) gp_context_progress_stop(camera->pl->context, pid); return GP_OK; } /* * dc3200_cancel_get_data * * stops a get data command * */ int dc3200_cancel_get_data(Camera *camera) { unsigned char pkt[20] = {0x01, dc3200_calc_seqnum(camera), 0x80, 0x00, 0x20, 0x03, 0x0d, 0xc1, 0x50, 0xc0, 0x00, 0x00, 0x00, 0x06, 0x04, 0x01, 0x00, 0x01, (camera->pl->cmd_seqnum >> 8) & 0xff, camera->pl->cmd_seqnum & 0xff}; unsigned char ack[ACK_PACKET_LEN], resp[DEF_PACKET_LEN]; int ack_len = ACK_PACKET_LEN, resp_len = DEF_PACKET_LEN; struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 1000; /* wait a bit ... */ select(0, 0, 0, 0, &timeout); /* clear the buffer */ dc3200_clear_read_buffer(camera); if(dc3200_send_command(camera, (unsigned char *)pkt, 20, ack, &ack_len) == GP_ERROR) return GP_ERROR; if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR) return GP_ERROR; else dc3200_send_ack(camera, resp[1]); resp_len = DEF_PACKET_LEN; if(dc3200_recv_response(camera, resp, &resp_len) == GP_ERROR) return GP_ERROR; else dc3200_send_ack(camera, resp[1]); return GP_OK; } /* * dc3200_send_command * * if cmd == NULL || cmd_len == 0, send_command waits for a response * otherwise, it sends a command and waits for an acknowledgement * */ int dc3200_send_command(Camera *camera, unsigned char *cmd, int cmd_len, unsigned char *ack, int *ack_len) { int sends, reads; int buff_len = *ack_len; int received = 0; unsigned char *buff = NULL; buff = malloc(sizeof(unsigned char) * *ack_len); if(buff == NULL) { return GP_ERROR; } sends = SEND_RETRIES; while(sends > 0) { reads = READ_RETRIES; /* check that we are acutally sending a command * and not just waiting for data */ if(cmd != NULL && cmd_len > 0) { /* clear the read buffer */ dc3200_clear_read_buffer(camera); /* send the command */ dc3200_send_packet(camera, cmd, cmd_len); } /* wait for response */ while(reads > 0) { if(dc3200_recv_packet(camera, buff, &buff_len) != GP_ERROR) { received = 1; break; } reads--; } if(received) { if(buff_len > *ack_len) { /* buffer size too small */ free(buff); return GP_ERROR; } /* sukksess */ *ack_len = buff_len; memcpy(ack, buff, buff_len); free(buff); return GP_OK; } else { sends--; } } /* send failed */ free(buff); return GP_ERROR; } /* * dc3200_recv_response * * receives a response from a previous command * */ int dc3200_recv_response(Camera *camera, unsigned char *resp, int *resp_len) { return dc3200_send_command(camera, NULL, 0, resp, resp_len); } /* * dc3200_send_ack * * sends an ack packet * */ int dc3200_send_ack(Camera *camera, int seqnum) { unsigned char ack[ACK_PACKET_LEN]; ack[0] = 0x01; ack[1] = seqnum + 16; return dc3200_send_packet(camera, ack, sizeof(ack)); } /* * dc3200_check_ack * * checks an ack packet (well ok not really) * */ int dc3200_check_ack(Camera *camera, unsigned char *ack, int ack_len) { return GP_OK; } /* * dc3200_send_packet * * compiles a packet from data and sends it * */ int dc3200_send_packet(Camera *camera, unsigned char *data, int data_len) { int res; int buff_len = data_len; unsigned char *buff = NULL; buff = malloc(sizeof(unsigned char) * buff_len); if(!buff) return GP_ERROR; memcpy(buff, data, buff_len); /* compile this into a packet */ res = dc3200_compile_packet(camera, &buff, &buff_len); if(res == GP_ERROR) return res; #ifdef DEBUG dump_buffer(buff, buff_len, "s", 16); #endif res = gp_port_write(camera->port, buff, data_len + 3); free(buff); return res; } /* * dc3200_recv_packet * * waits for a packet to arrive, checks it, and returns it * */ int dc3200_recv_packet(Camera *camera, unsigned char *data, int *data_len) { int complete = 0; int num_read = 0, res = 0, fails = 0; /* allocate storage for size, checksum, and EOP */ unsigned char *buff = NULL; buff = malloc(sizeof(unsigned char) * (*data_len + 3)); if(buff == NULL) { return GP_ERROR; } memset(buff, 0, *data_len + 3); /* * - read data until we get an 0xFF * - process packet * */ res = gp_port_read(camera->port, &buff[num_read], 1); while(res >= 0 && fails < READ_RETRIES) { if(res == 0) { /* read nothing */ fails++; } else { /* reset # of fails */ fails = 0; num_read++; if(buff[num_read-1] == 0xFF) { complete = 1; break; } if(num_read == *data_len + 3) { /* we've reached the buffer limit */ complete = 0; break; } } res = gp_port_read(camera->port, &buff[num_read], 1); } if(!complete) { /* packet incomplete */ return GP_ERROR; } #ifdef DEBUG dump_buffer(buff, num_read, "r", 16); #endif if(dc3200_process_packet(camera, buff, &num_read) == GP_ERROR) { return GP_ERROR; } /* save the last successful packet received time */ time(&(camera->pl->last)); memcpy(data, buff, *data_len); /* return with new packet size */ *data_len = num_read; free(buff); return GP_OK; } /* * dc3200_compile_packet * * changes 0xFF -> 0xFE 0x01 * 0xFE -> 0xFE 0x00 * adds packet length, checksum, and EOP (0xFF) * */ int dc3200_compile_packet(Camera *camera, unsigned char **data, int *data_len) { int count, i, j; unsigned char *new_data = NULL; unsigned char *tmp_ptr = NULL; /* realloc + 2 for len and checksum */ *data_len += 2; tmp_ptr = (unsigned char*)realloc(*data, *data_len); if(tmp_ptr == NULL) return GP_ERROR; *data = tmp_ptr; /* add length, checksum */ (*data)[*data_len - 2] = *data_len - 2; (*data)[*data_len - 1] = dc3200_calc_checksum(camera, *data, *data_len - 1); /* this is a hack to fix the 0xFF/0xFE problem. * we adjust a "don't care" byte so the checksum * is not 0xFF or 0xFE */ if((*data)[*data_len - 1] >= 0xFE) { if(*data_len > 19) { (*data)[19] += 2; (*data)[*data_len - 1] = dc3200_calc_checksum(camera, *data, *data_len - 1); printf("adjusting checksum to %02x\n", (*data)[*data_len - 1]); } } /* count number of 0xfe's and 0xff's */ count = 0; for(i=0;i<*data_len; i++) { if((*data)[i] == 0xFE || (*data)[i] == 0xFF) count++; } new_data = (unsigned char*)malloc(*data_len + count + 3); /* 3 for length, checksum, EOP */ if(!new_data) return GP_ERROR; j = 0; for(i=0;i<*data_len; i++) { if((*data)[i] == 0xFE || (*data)[i] == 0xFF) { printf("(*data)[i] == %02x\n", (*data)[i]); printf("(*data)[i] - 0xFE == %02x\n", (*data)[i] - 0xFE); new_data[j++] = 0xFE; new_data[j++] = (*data)[i] - 0xFE; } else { new_data[j++] = (*data)[i]; } } /* adjust the new packet count */ *data_len += count + 1; new_data[*data_len - 1] = 0xFF; /* free the old packet data */ free(*data); /* set the ptr */ *data = new_data; return GP_OK; } /* * dc3200_process_packet * * changes 0xFE 0x01 -> 0xFF * 0xFE 0x00 -> 0xFE * checks & removes packet length, checksum, EOP (0xFF) * */ int dc3200_process_packet(Camera *camera, unsigned char *data, int *data_len) { int count = 0, i; int length, checksum; unsigned char *buff; if(data == NULL || *data_len < 1) { return GP_ERROR; } /* allocate a new buffer */ buff = (unsigned char*)malloc(sizeof(unsigned char) * *data_len); if(!buff) return GP_ERROR; /* change 0xFE 0x00 | 0x01 -> 0xFF | 0xFE */ for(i=0; i<*data_len; i++) { if(data[i] == 0xFE) { if(i<*data_len-1) { /* so we don't run out of array bounds */ if(data[i+1] == 0x00) { buff[count] = 0xFE; /* advance i so we don't pick up the trailing byte */ i++; /* incr count */ count++; } else if(data[i+1] == 0x01) { buff[count] = 0xFF; i++; count++; } } else { /* we've found an 0xFE but there is no trailing byte */ free(buff); return GP_ERROR; } } else { buff[count] = data[i]; count++; } } /* copy over the old buffer */ memcpy(data, buff, count); length = data[count - 3]; checksum = data[count - 2]; /* make sure its a valid packet */ if(length != count - 3 || checksum != dc3200_calc_checksum(camera, data, count - 2)) { printf("%02x=%02x %02x=%02x\n", length, count - 3, checksum, dc3200_calc_checksum(camera, data, count - 2)); free(buff); return GP_ERROR; } /* adjust packet size, strip length, checksum, EOP */ *data_len = count - 3; free(buff); return GP_OK; } /* * dc3200_calc_checksum * * calculates the checksum for a byte array * */ int dc3200_calc_checksum(Camera *camera, unsigned char * buffer, int len) { int sum = 0, i; for(i=0; i<len; i++) { sum += buffer[i]; } sum = -sum + 0xFF; if(sum < 0) sum = sum & 0xFF; return sum; } /* * dc3200_calc_seqnum * * calculates the seqnum for a packet * */ int dc3200_calc_seqnum(Camera *camera) { if(camera->pl->pkt_seqnum >= 0x1F || camera->pl->pkt_seqnum < 0x10) { camera->pl->pkt_seqnum = 0x10; return camera->pl->pkt_seqnum; } else { camera->pl->pkt_seqnum++; return camera->pl->pkt_seqnum; } } /* * dc3200_keep_alive * * sends and receives a ping packet to keep the * camera awake * */ int dc3200_keep_alive(Camera *camera) { unsigned char ka[ACK_PACKET_LEN]; /* keepalive */ unsigned char ak[ACK_PACKET_LEN]; /* keepalive ack */ int ak_len = ACK_PACKET_LEN; ka[0] = 0xCF; ka[1] = 0x01; /* send keep alive packet */ if(dc3200_send_command(camera, ka, sizeof(ka), ak, &ak_len) == GP_ERROR) { return GP_ERROR; } /* check the ack (should be same packet) */ if(memcmp(ak,ka,ak_len) == 0) { return GP_OK; } return GP_ERROR; } /* * dc3200_clear_read_buffer * * clears data in the read buffer by reading it out * * there is definitely a better way to accomplish this... * */ int dc3200_clear_read_buffer(Camera *camera) { unsigned char byte; int count = 0; gp_port_set_timeout(camera->port, 0); while(gp_port_read(camera->port, &byte, 1) > 0) count++; if(count > 0) printf("cleared %d bytes from read buffer\n", count); gp_port_set_timeout(camera->port, TIMEOUT); return GP_OK; } /* * dump_buffer * * displays a byte array nicely formatted in hex format * */ int dump_buffer(unsigned char * buffer, int len, char * title, int bytesperline) { char spacer[80]; int i; memset(spacer, 0, sizeof(spacer)); memset(spacer, ' ', strlen(title)+2); printf("%s: ", title); for(i=0; i<len; i++) { if(i%bytesperline==0 && i > 0) { printf("\n%s", spacer); } printf("%02x ", buffer[i]); } printf("\n"); printf("%s: ", title); for(i=0; i<len; i++) { if(i%bytesperline==0 && i > 0) { printf("\n%s", spacer); } if(buffer[i] >= 0x20 && buffer[i] < 0x7F) { printf("%c", buffer[i]); } else { printf("."); } } printf("\n"); return GP_OK; } unsigned long bytes_to_l(int a, int b, int c, int d) { unsigned long res = a; res = res << 24 | b << 16 | c << 8 | d; return res; }