https://bitbucket.org/hudson/magic-lantern
Tip revision: 858a8c90cfc634da021c72ac878187679d88d554 authored by a1ex on 21 July 2014, 18:32:00 UTC
Close branch mlv_play
Close branch mlv_play
Tip revision: 858a8c9
gdb.patch
Index: ptp.c
===================================================================
--- ptp.c (revision 874)
+++ ptp.c (working copy)
@@ -1759,6 +1759,48 @@
return buf;
}
+char* ptp_chdk_gdb_upload(PTPParams* params, PTPDeviceInfo* deviceinfo)
+{
+ uint16_t ret;
+ PTPContainer ptp;
+ char *buf = NULL;
+
+ PTP_CNT_INIT(ptp);
+ ptp.Code=PTP_OC_CHDK;
+ ptp.Nparam=2;
+ ptp.Param1=PTP_CHDK_GDBStub_Upload;
+ ptp.Param2=1024;
+ ptp.Param3=0;
+ ret=ptp_transaction(params, &ptp, PTP_DP_GETDATA, 0, &buf);
+ if ( ret != 0x2001 )
+ {
+ ptp_error(params,"unexpected return code 0x%x",ret);
+ free(buf);
+ return NULL;
+ }
+ return buf;
+}
+
+int ptp_chdk_gdb_download(char *buf, PTPParams* params, PTPDeviceInfo* deviceinfo)
+{
+ uint16_t ret;
+ PTPContainer ptp;
+
+ PTP_CNT_INIT(ptp);
+ ptp.Code=PTP_OC_CHDK;
+ ptp.Nparam=2;
+ ptp.Param1=PTP_CHDK_GDBStub_Download;
+ ptp.Param2=strlen(buf);
+ ptp.Param3=0;
+ ret=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, strlen(buf), &buf);
+ if ( ret != 0x2001 )
+ {
+ ptp_error(params,"unexpected return code 0x%x",ret);
+ return 0;
+ }
+ return 1;
+}
+
int ptp_chdk_set_memory_long(int addr, int val, PTPParams* params, PTPDeviceInfo* deviceinfo)
{
uint16_t ret;
@@ -1787,8 +1829,10 @@
PTP_CNT_INIT(ptp);
ptp.Code=PTP_OC_CHDK;
- ptp.Nparam=1;
+ ptp.Nparam=2;
ptp.Param1=PTP_CHDK_CallFunction;
+ ptp.Param2=size;
+ ptp.Param3=0;
r=ptp_transaction(params, &ptp, PTP_DP_SENDDATA, size*sizeof(int), (char **) &args);
if ( r != 0x2001 )
{
Index: ptp.h
===================================================================
--- ptp.h (revision 874)
+++ ptp.h (working copy)
@@ -933,6 +933,10 @@
// data length is handled by ptp data phase
// input messages do not have type or subtype, they are always a string destined for the script (similar to USER/string)
// output param1 is ptp_chdk_script_msg_status
+ PTP_CHDK_GDBStub_Upload,
+ // param2 is the transfer buffer size
+ PTP_CHDK_GDBStub_Download,
+ // param2 is the transfer buffer size
};
// data types as used by ReadScriptMessage
@@ -1005,6 +1009,10 @@
int ptp_chdk_get_script_support(PTPParams* params, PTPDeviceInfo* deviceinfo, int *status);
int ptp_chdk_get_script_status(PTPParams* params, PTPDeviceInfo* deviceinfo, int *status);
+
+int ptp_chdk_gdb_download(char *buf, PTPParams* params, PTPDeviceInfo* deviceinfo);
+char* ptp_chdk_gdb_upload(PTPParams* params, PTPDeviceInfo* deviceinfo);
+
typedef struct {
unsigned size;
unsigned script_id; // id of script message is to/from
Index: ptpcam.c
===================================================================
--- ptpcam.c (revision 874)
+++ ptpcam.c (working copy)
@@ -2230,6 +2230,16 @@
close_camera(&ptp_usb,¶ms,dev);
}
+
+int kbhit()
+{
+ struct timeval tv = { 0L, 0L };
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(0, &fds);
+ return select(1, &fds, NULL, NULL, &tv);
+}
+
static void reset_connection()
{
if ( connected )
@@ -2316,6 +2326,193 @@
printf("\n");
}
+int engio_dump(unsigned char * data_buf, int length, int addr)
+{
+ unsigned int reg = 0;
+ unsigned int data = 0;
+ unsigned int pos = 0;
+
+ do
+ {
+ data = data_buf[pos + 0] | (data_buf[pos + 1] << 8) | (data_buf[pos + 2] << 16) | (data_buf[pos + 3] << 24);
+ pos += 4;
+ reg = data_buf[pos + 0] | (data_buf[pos + 1] << 8) | (data_buf[pos + 2] << 16) | (data_buf[pos + 3] << 24);
+ pos += 4;
+ if(reg != 0xFFFFFFFF)
+ {
+ printf("[0x%08X] <- [0x%08X]\r\n", reg, data);
+ }
+ } while (reg != 0xFFFFFFFF && pos <= length - 8);
+
+ printf("\r\n");
+}
+
+int adtg_dump(unsigned char * data_buf, int length, int addr)
+{
+ unsigned int reg = 0;
+ unsigned int data = 0;
+ unsigned int pos = 0;
+
+ do
+ {
+ data = data_buf[pos + 0] | (data_buf[pos + 1] << 8);
+ pos += 2;
+ reg = data_buf[pos + 0] | (data_buf[pos + 1] << 8);
+ pos += 2;
+ if(reg != 0xFFFF && data != 0xFFFF)
+ {
+ printf("[0x%04X] <- [0x%04X]\r\n", reg, data);
+ }
+ } while (reg != 0xFFFF && data != 0xFFFF && pos <= length - 4);
+
+ printf("\r\n");
+}
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#define INVALID_SOCKET -1
+int gdb_port = 23946;
+
+int accepttimeout ( int s, struct sockaddr *addr, int *addrlen, int timeout )
+{
+ fd_set fds;
+ int n;
+ struct timeval tv;
+
+ // set up the file descriptor set
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+
+ // set up the struct timeval for the timeout
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout * 1000;
+
+ // wait until timeout or data received
+ n = select(s+1, &fds, NULL, NULL, &tv);
+ if (n == 0) return -2; // timeout!
+ if (n == -1) return -1; // error
+
+ // data must be here, so do a normal recv()
+ return accept ( s, addr, addrlen );
+}
+
+
+int recvtimeout ( int s, char *buf, int len, int timeout )
+{
+ fd_set fds;
+ int n;
+ struct timeval tv;
+
+ // set up the file descriptor set
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+
+ // set up the struct timeval for the timeout
+ tv.tv_sec = 0;
+ tv.tv_usec = timeout * 1000;
+
+ // wait until timeout or data received
+ n = select(s+1, &fds, NULL, NULL, &tv);
+ if (n == 0) return -2; // timeout!
+ if (n == -1) return -1; // error
+
+ // data must be here, so do a normal recv()
+ return recv ( s, buf, len, 0 );
+}
+
+
+unsigned int gdb_loop (int socket)
+{
+ char buffer[8192];
+ while(1)
+ {
+ {
+ int recvStatus = recv ( socket, buffer, 8192, MSG_DONTWAIT );//recvtimeout (socket, buffer, 8192, 1);
+
+ if(recvStatus > 0)
+ {
+ buffer[recvStatus] = 0;
+ printf("Download: '%s'\n", buffer);
+
+ if (ptp_chdk_gdb_download(buffer,¶ms,¶ms.deviceinfo) == 0)
+ {
+ printf("error sending command\n");
+ return;
+ }
+ }
+ else if((recvStatus == EAGAIN ) || (recvStatus == EWOULDBLOCK))//-2)
+ {
+ }
+ else if((recvStatus == -1 ) || (recvStatus == EWOULDBLOCK))//-2)
+ {
+ }
+ else
+ {
+ printf("error %i during recvtimeout\n", recvStatus );
+ return;
+ }
+ }
+
+ /* upload */
+ {
+ char *buf;
+
+ buf = ptp_chdk_gdb_upload(¶ms,¶ms.deviceinfo);
+
+ if(buf != NULL && strlen(buf) > 0)
+ {
+ printf("Upload: '%s'\n", buf);
+ send(socket, buf, strlen(buf), 0 );
+ }
+ }
+ }
+}
+
+unsigned int gdb_listen ( )
+{
+ struct sockaddr_in local;
+ struct sockaddr_in remote;
+ int remotelen = sizeof ( remote );
+ int server_fd = INVALID_SOCKET;
+ int client_fd = INVALID_SOCKET;
+
+#ifdef WIN32
+ if ( WSAStartup ( 0x101, &gdb_wsadata ) != 0 )
+ return E_FAIL;
+#endif
+
+ local.sin_family = AF_INET;
+ local.sin_addr.s_addr = INADDR_ANY;
+ local.sin_port = htons ( (u_short)gdb_port );
+
+ server_fd = socket ( AF_INET, SOCK_STREAM, 0 );
+ if ( server_fd == INVALID_SOCKET )
+ printf ("(socket error)\n");
+ else if ( bind ( server_fd, (struct sockaddr*)&local, sizeof(local) ) !=0 )
+ printf ("(port already used)\n" );
+ else if ( listen ( server_fd, 10 ) !=0 )
+ printf ("(listen error)\n");
+ else
+ {
+ while ( 1 )
+ {
+ client_fd = accepttimeout ( server_fd, (struct sockaddr*)&remote, &remotelen, 500 );
+ if ( client_fd >= 0 )
+ {
+ close ( server_fd );
+ printf ("remote connected: %s\n", inet_ntoa ( remote.sin_addr ) );
+ gdb_loop(client_fd);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
int chdk(int busn, int devn, short force)
{
char buf[CHDKBUFS], *s;
@@ -2477,7 +2674,7 @@
end = start+strtoul(s+1,NULL,0);
} else {
start = strtoul(buf2,NULL,0);
- end = start+1;
+ end = start + 0x100;
}
if ( (buf2 = ptp_chdk_get_memory(start,end-start,¶ms,¶ms.deviceinfo)) == NULL )
@@ -2488,8 +2685,432 @@
free(buf2);
}
- } else if ( !strncmp("set ",buf,4) )
+ } else if ( !strncmp("engio",buf,3) )
{
+ unsigned int addr = 0;
+ char *buf2;
+ unsigned int block_size = 0x200;
+ unsigned char *data_buf;
+
+ buf2 = strchr(buf,' ')+1;
+
+ while((*buf2 != '\000') && (*buf2 == ' '))
+ {
+ buf2++;
+ }
+ addr = strtoul(buf2,NULL,0);
+ printf("Reading engio buffers from 0x%08X\r\n", addr);
+
+ if(addr > 0)
+ {
+ unsigned int reg = 0;
+ unsigned int data = 0;
+
+ while(reg != 0xFFFFFFFF)
+ {
+ if ( (data_buf = ptp_chdk_get_memory(addr,block_size,¶ms,¶ms.deviceinfo)) == NULL )
+ {
+ printf("error getting memory\n");
+ break;
+ }
+ else
+ {
+ unsigned int pos = 0;
+ do
+ {
+ reg = data_buf[pos + 0] | (data_buf[pos + 1] << 8) | (data_buf[pos + 2] << 16) | (data_buf[pos + 3] << 24);
+ pos += 4;
+ data = data_buf[pos + 0] | (data_buf[pos + 1] << 8) | (data_buf[pos + 2] << 16) | (data_buf[pos + 3] << 24);
+ pos += 4;
+ if(reg != 0xFFFFFFFF)
+ {
+ printf("[0x%08X] <- [0x%08X]\r\n", reg, data);
+ }
+ } while (reg != 0xFFFFFFFF && pos <= block_size - 8);
+ free(data_buf);
+
+ addr += block_size;
+ }
+ }
+ }
+
+
+ } else if ( !strncmp("dump ",buf,5) )
+ {
+ unsigned long long start;
+ unsigned long long end;
+ unsigned long long addr;
+ unsigned long long len;
+ unsigned long long block_size = 0x1000;
+ unsigned char *s;
+ unsigned char *buf2;
+ unsigned char *data_buf;
+ FILE *dumpfile;
+
+ buf2 = strchr(buf,' ')+1;
+
+ if ( (s = strchr(buf2,'-')) != NULL )
+ {
+ *s = '\0';
+ start = strtoul(buf2,NULL,0);
+ end = strtoul(s+1,NULL,0)+1;
+ }
+ else if ( (s = strchr(buf2,' ')) != NULL )
+ {
+ *s = '\0';
+ start = strtoul(buf2,NULL,0);
+ end = start+strtoul(s+1,NULL,0);
+ }
+ else {
+ start = strtoul(buf2,NULL,0);
+ end = start + 0x100;
+ }
+
+ addr = start;
+
+ dumpfile = fopen("dump.bin", "wb");
+ if(dumpfile != NULL)
+ {
+ while(addr < end)
+ {
+ /* check for maximum block size */
+ if(addr + block_size > end)
+ {
+ len = end - addr;
+ }
+ else
+ {
+ len = block_size;
+ }
+
+ printf("\rReading: 0x%08X...", (unsigned int)addr);
+ fflush(stdout);
+
+ if ( (data_buf = ptp_chdk_get_memory(addr,block_size,¶ms,¶ms.deviceinfo)) == NULL )
+ {
+ printf("error getting memory\n");
+ break;
+ }
+ else
+ {
+ fwrite(data_buf, len, 1, dumpfile);
+ free(data_buf);
+ }
+ addr += len;
+ }
+ fclose(dumpfile);
+ printf("\r\nDone\r\n");
+ }
+
+ }else if ( !strncmp("ptr",buf,3) )
+ {
+ unsigned int current_address = 0;
+ int done = 0;
+ char *buf2;
+ unsigned char *data_buf;
+
+ while(!done)
+ {
+ int addr = 0;
+
+ if ( fgets(buf,CHDKBUFS-1,stdin) == NULL )
+ {
+ printf("\n");
+ break;
+ }
+
+ if(strlen(buf) < 3)
+ {
+ break;
+ }
+
+ buf2 = buf;
+
+ while((*buf2 != '\000') && (*buf2 == ' '))
+ {
+ buf2++;
+ }
+ addr = strtoul(buf2,NULL,0);
+ printf("offset: 0x%08X -> ", addr);
+
+ current_address += addr;
+ printf("read: 0x%08X -> ", current_address);
+
+ if(current_address > 0)
+ {
+ if ( (data_buf = ptp_chdk_get_memory(current_address,0x20,¶ms,¶ms.deviceinfo)) == NULL )
+ {
+ printf("error getting memory\n");
+ break;
+ }
+ else
+ {
+ current_address = data_buf[0] | (data_buf[1] << 8) | (data_buf[2] << 16) | (data_buf[3] << 24);
+ printf("next: 0x%08X\r\n", current_address);
+ free(data_buf);
+ }
+ }
+ }
+ }
+ else if (!strncmp("gdb s ",buf,6))
+ {
+ char *cmd = &(buf[6]);
+
+ if (ptp_chdk_gdb_download(cmd,¶ms,¶ms.deviceinfo) == 0)
+ {
+ printf("error sending command\n");
+ }
+ }
+ else if (!strncmp("gdbproxy",buf,8))
+ {
+ gdb_listen();
+ }
+ else if (!strncmp("gdb r",buf,5))
+ {
+ char *buf;
+
+ buf = ptp_chdk_gdb_upload(¶ms,¶ms.deviceinfo);
+
+ if(buf == NULL)
+ {
+ printf("error receiving response\n");
+ }
+ else
+ {
+ printf("gdb> '%s'\n", buf);
+ }
+ }
+ else if ( !strncmp("delta ",buf,6) || !strncmp("adtgdelta ",buf,6) || !strncmp("engiodelta ",buf,6))
+ {
+ int regdump = 0;
+ int start;
+ int end;
+ int deltaPos;
+ int deltaNum = 0;
+ char *s;
+ unsigned char *buf2;
+ unsigned int *deltaCount;
+
+ if( !strncmp("adtgdelta ",buf,6))
+ {
+ regdump = 1;
+ }
+ if( !strncmp("engiodelta ",buf,6))
+ {
+ regdump = 2;
+ }
+ buf2 = strchr(buf,' ')+1;
+
+ if ( (s = strchr(buf2,'-')) != NULL )
+ {
+ *s = '\0';
+ start = strtoul(buf2,NULL,0);
+ end = strtoul(s+1,NULL,0)+1;
+ }
+ else if ( (s = strchr(buf2,' ')) != NULL )
+ {
+ *s = '\0';
+ start = strtoul(buf2,NULL,0);
+ end = start+strtoul(s+1,NULL,0);
+ }
+ else
+ {
+ start = strtoul(buf2,NULL,0);
+ end = start+0x100;
+ }
+
+ /* get reference buffer */
+ if ( (buf2 = ptp_chdk_get_memory(start,end-start,¶ms,¶ms.deviceinfo)) == NULL )
+ {
+ printf("error getting memory\n");
+ }
+ else
+ {
+ if(regdump == 1)
+ {
+ adtg_dump(buf2, end-start, start);
+ }
+ else if(regdump == 2)
+ {
+ engio_dump(buf2, end-start, start);
+ }
+ else
+ {
+ hexdump(buf2,end-start,start);
+ }
+ }
+
+
+ deltaCount = malloc(sizeof(unsigned int) * (end-start));
+
+ for(deltaPos = 0; deltaPos < (end-start); deltaPos++)
+ {
+ deltaCount[deltaPos] = 0;
+ }
+
+ while(!kbhit())
+ {
+ unsigned char *buf3;
+
+ /* get reference buffer */
+ if ( (buf3 = ptp_chdk_get_memory(start,end-start,¶ms,¶ms.deviceinfo)) == NULL )
+ {
+ printf("error getting memory\n");
+ }
+ else
+ {
+ int pos = 0;
+ int deltas = 0;
+
+ for(pos = 0; pos < (end-start); pos++)
+ {
+ if(buf2[pos] != buf3[pos] && deltaCount[pos] < 10)
+ {
+ printf("Ignoring delta at 0x%08X: 0x%02X -> 0x%02X\r\n", start + pos, buf2[pos], buf3[pos]);
+ deltaCount[pos]++;
+ deltas++;
+ }
+ }
+
+ if(deltas)
+ {
+ memcpy(buf2, buf3, end-start);
+ }
+ free(buf3);
+ }
+ }
+ fgetc(stdin);
+
+
+
+ while(!kbhit())
+ {
+ unsigned char *buf3;
+
+ /* get reference buffer */
+ if ( (buf3 = ptp_chdk_get_memory(start,end-start,¶ms,¶ms.deviceinfo)) == NULL )
+ {
+ printf("error getting memory\n");
+ }
+ else
+ {
+ int pos = 0;
+ int deltas = 0;
+
+ for(pos = 0; pos < (end-start); pos++)
+ {
+ if(deltaCount[pos] >= 10)
+ {
+ buf3[pos] = 0;
+ buf2[pos] = 0;
+ }
+
+ if(buf2[pos] != buf3[pos] )
+ {
+ printf("Delta #%i at 0x%08X: 0x%02X -> 0x%02X\r\n", deltaNum++, start + pos, buf2[pos], buf3[pos]);
+ deltas++;
+ }
+
+ }
+ if(deltas)
+ {
+ memcpy(buf2, buf3, end-start);
+ if(regdump == 1)
+ {
+ adtg_dump(buf2, end-start, start);
+ }
+ else if(regdump == 2)
+ {
+ engio_dump(buf2, end-start, start);
+ }
+ else
+ {
+ hexdump(buf2,end-start,start);
+ }
+ }
+ free(buf3);
+ }
+ }
+
+ free(buf2);
+ fgetc(stdin);
+
+ }
+ else if ( !strncmp("rate ",buf,5))
+ {
+ int regdump = 0;
+ int start;
+ int deltaPos;
+ int deltaNum = 0;
+ char *s;
+ unsigned char *buf2;
+ unsigned int *deltaCount;
+ unsigned int oldVal = 0;
+ unsigned int maxVal = 0;
+ struct timeval oldTv;
+ struct timeval nextTv;
+ unsigned int loops = 0;
+ double avgDelta = -1.0f;
+
+ buf2 = strchr(buf,' ') + 1;
+
+ start = strtoul(buf2,NULL,0);
+
+ while(!kbhit())
+ {
+ unsigned char *buf3;
+
+ /* get reference buffer */
+ if ( (buf3 = ptp_chdk_get_memory(start,4,¶ms,¶ms.deviceinfo)) == NULL )
+ {
+ printf("error getting memory\n");
+ }
+ else
+ {
+ unsigned int nextVal = 0;
+
+ nextVal = *((unsigned int*)buf3);
+ if(maxVal < nextVal)
+ {
+ maxVal = nextVal;
+ }
+
+ if(nextVal < oldVal)
+ {
+ unsigned int delta = 0;
+
+ gettimeofday(&nextTv, NULL);
+ delta = ((nextTv.tv_sec - oldTv.tv_sec) * 1000000) + (nextTv.tv_usec - oldTv.tv_usec);
+
+
+ if(loops++ > 0)
+ {
+ double rate = 0;
+
+ if(avgDelta < 0)
+ {
+ avgDelta = delta;
+ }
+ else
+ {
+ avgDelta = avgDelta - avgDelta/loops + delta / loops;
+ }
+
+ rate = 1000000.0f / (avgDelta / maxVal);
+ printf("Overflows: %i µsec (avg: %f), maxVal = 0x%08X, tickRate = %f Hz\n", delta, avgDelta, maxVal, rate);
+ }
+ }
+
+ oldVal = nextVal;
+ oldTv = nextTv;
+
+ free(buf3);
+ }
+ }
+ fgetc(stdin);
+ }
+ else if ( !strncmp("set ",buf,4) )
+ {
int addr;
int val;
char *s;