Loading .gitignore 0 → 100644 +1 −0 Original line number Original line Diff line number Diff line *~ adb/framebuffer_service.c +53 −17 Original line number Original line Diff line number Diff line Loading @@ -28,18 +28,35 @@ #include <sys/mman.h> #include <sys/mman.h> /* TODO: /* TODO: ** - grab the current buffer, not the first buffer ** - sync with vsync to avoid tearing ** - sync with vsync to avoid tearing */ */ /* This version number defines the format of the fbinfo struct. It must match versioning in ddms where this data is consumed. */ #define DDMS_RAWIMAGE_VERSION 1 struct fbinfo { unsigned int version; unsigned int bpp; unsigned int size; unsigned int width; unsigned int height; unsigned int red_offset; unsigned int red_length; unsigned int blue_offset; unsigned int blue_length; unsigned int green_offset; unsigned int green_length; unsigned int alpha_offset; unsigned int alpha_length; } __attribute__((packed)); void framebuffer_service(int fd, void *cookie) void framebuffer_service(int fd, void *cookie) { { struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo; int fb; int fb, offset; void *ptr = MAP_FAILED; char x[256]; char x; unsigned fbinfo[4]; struct fbinfo fbinfo; unsigned i, bytespp; fb = open("/dev/graphics/fb0", O_RDONLY); fb = open("/dev/graphics/fb0", O_RDONLY); if(fb < 0) goto done; if(fb < 0) goto done; Loading @@ -47,24 +64,43 @@ void framebuffer_service(int fd, void *cookie) if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; fcntl(fb, F_SETFD, FD_CLOEXEC); fcntl(fb, F_SETFD, FD_CLOEXEC); fbinfo[0] = 16; bytespp = vinfo.bits_per_pixel / 8; fbinfo[1] = vinfo.xres * vinfo.yres * 2; fbinfo[2] = vinfo.xres; fbinfo[3] = vinfo.yres; ptr = mmap(0, fbinfo[1], PROT_READ, MAP_SHARED, fb, 0); fbinfo.version = DDMS_RAWIMAGE_VERSION; if(ptr == MAP_FAILED) goto done; fbinfo.bpp = vinfo.bits_per_pixel; fbinfo.size = vinfo.xres * vinfo.yres * bytespp; fbinfo.width = vinfo.xres; fbinfo.height = vinfo.yres; fbinfo.red_offset = vinfo.red.offset; fbinfo.red_length = vinfo.red.length; fbinfo.green_offset = vinfo.green.offset; fbinfo.green_length = vinfo.green.length; fbinfo.blue_offset = vinfo.blue.offset; fbinfo.blue_length = vinfo.blue.length; fbinfo.alpha_offset = vinfo.transp.offset; fbinfo.alpha_length = vinfo.transp.length; if(writex(fd, fbinfo, sizeof(unsigned) * 4)) goto done; /* HACK: for several of our 3d cores a specific alignment * is required so the start of the fb may not be an integer number of lines * from the base. As a result we are storing the additional offset in * xoffset. This is not the correct usage for xoffset, it should be added * to each line, not just once at the beginning */ offset = vinfo.xoffset * bytespp; for(;;) { offset += vinfo.xres * vinfo.yoffset * bytespp; if(readx(fd, &x, 1)) goto done; if(writex(fd, ptr, fbinfo[1])) goto done; if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done; lseek(fb, offset, SEEK_SET); for(i = 0; i < fbinfo.size; i += 256) { if(readx(fb, &x, 256)) goto done; if(writex(fd, &x, 256)) goto done; } } if(readx(fb, &x, fbinfo.size % 256)) goto done; if(writex(fd, &x, fbinfo.size % 256)) goto done; done: done: if(ptr != MAP_FAILED) munmap(ptr, fbinfo[1]); if(fb >= 0) close(fb); if(fb >= 0) close(fb); close(fd); close(fd); } } adb/usb_vendors.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,8 @@ #define VENDOR_ID_HUAWEI 0x12D1 #define VENDOR_ID_HUAWEI 0x12D1 // Acer's USB Vendor ID // Acer's USB Vendor ID #define VENDOR_ID_ACER 0x0502 #define VENDOR_ID_ACER 0x0502 // Sony Ericsson's USB Vendor ID #define VENDOR_ID_SONY_ERICSSON 0x0FCE /** built-in vendor list */ /** built-in vendor list */ int builtInVendorIds[] = { int builtInVendorIds[] = { Loading @@ -59,6 +61,7 @@ int builtInVendorIds[] = { VENDOR_ID_LGE, VENDOR_ID_LGE, VENDOR_ID_HUAWEI, VENDOR_ID_HUAWEI, VENDOR_ID_ACER, VENDOR_ID_ACER, VENDOR_ID_SONY_ERICSSON, }; }; #define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) #define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) Loading debuggerd/debuggerd.c +95 −105 Original line number Original line Diff line number Diff line Loading @@ -48,8 +48,6 @@ extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, int *frame0_pc_sane, int *frame0_pc_sane, bool at_fault); bool at_fault); static char **process_name_ptr; static int logsocket = -1; static int logsocket = -1; #define ANDROID_LOG_INFO 4 #define ANDROID_LOG_INFO 4 Loading Loading @@ -128,6 +126,7 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, struct pt_regs r; struct pt_regs r; int sp_depth; int sp_depth; bool only_in_tombstone = !at_fault; bool only_in_tombstone = !at_fault; char code_buffer[80]; if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; sp = r.ARM_sp; sp = r.ARM_sp; Loading @@ -140,26 +139,53 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, pc = r.ARM_lr; pc = r.ARM_lr; } } _LOG(tfd, true, "code%s:\n", frame0_pc_sane ? "" : " (around frame #01)"); _LOG(tfd, only_in_tombstone, "\ncode around %s:\n", frame0_pc_sane ? "pc" : "lr"); end = p = pc & ~3; end = p = pc & ~3; p -= 16; p -= 16; end += 16; /* Dump the code as: /* Dump the code around PC as: * PC contents * addr contents * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 */ */ while (p <= end) { while (p <= end) { int i; int i; _LOG(tfd, true, " %08x ", p); sprintf(code_buffer, "%08x ", p); for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) { data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); _LOG(tfd, true, " %08x", data); sprintf(code_buffer + strlen(code_buffer), "%08x ", data); p += 4; p += 4; } } _LOG(tfd, true, "\n", p); _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); } if (frame0_pc_sane) { _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); end = p = r.ARM_lr & ~3; p -= 16; end += 16; /* Dump the code around LR as: * addr contents * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 */ while (p <= end) { int i; sprintf(code_buffer, "%08x ", p); for (i = 0; i < 4; i++) { data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); sprintf(code_buffer + strlen(code_buffer), "%08x ", data); p += 4; } _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); } } } p = sp - 64; p = sp - 64; Loading @@ -177,7 +203,7 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, end += 0xff; end += 0xff; } } _LOG(tfd, only_in_tombstone, "stack:\n"); _LOG(tfd, only_in_tombstone, "\nstack:\n"); /* If the crash is due to PC == 0, there will be two frames that /* If the crash is due to PC == 0, there will be two frames that * have identical SP value. * have identical SP value. Loading Loading @@ -330,7 +356,7 @@ static void parse_exidx_info(mapinfo *milist, pid_t pid) ptr = (Elf32_Phdr *) (mi->start + ehdr.e_phoff); ptr = (Elf32_Phdr *) (mi->start + ehdr.e_phoff); for (i = 0; i < ehdr.e_phnum; i++) { for (i = 0; i < ehdr.e_phnum; i++) { /* Parse the program header */ /* Parse the program header */ get_remote_struct(pid, (void *) ptr+i, &phdr, get_remote_struct(pid, (char *) ptr+i, &phdr, sizeof(Elf32_Phdr)); sizeof(Elf32_Phdr)); /* Found a EXIDX segment? */ /* Found a EXIDX segment? */ if (phdr.p_type == PT_ARM_EXIDX) { if (phdr.p_type == PT_ARM_EXIDX) { Loading Loading @@ -401,40 +427,6 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) } } } } /* FIXME: unused: use it or lose it*/ #if 0 static void start_gdbserver_vs(int pid, int port) { pid_t p; char *args[5]; char commspec[16]; char pidspec[16]; p = fork(); if(p < 0) { LOG("could not fork()\n"); return; } if(p == 0) { sprintf(commspec, ":%d", port); sprintf(pidspec, "%d", pid); args[0] = "/system/bin/gdbserver"; args[1] = commspec; args[2] = "--attach"; args[3] = pidspec; args[4] = 0; exit(execv(args[0], args)); } else { LOG("gdbserver pid=%d port=%d targetpid=%d\n", p, port, pid); sleep(5); } } #endif #define MAX_TOMBSTONES 10 #define MAX_TOMBSTONES 10 #define typecheck(x,y) { \ #define typecheck(x,y) { \ Loading Loading @@ -807,13 +799,11 @@ done: if(fd != -1) close(fd); if(fd != -1) close(fd); } } int main(int argc, char **argv) int main() { { int s; int s; struct sigaction act; struct sigaction act; process_name_ptr = argv; logsocket = socket_local_client("logd", logsocket = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM); ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM); if(logsocket < 0) { if(logsocket < 0) { Loading fastboot/fastboot.c +4 −2 Original line number Original line Diff line number Diff line Loading @@ -147,10 +147,12 @@ oops: int match_fastboot(usb_ifc_info *info) int match_fastboot(usb_ifc_info *info) { { if(!(vendor_id && (info->dev_vendor == vendor_id)) && if(!(vendor_id && (info->dev_vendor == vendor_id)) && (info->dev_vendor != 0x18d1) && (info->dev_vendor != 0x18d1) && // Google (info->dev_vendor != 0x0451) && (info->dev_vendor != 0x0451) && (info->dev_vendor != 0x22b8) && // Motorola (info->dev_vendor != 0x0502) && (info->dev_vendor != 0x0502) && (info->dev_vendor != 0x0bb4)) return -1; (info->dev_vendor != 0x0bb4)) // HTC return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; if(info->ifc_subclass != 0x42) return -1; if(info->ifc_protocol != 0x03) return -1; if(info->ifc_protocol != 0x03) return -1; Loading Loading
adb/framebuffer_service.c +53 −17 Original line number Original line Diff line number Diff line Loading @@ -28,18 +28,35 @@ #include <sys/mman.h> #include <sys/mman.h> /* TODO: /* TODO: ** - grab the current buffer, not the first buffer ** - sync with vsync to avoid tearing ** - sync with vsync to avoid tearing */ */ /* This version number defines the format of the fbinfo struct. It must match versioning in ddms where this data is consumed. */ #define DDMS_RAWIMAGE_VERSION 1 struct fbinfo { unsigned int version; unsigned int bpp; unsigned int size; unsigned int width; unsigned int height; unsigned int red_offset; unsigned int red_length; unsigned int blue_offset; unsigned int blue_length; unsigned int green_offset; unsigned int green_length; unsigned int alpha_offset; unsigned int alpha_length; } __attribute__((packed)); void framebuffer_service(int fd, void *cookie) void framebuffer_service(int fd, void *cookie) { { struct fb_var_screeninfo vinfo; struct fb_var_screeninfo vinfo; int fb; int fb, offset; void *ptr = MAP_FAILED; char x[256]; char x; unsigned fbinfo[4]; struct fbinfo fbinfo; unsigned i, bytespp; fb = open("/dev/graphics/fb0", O_RDONLY); fb = open("/dev/graphics/fb0", O_RDONLY); if(fb < 0) goto done; if(fb < 0) goto done; Loading @@ -47,24 +64,43 @@ void framebuffer_service(int fd, void *cookie) if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; fcntl(fb, F_SETFD, FD_CLOEXEC); fcntl(fb, F_SETFD, FD_CLOEXEC); fbinfo[0] = 16; bytespp = vinfo.bits_per_pixel / 8; fbinfo[1] = vinfo.xres * vinfo.yres * 2; fbinfo[2] = vinfo.xres; fbinfo[3] = vinfo.yres; ptr = mmap(0, fbinfo[1], PROT_READ, MAP_SHARED, fb, 0); fbinfo.version = DDMS_RAWIMAGE_VERSION; if(ptr == MAP_FAILED) goto done; fbinfo.bpp = vinfo.bits_per_pixel; fbinfo.size = vinfo.xres * vinfo.yres * bytespp; fbinfo.width = vinfo.xres; fbinfo.height = vinfo.yres; fbinfo.red_offset = vinfo.red.offset; fbinfo.red_length = vinfo.red.length; fbinfo.green_offset = vinfo.green.offset; fbinfo.green_length = vinfo.green.length; fbinfo.blue_offset = vinfo.blue.offset; fbinfo.blue_length = vinfo.blue.length; fbinfo.alpha_offset = vinfo.transp.offset; fbinfo.alpha_length = vinfo.transp.length; if(writex(fd, fbinfo, sizeof(unsigned) * 4)) goto done; /* HACK: for several of our 3d cores a specific alignment * is required so the start of the fb may not be an integer number of lines * from the base. As a result we are storing the additional offset in * xoffset. This is not the correct usage for xoffset, it should be added * to each line, not just once at the beginning */ offset = vinfo.xoffset * bytespp; for(;;) { offset += vinfo.xres * vinfo.yoffset * bytespp; if(readx(fd, &x, 1)) goto done; if(writex(fd, ptr, fbinfo[1])) goto done; if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done; lseek(fb, offset, SEEK_SET); for(i = 0; i < fbinfo.size; i += 256) { if(readx(fb, &x, 256)) goto done; if(writex(fd, &x, 256)) goto done; } } if(readx(fb, &x, fbinfo.size % 256)) goto done; if(writex(fd, &x, fbinfo.size % 256)) goto done; done: done: if(ptr != MAP_FAILED) munmap(ptr, fbinfo[1]); if(fb >= 0) close(fb); if(fb >= 0) close(fb); close(fd); close(fd); } }
adb/usb_vendors.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -49,6 +49,8 @@ #define VENDOR_ID_HUAWEI 0x12D1 #define VENDOR_ID_HUAWEI 0x12D1 // Acer's USB Vendor ID // Acer's USB Vendor ID #define VENDOR_ID_ACER 0x0502 #define VENDOR_ID_ACER 0x0502 // Sony Ericsson's USB Vendor ID #define VENDOR_ID_SONY_ERICSSON 0x0FCE /** built-in vendor list */ /** built-in vendor list */ int builtInVendorIds[] = { int builtInVendorIds[] = { Loading @@ -59,6 +61,7 @@ int builtInVendorIds[] = { VENDOR_ID_LGE, VENDOR_ID_LGE, VENDOR_ID_HUAWEI, VENDOR_ID_HUAWEI, VENDOR_ID_ACER, VENDOR_ID_ACER, VENDOR_ID_SONY_ERICSSON, }; }; #define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) #define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) Loading
debuggerd/debuggerd.c +95 −105 Original line number Original line Diff line number Diff line Loading @@ -48,8 +48,6 @@ extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, int *frame0_pc_sane, int *frame0_pc_sane, bool at_fault); bool at_fault); static char **process_name_ptr; static int logsocket = -1; static int logsocket = -1; #define ANDROID_LOG_INFO 4 #define ANDROID_LOG_INFO 4 Loading Loading @@ -128,6 +126,7 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, struct pt_regs r; struct pt_regs r; int sp_depth; int sp_depth; bool only_in_tombstone = !at_fault; bool only_in_tombstone = !at_fault; char code_buffer[80]; if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; sp = r.ARM_sp; sp = r.ARM_sp; Loading @@ -140,26 +139,53 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, pc = r.ARM_lr; pc = r.ARM_lr; } } _LOG(tfd, true, "code%s:\n", frame0_pc_sane ? "" : " (around frame #01)"); _LOG(tfd, only_in_tombstone, "\ncode around %s:\n", frame0_pc_sane ? "pc" : "lr"); end = p = pc & ~3; end = p = pc & ~3; p -= 16; p -= 16; end += 16; /* Dump the code as: /* Dump the code around PC as: * PC contents * addr contents * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 */ */ while (p <= end) { while (p <= end) { int i; int i; _LOG(tfd, true, " %08x ", p); sprintf(code_buffer, "%08x ", p); for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) { data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); _LOG(tfd, true, " %08x", data); sprintf(code_buffer + strlen(code_buffer), "%08x ", data); p += 4; p += 4; } } _LOG(tfd, true, "\n", p); _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); } if (frame0_pc_sane) { _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); end = p = r.ARM_lr & ~3; p -= 16; end += 16; /* Dump the code around LR as: * addr contents * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 */ while (p <= end) { int i; sprintf(code_buffer, "%08x ", p); for (i = 0; i < 4; i++) { data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); sprintf(code_buffer + strlen(code_buffer), "%08x ", data); p += 4; } _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); } } } p = sp - 64; p = sp - 64; Loading @@ -177,7 +203,7 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, end += 0xff; end += 0xff; } } _LOG(tfd, only_in_tombstone, "stack:\n"); _LOG(tfd, only_in_tombstone, "\nstack:\n"); /* If the crash is due to PC == 0, there will be two frames that /* If the crash is due to PC == 0, there will be two frames that * have identical SP value. * have identical SP value. Loading Loading @@ -330,7 +356,7 @@ static void parse_exidx_info(mapinfo *milist, pid_t pid) ptr = (Elf32_Phdr *) (mi->start + ehdr.e_phoff); ptr = (Elf32_Phdr *) (mi->start + ehdr.e_phoff); for (i = 0; i < ehdr.e_phnum; i++) { for (i = 0; i < ehdr.e_phnum; i++) { /* Parse the program header */ /* Parse the program header */ get_remote_struct(pid, (void *) ptr+i, &phdr, get_remote_struct(pid, (char *) ptr+i, &phdr, sizeof(Elf32_Phdr)); sizeof(Elf32_Phdr)); /* Found a EXIDX segment? */ /* Found a EXIDX segment? */ if (phdr.p_type == PT_ARM_EXIDX) { if (phdr.p_type == PT_ARM_EXIDX) { Loading Loading @@ -401,40 +427,6 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) } } } } /* FIXME: unused: use it or lose it*/ #if 0 static void start_gdbserver_vs(int pid, int port) { pid_t p; char *args[5]; char commspec[16]; char pidspec[16]; p = fork(); if(p < 0) { LOG("could not fork()\n"); return; } if(p == 0) { sprintf(commspec, ":%d", port); sprintf(pidspec, "%d", pid); args[0] = "/system/bin/gdbserver"; args[1] = commspec; args[2] = "--attach"; args[3] = pidspec; args[4] = 0; exit(execv(args[0], args)); } else { LOG("gdbserver pid=%d port=%d targetpid=%d\n", p, port, pid); sleep(5); } } #endif #define MAX_TOMBSTONES 10 #define MAX_TOMBSTONES 10 #define typecheck(x,y) { \ #define typecheck(x,y) { \ Loading Loading @@ -807,13 +799,11 @@ done: if(fd != -1) close(fd); if(fd != -1) close(fd); } } int main(int argc, char **argv) int main() { { int s; int s; struct sigaction act; struct sigaction act; process_name_ptr = argv; logsocket = socket_local_client("logd", logsocket = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM); ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM); if(logsocket < 0) { if(logsocket < 0) { Loading
fastboot/fastboot.c +4 −2 Original line number Original line Diff line number Diff line Loading @@ -147,10 +147,12 @@ oops: int match_fastboot(usb_ifc_info *info) int match_fastboot(usb_ifc_info *info) { { if(!(vendor_id && (info->dev_vendor == vendor_id)) && if(!(vendor_id && (info->dev_vendor == vendor_id)) && (info->dev_vendor != 0x18d1) && (info->dev_vendor != 0x18d1) && // Google (info->dev_vendor != 0x0451) && (info->dev_vendor != 0x0451) && (info->dev_vendor != 0x22b8) && // Motorola (info->dev_vendor != 0x0502) && (info->dev_vendor != 0x0502) && (info->dev_vendor != 0x0bb4)) return -1; (info->dev_vendor != 0x0bb4)) // HTC return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_class != 0xff) return -1; if(info->ifc_subclass != 0x42) return -1; if(info->ifc_subclass != 0x42) return -1; if(info->ifc_protocol != 0x03) return -1; if(info->ifc_protocol != 0x03) return -1; Loading