#include #include #include #include "networkprotocols.h" #include "usbdevice.h" //#include NOTE: problem with isxdigit macro vs isxdigit method in stl #include #include "stringutils.h" #include "vectorutils.h" #ifdef _WTHREAD #include "usbthreads.h" #endif /* usb_device DCB 0x12, 0x01(DEVICE), 0x0200, class<0, 0, 0>, maxpkt=0x40, vidpid<0x0BB4, 0x00CE>, devnr<0x0000>, mfr<1>, prod<2>, ser<0>, ncfg<1> usb_config DCB 0x09, 0x02(CONFIG), 0x0020, nif<1>, cfg<1>, name<0>, flags<0xC0>, maxpow<0xFA> usb_interface DCB 0x09, 0x04(INTERF), ifnr<0>, alt<0>, nrep<2>, class<0xFF, 0xFF, 0xFF>, name<0> usb_endpoint_81 DCB 0x07, 0x05(ENDPT ), ep<0x81>, attr<0x02>, maxpkt<0x0040>, nak<0> usb_endpoint_02 DCB 0x07, 0x05(ENDPT ), ep<0x02>, attr<0x02>, maxpkt<0x0040>, nak<0> usbstr_HTC DCB 0x08, 0x03(STRING), L usbstr_Qualcomm DCB 0x3E, 0x03(STRING), L usbstr_DataIf DCB 0x1E, 0x03(STRING), L usb_langid DCB 0x04, 0x03(STRING), 0x0409 */ // g++-mp-4.4 htcusb.cpp -I /opt/local/include/ -Wall -L/usr/local/lib -lreadline -lusb -L/opt/local/lib -lboost_thread-mt -o htcusb void handle_rndis(usbdev& ph) { printf("\nUSB RNDIS\n"); // todo: figure out how to do a URB_FUNCTION_CLASS_INTERFACE transfer ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVV", 2, 0x18, 2, 1, 0, 0x400)); // read dwords{1,0} from EP81 // ph.controlread(0xa1, 1, 0, 0, 0x1000); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x1c, 0x03, 0x0010101, 0x0, 0x14, 0x0)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x04, 0x0010116, 0x4, 0x14, 0x0, 0x0)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x05, 0x0010105, 0x4, 0x14, 0x0, 0x0)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x06, 0x0010113, 0x4, 0x14, 0x0, 1500)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x07, 0x0010115, 0x4, 0x14, 0x0, 0xd)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x08, 0x1010104, 0x4, 0x14, 0x0, 0x0)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVH",0x4, 0x22, 0x09, 0x1010102, 0x6, 0x14, 0x0, "000000002851")); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVH",0x4, 0x22, 0x0a, 0x1010102, 0x6, 0x14, 0x0, "000000000000")); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x0b, 0x0010106, 0x4, 0x14, 0x0, 0x0)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x0c, 0x0010107, 0x4, 0x14, 0x0, 0x01000100)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x0d, 0x0010113, 0x4, 0x14, 0x0, 0x88)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x5, 0x20, 0x0e, 0x001010f, 0x4, 0x14, 0x0, 0x80)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x5, 0x20, 0x0f, 0x001010e, 0x4, 0x14, 0x0, 0xb)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x10, 0x0010114, 0x4, 0x14, 0x0, 0x0f780002)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x11, 0x0010114, 0x4, 0x14, 0x0, 0x1)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x12, 0x0010107, 0x4, 0x14, 0x0, 1000000000)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x13, 0x0010107, 0x4, 0x14, 0x0, 1000000000)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x14, 0x0010107, 0x4, 0x14, 0x0, 10000000)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x15, 0x0010107, 0x4, 0x14, 0x0, 1000000000)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x16, 0x0010107, 0x4, 0x14, 0x0, 1000000000)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVH",0x4, 0x4c, 0x17, 0x0010107, 0x30, 0x14, 0x0, "0000000000000000000000000000000001380482000000007038cb827038cb820600470054435063784f5680784f5680")); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x18, 0x0010107, 0x4, 0x14, 0x0, 1000000000)); ph.controlwrite(0x21, 0, 0, 0, bufpack("VVVVVVVV",0x4, 0x20, 0x19, 0x0010107, 0x4, 0x14, 0x0, 1000000000)); // 0x80000004, len, seqnr, 0, propid, len, propval // // propid 0x02 : int16 // propid 0x04 : int32 mtu, other values // propid 0x06 : ethernet addr // propid 0x0A : "Microsoft." // propid 0x78 : list of 4 byte records // todo #ifdef _WTHREAD rndisreader rd(ph, network::make()); #endif #ifndef _WTHREAD // todo: get '0x200' from max_packet_size ByteVector buf(0x200); size_t n; while ((n= ph.bulkread(buf.begin(), buf.end()))!=0) { buf.resize(n); printf("%s\n", ascdump(buf).c_str()); buf.resize(0x200); } #endif } struct usbsercontext : context { typedef boost::shared_ptr ptr; usbsercontext() { } static ptr make() { return ptr(new usbsercontext()); } usbsercontext(context::ptr ctx) : context(ctx) { } static ptr make(context::ptr ctx) { return ptr(new usbsercontext(ctx)); } virtual std::string asstring() const { return stringformat("usbser"); } }; class usbserinput: public protocollayer { usbdev& _ph; public: typedef boost::shared_ptr ptr; static ptr make(usbdev& ph) { return ptr(new usbserinput(ph)); } usbserinput(usbdev& ph) : _ph(ph) { } virtual void send(context::ptr ctx, pktdata& data) { printf("usbser-xmit: %s\n", data.hexdump().c_str()); usbsercontext::ptr usbser= boost::dynamic_pointer_cast(ctx); _ph.bulkwrite(data.begin(), data.end()); } virtual void recv(context::ptr ctx, pktdata& data) { printf("usbser-recv: %s\n", data.hexdump().c_str()); usbsercontext::ptr usbser= usbsercontext::make(ctx); protocollayer::ptr up= find(usbser->id()); if (up) up->recv(usbser, data); else { printf("dropping unsupported usbser \n"); } } }; protocollayer::ptr serialprotocolstack(usbdev& ph) { usbserinput::ptr usbser=usbserinput::make(ph); pppflagescape::ptr p0=pppflagescape::make(); usbser->addprotocol(p0); ppphdlcframing::ptr hdlc=ppphdlcframing::make(); p0->addprotocol(hdlc); pppprotocol::ptr ppp= pppprotocol::make(); hdlc->addprotocol(ppp); ppp_lcp::ptr lcp= ppp_lcp::make(); ppp->addprotocol(lcp, pppcontext::make(0xc021)); ppp_pap::ptr pap= ppp_pap::make(); ppp->addprotocol(pap, pppcontext::make(0xc023)); ppp_ipcp::ptr ipcp= ppp_ipcp::make(); ppp->addprotocol(ipcp, pppcontext::make(0x8021)); ppp_ip6cp::ptr ip6cp= ppp_ip6cp::make(); ppp->addprotocol(ip6cp, pppcontext::make(0x8057)); // todo: ipv6: ppp proto 0x57 ipprotocol::ptr ip= ipprotocol::make(); ppp->addprotocol(ip, pppcontext::make(0x21)); icmpprotocol::ptr icmp= icmpprotocol::make(); ip->addprotocol(icmp, ipcontext::make(1)); tcpprotocol::ptr tcp= tcpprotocol::make(); ip->addprotocol(tcp, ipcontext::make(6)); udpprotocol::ptr udp= udpprotocol::make(); ip->addprotocol(udp, ipcontext::make(17)); return usbser; } void handle_client_server_handshake(usbdev& ph) { while (true) { sleep(1); #ifndef _WTHREAD // todo: get '0x200' from max_packet_size ByteVector buf(0x200); size_t n; while ((n= ph.bulkread(buf.begin(), buf.end()))!=0) { buf.resize(n); printf("%s\n", ascdump(buf).c_str()); if (n==6 && memcmp(&buf.front(), "CLIENT", 6)==0) { printf("client detected\n"); const uint8_t *cs= (const uint8_t *)"CLIENTSERVER"; ph.bulkwrite(cs, cs+12); ph.bulkwrite(cs, cs+12); } else { printf("non CLIENT received - dropping first ppp frame\n"); return; } buf.resize(0x200); } #endif // uint8_t *cmd= (uint8_t*)readline(0); // if (cmd) { // size_t l= strlen((char*)cmd); // cmd=(uint8_t*)realloc(cmd, l+2); // cmd[l]= '\r'; // cmd[l+1]= 0; // ph.bulkwrite(cmd, cmd+l+1); // free(cmd); // } } } void handle_usbserial(usbdev& ph) { printf("\nUSB Serial\n"); ph.controlread(0x21, 0x22, 0x0, 0); ph.controlread(0x21, 0x22, 0x1, 0); protocollayer::ptr prot= serialprotocolstack(ph); handle_client_server_handshake(ph); while (1) { ByteVector buf(0x2000); size_t n; while ((n= ph.bulkread(buf.begin(), buf.end()))!=0) { pktdata pkt(&buf.front(), n); prot->recv(context::ptr(), pkt); } } } int main(int,char**) { try { usbdev ph; ph.support(vidpid(0xbb4,0xb51)); // startrek ph.support(vidpid(0xbb4,0xb22)); // viva advanced ph.support(vidpid(0xbb4,0xa22)); // viva no advanced ph.support(vidpid(0xbb4,0xbce)); // herald advanced ph.support(vidpid(0xbb4,0xa51)); // herald/startrek (no advanced) ph.support(vidpid(0xbb4,0xb30)); // diamond2 advanced ph.support(vidpid(0xbb4,0xa30)); // diamond2 no advanced ph.support(vidpid(0xbb4,0xb13)); // diamond rndis ph.support(vidpid(0xbb4,0xa13)); // diamond serial ph.support(vidpid(0xbb4,0xb0b)); // kaiser ph.support(vidpid(0x1a26,0x9d84)); // thurays sg2520 ph.support(vidpid(0xbb4,0xa51)); ph.support(vidpid(0xbb4,0xa07)); ph.support(vidpid(0x45e,0x0ce)); // >perl /Users/itsme/cvsprj/secphone/trunk/scripts/parseutlog.pl -v /Users/itsme/phones/imate-810f/updater/UTLog2.utl // >perl /Users/itsme/cvsprj/secphone/trunk/scripts/parseutlog.pl -v /Users/itsme/phones/imate-810f/updater/utlog1.utl // >perl /Users/itsme/cvsprj/secphone/trunk/scripts/parseutlog.pl -v /Users/itsme/phones/imate-810f/updater/imate.utl ph.support(vidpid(0xbb4,0x0ce)); // note: imate also has 1286:f003 while (!ph.connect()) usleep(100); printf("connected\n"); ph.dumpdesc(); if (ph.isserial()) { handle_usbserial(ph); } else { handle_rndis(ph); } } catch(...) { printf("EXCEPTION\n"); } } // rndis: // perl /Users/itsme/cvsprj/secphone/trunk/scripts/parseutlog.pl -v ~/cvsprj/xda-devtools/itsutils/comm/UTLog-diamondwj.utl // // struct { // uint32_t alwaysone; // uint32_t totallen // uint32_t hdrlen; // uint32_t payloadlen; // uint32_t nuls[7]; // uint8_t etherpkt[0]; // } // // ep82: smb 'TOUCH_DIAMOND' on udp-137 // ep03: dhcp req from macbook // ep82: arp // // old serial usb: // perl /Users/itsme/cvsprj/secphone/trunk/scripts/parseutlog.pl -v ~/cvsprj/xda-devtools/itsutils/comm/UTLog-diamondoleg.utl // // ep81: 'CLIENT' // ep02: 'CLIENTSERVER' // ep02: 'CLIENTSERVER' // ep81: ppp setup packet //