PageRenderTime 56ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/release/src/router/apcupsd/examples/snoopdecode.c

https://gitlab.com/envieidoc/tomato
C | 519 lines | 373 code | 73 blank | 73 comment | 91 complexity | d3fb928ede5634598e6eecd4cc4774c1 MD5 | raw file
  1. /*
  2. * snoopdecode.c
  3. *
  4. * Decodes traces captured by 'usbsnoop'
  5. * (http://benoit.papillault.free.fr/usbsnoop/index.php)
  6. *
  7. * See usbsnoop.txt for details.
  8. */
  9. /*
  10. * Copyright (C) 2004-2005 Adam Kropelin
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of version 2 of the GNU General
  14. * Public License as published by the Free Software Foundation.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public
  22. * License along with this program; if not, write to the Free
  23. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  24. * MA 02111-1307, USA.
  25. */
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #define MAX_LINE 1024
  30. char line[MAX_LINE] = "";
  31. FILE* file;
  32. enum
  33. {
  34. DIR_UNKNOWN = 0,
  35. DIR_TO_DEVICE,
  36. DIR_FROM_DEVICE
  37. };
  38. enum
  39. {
  40. FUNC_UNKNOWN = 0,
  41. FUNC_CONTROL_TXFER,
  42. FUNC_CLASS_INTERFACE,
  43. FUNC_GET_DESC,
  44. FUNC_SELECT_CONFIG,
  45. FUNC_GET_DESC_FROM_IFACE,
  46. FUNC_BULK_TXFER,
  47. FUNC_RESET_PIPE,
  48. FUNC_ABORT_PIPE,
  49. };
  50. enum
  51. {
  52. REQ_GET_REPORT = 1,
  53. REQ_GET_IDLE = 2,
  54. REQ_GET_PROTOCOL = 3,
  55. REQ_SET_REPORT = 9,
  56. REQ_SET_IDLE = 10,
  57. REQ_SET_PROTOCOL = 11
  58. };
  59. struct urb
  60. {
  61. int seq;
  62. unsigned long len;
  63. unsigned char* data;
  64. unsigned long flags;
  65. unsigned long index;
  66. unsigned long type;
  67. unsigned long reserved;
  68. unsigned long request;
  69. unsigned long value;
  70. int time;
  71. int dir;
  72. int func;
  73. };
  74. struct rpt
  75. {
  76. struct rpt* next;
  77. unsigned char* data;
  78. int seq;
  79. unsigned short len;
  80. unsigned char id;
  81. unsigned long value;
  82. };
  83. struct rpt* rpts = NULL;
  84. /*
  85. [197 ms] >>> URB 1 going down >>>
  86. -- URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
  87. TransferBufferLength = 00000012
  88. TransferBuffer = 864c9208
  89. TransferBufferMDL = 00000000
  90. Index = 00000000
  91. DescriptorType = 00000001 (USB_DEVICE_DESCRIPTOR_TYPE)
  92. LanguageId = 00000000
  93. [203 ms] UsbSnoop - MyInternalIOCTLCompletion(f7b91db0) : fido=00000000, Irp=863df850, Context=86405d10, IRQL=2
  94. [203 ms] <<< URB 1 coming back <<<
  95. -- URB_FUNCTION_CONTROL_TRANSFER:
  96. PipeHandle = 863e4150
  97. TransferFlags = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK)
  98. TransferBufferLength = 00000012
  99. TransferBuffer = 864c9208
  100. TransferBufferMDL = 8640f108
  101. 00000000: 12 01 10 01 00 00 00 08 1d 05 02 00 06 00 03 01
  102. 00000010: 02 01
  103. UrbLink = 00000000
  104. */
  105. /*
  106. [59563 ms] >>> URB 346 going down >>>
  107. -- URB_FUNCTION_CLASS_INTERFACE:
  108. TransferFlags = 00000001 (USBD_TRANSFER_DIRECTION_IN, ~USBD_SHORT_TRANSFER_OK)
  109. TransferBufferLength = 00000005
  110. TransferBuffer = f7f12ba0
  111. TransferBufferMDL = 00000000
  112. UrbLink = 00000000
  113. RequestTypeReservedBits = 00000022
  114. Request = 00000001
  115. Value = 0000032f
  116. Index = 00000000
  117. [59567 ms] UsbSnoop - MyInternalIOCTLCompletion(f7b91db0) : fido=86397288, Irp=85ff4b40, Context=85f4b3d8, IRQL=2
  118. [59567 ms] <<< URB 346 coming back <<<
  119. -- URB_FUNCTION_CONTROL_TRANSFER:
  120. PipeHandle = 863e4150
  121. TransferFlags = 0000000b (USBD_TRANSFER_DIRECTION_IN, USBD_SHORT_TRANSFER_OK)
  122. TransferBufferLength = 00000002
  123. TransferBuffer = f7f12ba0
  124. TransferBufferMDL = 85f102f0
  125. 00000000: 2f 02
  126. UrbLink = 00000000
  127. SetupPacket =
  128. 00000000: a1 01 2f 03 00 00 05 00
  129. */
  130. int fetch_line()
  131. {
  132. return !!fgets(line, sizeof(line), file);
  133. }
  134. int find_urb()
  135. {
  136. do
  137. {
  138. if (line[0] == '[' && strstr(line, " URB ") &&
  139. (strstr(line, "going down") || strstr(line, "coming back")))
  140. {
  141. return 1;
  142. }
  143. }
  144. while( fetch_line() );
  145. return 0;
  146. }
  147. int init_urb(struct urb* urb)
  148. {
  149. memset(urb, 0, sizeof(*urb));
  150. if (!find_urb())
  151. return 0;
  152. urb->time = atoi(line+1);
  153. if (strstr(line, "going down"))
  154. urb->dir = DIR_TO_DEVICE;
  155. else if(strstr(line, "coming back"))
  156. urb->dir = DIR_FROM_DEVICE;
  157. else
  158. urb->dir = DIR_UNKNOWN;
  159. urb->seq = atoi(strstr(line,"URB ")+4);
  160. return 1;
  161. }
  162. unsigned long get_hex_value()
  163. {
  164. char* ptr = strchr(line, '=');
  165. if (!ptr)
  166. return 0xffff;
  167. return strtoul(ptr+2, NULL, 16);
  168. }
  169. unsigned char* parse_data_dump(int len)
  170. {
  171. int count = 0;
  172. char* ptr= NULL;
  173. unsigned char* data = (unsigned char *)malloc(len);
  174. if (!data)
  175. return NULL;
  176. while(count < len)
  177. {
  178. if ((count % 16) == 0)
  179. {
  180. if (count)
  181. {
  182. if (!fetch_line())
  183. {
  184. free(data);
  185. return NULL;
  186. }
  187. }
  188. ptr = strchr(line, ':');
  189. if (!ptr)
  190. {
  191. free(data);
  192. return NULL;
  193. }
  194. ptr += 2;
  195. }
  196. data[count++] = strtoul(ptr, NULL, 16);
  197. ptr += 3;
  198. }
  199. return data;
  200. }
  201. void parse_urb_body(struct urb* urb)
  202. {
  203. int setup_packet = 0;
  204. while (fetch_line())
  205. {
  206. if (line[0] == '[')
  207. break;
  208. if (strstr(line, "TransferBufferLength"))
  209. {
  210. urb->len = get_hex_value();
  211. }
  212. else if (strstr(line, "TransferFlags"))
  213. {
  214. urb->flags = get_hex_value();
  215. }
  216. else if (strstr(line, "Index"))
  217. {
  218. urb->index = get_hex_value();
  219. }
  220. else if (strstr(line, "DescriptorType"))
  221. {
  222. urb->type = get_hex_value();
  223. }
  224. else if (strstr(line, "RequestTypeReservedBits"))
  225. {
  226. urb->reserved = get_hex_value();
  227. }
  228. else if (strstr(line, "Request"))
  229. {
  230. urb->request = get_hex_value();
  231. }
  232. else if (strstr(line, "Value"))
  233. {
  234. urb->value = get_hex_value();
  235. }
  236. else if (strstr(line, "SetupPacket"))
  237. {
  238. setup_packet = 1;
  239. }
  240. else if (strstr(line, "00000000:"))
  241. {
  242. if (!setup_packet && !urb->data)
  243. urb->data = parse_data_dump(urb->len);
  244. }
  245. else if (strstr(line, "-- URB_FUNCTION_"))
  246. {
  247. if (strstr(line, "URB_FUNCTION_CONTROL_TRANSFER"))
  248. urb->func = FUNC_CONTROL_TXFER;
  249. else if (strstr(line, "URB_FUNCTION_CLASS_INTERFACE"))
  250. urb->func = FUNC_CLASS_INTERFACE;
  251. else if (strstr(line, "URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE"))
  252. urb->func = FUNC_GET_DESC;
  253. else if (strstr(line, "URB_FUNCTION_SELECT_CONFIGURATION"))
  254. urb->func = FUNC_SELECT_CONFIG;
  255. else if (strstr(line, "URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE"))
  256. urb->func = FUNC_GET_DESC_FROM_IFACE;
  257. else if (strstr(line, "URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER"))
  258. urb->func = FUNC_BULK_TXFER;
  259. else if (strstr(line, "URB_FUNCTION_RESET_PIPE"))
  260. urb->func = FUNC_RESET_PIPE;
  261. else if (strstr(line, "URB_FUNCTION_ABORT_PIPE"))
  262. urb->func = FUNC_ABORT_PIPE;
  263. else
  264. {
  265. urb->func = FUNC_UNKNOWN;
  266. printf("Unknown FUNC: %s\n", line);
  267. exit(0);
  268. }
  269. }
  270. }
  271. }
  272. void free_urb(struct urb* urb)
  273. {
  274. free(urb->data);
  275. }
  276. void print_urb(struct urb* urb)
  277. {
  278. unsigned int x;
  279. printf("[%08d ms] %05d %c ", urb->time, urb->seq,
  280. (urb->dir == DIR_TO_DEVICE) ? '>' : (urb->dir == DIR_FROM_DEVICE) ? '<' : '?');
  281. printf("req=%04lx value=%04lx", urb->request, urb->value);
  282. if( urb->data )
  283. {
  284. printf(" [");
  285. for(x=0; x<urb->len; x++)
  286. {
  287. printf( "%02x", urb->data[x] );
  288. if (x < urb->len-1)
  289. printf(" ");
  290. }
  291. printf("]");
  292. }
  293. printf("\n");
  294. }
  295. struct rpt* find_report_by_seq(int seq)
  296. {
  297. struct rpt* rpt = rpts;
  298. while( rpt )
  299. {
  300. if (rpt->seq == seq)
  301. break;
  302. rpt = rpt->next;
  303. }
  304. return rpt;
  305. }
  306. struct rpt* find_report_by_id(unsigned char id)
  307. {
  308. struct rpt* rpt = rpts;
  309. while( rpt )
  310. {
  311. if (rpt->id == id)
  312. break;
  313. rpt = rpt->next;
  314. }
  315. return rpt;
  316. }
  317. void del_report(struct urb* urb)
  318. {
  319. unsigned char id = urb->data[0];
  320. struct rpt* rpt = rpts;
  321. struct rpt** prev = &rpts;
  322. while( rpt )
  323. {
  324. if (rpt->id == id)
  325. break;
  326. prev = &(rpt->next);
  327. rpt = rpt->next;
  328. }
  329. if (rpt)
  330. {
  331. *prev = rpt->next;
  332. free(rpt);
  333. }
  334. }
  335. void add_report(struct urb* urb)
  336. {
  337. struct rpt* rpt;
  338. unsigned char id;
  339. if (urb->data)
  340. id = urb->data[0];
  341. else
  342. id = urb->value & 0xff;
  343. if ((rpt = find_report_by_id(id)))
  344. {
  345. rpt->seq = urb->seq;
  346. rpt->value = urb->value;
  347. return;
  348. }
  349. rpt = (struct rpt*)malloc(sizeof(*rpt));
  350. memset(rpt, 0, sizeof(*rpt));
  351. rpt->id = id;
  352. rpt->seq = urb->seq;
  353. rpt->value = urb->value;
  354. rpt->next = rpts;
  355. rpts = rpt;
  356. }
  357. int check_and_update_report(struct urb* urb)
  358. {
  359. struct rpt* rpt;
  360. rpt = find_report_by_seq(urb->seq);
  361. if (!rpt)
  362. return 0;
  363. if (rpt->data && !memcmp(rpt->data, urb->data+1, urb->len-1))
  364. return 0;
  365. free(rpt->data);
  366. rpt->len = urb->len-1;
  367. rpt->data = (unsigned char *)malloc(rpt->len);
  368. memcpy(rpt->data, urb->data+1, rpt->len);
  369. return 1;
  370. }
  371. void display_report(struct urb* urb)
  372. {
  373. unsigned long data = 0;
  374. char buf[9];
  375. unsigned int n;
  376. n = printf( "[%04d s] %05d %c %s 0x%02x (%03u) ",
  377. urb->time/1000, urb->seq, urb->func == FUNC_BULK_TXFER ? '*' : ' ',
  378. urb->dir==DIR_TO_DEVICE ? "WRITE" : " READ", urb->data[0], urb->data[0]);
  379. switch (urb->len)
  380. {
  381. case 5:
  382. data = (data << 8) | urb->data[4];
  383. case 4:
  384. data = (data << 8) | urb->data[3];
  385. case 3:
  386. data = (data << 8) | urb->data[2];
  387. case 2:
  388. data = (data << 8) | urb->data[1];
  389. sprintf(buf, "%0*lx", (int)(urb->len-1)*2, data);
  390. n += printf( "%8s (%lu)", buf, data );
  391. break;
  392. default:
  393. n += printf( "-------- (----------)" );
  394. break;
  395. }
  396. printf( "%*c", 55-n, ' ');
  397. for (n=0; n<urb->len-1; n++)
  398. printf("%02x ", urb->data[n+1]);
  399. printf("\n");
  400. fflush(stdout);
  401. }
  402. void update_reports(struct urb* urb)
  403. {
  404. if (urb->dir == DIR_TO_DEVICE)
  405. {
  406. // Only care about class requests
  407. if (urb->func != FUNC_CLASS_INTERFACE)
  408. return;
  409. if (urb->request == REQ_GET_REPORT)
  410. {
  411. add_report(urb);
  412. }
  413. else if (urb->request == REQ_SET_REPORT)
  414. {
  415. display_report(urb);
  416. del_report(urb);
  417. }
  418. }
  419. else
  420. {
  421. if (urb->func == FUNC_CONTROL_TXFER)
  422. {
  423. if (check_and_update_report(urb))
  424. display_report(urb);
  425. }
  426. else if (urb->data && urb->func == FUNC_BULK_TXFER)
  427. {
  428. add_report(urb);
  429. if (check_and_update_report(urb))
  430. display_report(urb);
  431. }
  432. }
  433. }
  434. int main(int argc, char* argv[])
  435. {
  436. struct urb urb;
  437. file = stdin;
  438. while(init_urb(&urb))
  439. {
  440. parse_urb_body(&urb);
  441. update_reports(&urb);
  442. free_urb(&urb);
  443. }
  444. return 0;
  445. }