Skip to content

Instantly share code, notes, and snippets.

@tewilove
Created August 22, 2015 04:19
Show Gist options
  • Save tewilove/75f63e1ecf708d07bea6 to your computer and use it in GitHub Desktop.
Save tewilove/75f63e1ecf708d07bea6 to your computer and use it in GitHub Desktop.
/*
*
* SHARP shdiag mode
* tewilove@gmail.com, All rights reserved
*
*/
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef __MINGW32__
#include <winsock2.h>
#else
#include <arpa/inet.h>
#endif
#include <errno.h>
#ifdef __APPLE__
#include <sys/malloc.h>
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <libusb-1.0/libusb.h>
#define USB_VID 0x04dd
#define USB_PID 0x933a
static libusb_context *g_ctx;
static int fldr_init() {
int rc;
rc = libusb_init(&g_ctx);
return rc;
}
static void fldr_free() {
libusb_exit(g_ctx);
}
// see lsusb -v -d 04dd:933a
static libusb_device_handle *fldr_open() {
int rc;
libusb_device_handle *h;
h = libusb_open_device_with_vid_pid(g_ctx, USB_VID, USB_PID);
if (!h)
return NULL;
rc = libusb_claim_interface(h, 1);
if (rc) {
// fprintf(stderr, "%04d:%s: %s(%d)\n", __LINE__, "libusb_claim_interface", libusb_error_name(rc), rc);
goto fail;
}
rc = libusb_set_interface_alt_setting(h, 1, 1);
if (rc) {
// fprintf(stderr, "%04d:%s: %s(%d)\n", __LINE__, "libusb_set_interface_alt_setting", libusb_error_name(rc), rc);
goto fail;
}
return h;
fail:
libusb_close(h);
return NULL;
}
static int fldr_close(libusb_device_handle *h) {
int rc;
rc = libusb_release_interface(h, 1);
libusb_close(h);
return rc;
}
size_t fldr_read(libusb_device_handle *h, char *buff, size_t size) {
int rc;
size_t nbtr = 0;
libusb_device *d;
int ps;
d = libusb_get_device(h);
if (!d)
return (size_t)(-1);
ps = libusb_get_max_packet_size(d, 0x81);
if (ps <= 0)
ps = 512;
while (nbtr < size) {
int nb, ch;
ch = size - nbtr;
if (ch > ps)
ch = ps;
rc = libusb_bulk_transfer(
h,
0x81,
(unsigned char *) buff + nbtr,
ch,
&nb,
1000);
if (rc) {
// fprintf(stderr, "%04d:%s: %s(%d)\n", __LINE__, __func__, libusb_error_name(rc), rc);
break;
}
nbtr += nb;
}
// fprintf(stderr, "%s: %d\n", __func__, (int) nbtr);
return nbtr;
}
size_t fldr_write(libusb_device_handle *h, const char *buff, size_t size) {
int rc;
size_t nbtr = 0;
libusb_device *d;
int ps;
d = libusb_get_device(h);
if (!d)
return (size_t)(-1);
ps = libusb_get_max_packet_size(d, 0x01);
if (ps <= 0)
ps = 512;
while (nbtr < size) {
int nb, ch;
ch = size - nbtr;
if (ch > ps)
ch = ps;
rc = libusb_bulk_transfer(
h,
0x01,
(unsigned char *) buff + nbtr,
ch,
&nb,
1000);
if (rc) {
// fprintf(stderr, "%04d:%s: %s(%d)\n", __LINE__, __func__, libusb_error_name(rc), rc);
break;
}
nbtr += nb;
}
// fprintf(stderr, "%s: %d\n", __func__, (int) nbtr);
return nbtr;
}
static int shdiag_xchar(int c) {
int i;
char xft[8] = { 0, 2, 4, 6, 1, 3, 5, 7 };
int r = 0;
for (i = 0; i < 8; i++) {
r |= (((c >> i) & 1) << xft[i]);
}
return r;
}
static int shdiag_encode_data(const char *in, size_t *is, char *out, size_t os) {
size_t ip = 0, op = 1;
int x, v;
if (os < *is / 2)
return -1;
srand(time(NULL));
v = (rand() & 0x7f) + 0xf;
x = shdiag_xchar(v);
out[0] = v;
while (ip < *is) {
if (in[ip] == '\r' || in[ip] == '\n') {
out[op++] = in[ip];
if (in[ip] == '\n' && ip + 1 < *is) {
x = shdiag_xchar(v);
out[op] = v;
op += 1;
}
} else {
out[op++] = (in[ip] ^ (x & 0x7f)) + 0xf;
x = (x >> 1) | ((x & 1) << 7);
}
ip += 1;
}
*is = op;
return 0;
}
static int shdiag_decode_data(const char *in, size_t *is, char *out, size_t os) {
size_t ip = 1, op = 0;
int x;
if (os < *is - 1)
return -1;
x = in[0];
x = shdiag_xchar(x);
while (ip < *is) {
if (in[ip] == '\r' || in[ip] == '\n') {
out[op++] = in[ip];
if (in[ip] == '\n' && ip + 1 < *is) {
x = in[ip + 1];
x = shdiag_xchar(x);
ip += 1;
}
} else {
out[op++] = (in[ip] - 0xf) ^ (x & 0x7f);
x = (x >> 1) | ((x & 1) << 7);
}
ip += 1;
}
*is = op;
return 0;
}
int main(int argc, char *argv[]) {
int rc, ret = -1;
struct libusb_device_handle *h;
char req[1024], res[1024];
char req_enc[1024], res_dec[1024];
size_t size;
size_t nbtr;
if (argc != 2)
return 1;
rc = fldr_init();
if (rc)
goto fail_fldr_init;
while (1) {
h = fldr_open();
if (h)
break;
}
nbtr = fldr_read(h, res, sizeof(res));
if (nbtr) {
memset(res_dec, 0, sizeof(res_dec));
size = nbtr;
rc = shdiag_decode_data(res, &size, res_dec, sizeof(res_dec));
if (rc)
goto fail_shdiag_decode_data;
res_dec[size] = 0;
// OK\r\nREADY\r\n
printf("%s", res_dec);
}
snprintf(req, sizeof(req), "%s\r\n", argv[1]);
size = strlen(argv[1]) + 2;
rc = shdiag_encode_data(req, &size, req_enc, sizeof(req_enc));
if (rc)
goto fail_shdiag_encode_data;
if (size && fldr_write(h, req_enc, size) == size) {
memset(res, 0, sizeof(res));
nbtr = fldr_read(h, res, sizeof(res));
if (nbtr) {
size = nbtr;
rc = shdiag_decode_data(res, &size, res_dec, sizeof(res_dec));
if (rc)
goto fail_shdiag_decode_data;
res_dec[size] = 0;
printf("%s", res_dec);
}
}
fail_shdiag_decode_data:
fail_shdiag_encode_data:
fldr_close(h);
//fail_fldr_open:
fldr_free();
fail_fldr_init:
return ret;
}
@tewilove
Copy link
Author

Heard someone using this SIM unlock 404SH and so on, damn it.

@tewilove
Copy link
Author

There is a GPIO called "test gpio" which could be found in SHARP kernel source. It is also confirmed that SBL1 also checks this GPIO. When it's pulled up, device will boot into SHDIAG mode.

@ttlover201212
Copy link

It seems that I should disassemble the phone and look for the "test gpio",any other better solution ?

@ttlover201212
Copy link

When testing on sharp 403SH,
h = libusb_open_device_with_vid_pid(g_ctx, USB_VID, USB_PID);
Always return 0.
I have compiled different version of libusb,no help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment