Norimasa Okamoto
/
LPC1114_USBProtocolAnalyzer
USB protocol analyzer
control:
interrupt in:
BaseUsbProtocolAnalyzer.cpp@0:0faa55631ffe, 2014-06-18 (annotated)
- Committer:
- va009039
- Date:
- Wed Jun 18 01:33:32 2014 +0000
- Revision:
- 0:0faa55631ffe
first commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 0:0faa55631ffe | 1 | #include "mbed.h" |
va009039 | 0:0faa55631ffe | 2 | #include "BaseUsbProtocolAnalyzer.h" |
va009039 | 0:0faa55631ffe | 3 | |
va009039 | 0:0faa55631ffe | 4 | |
va009039 | 0:0faa55631ffe | 5 | uint8_t crc5usb(uint16_t data) |
va009039 | 0:0faa55631ffe | 6 | { |
va009039 | 0:0faa55631ffe | 7 | uint16_t r = (data&0x7ff) ^ 0x1f; |
va009039 | 0:0faa55631ffe | 8 | for(int j = 0; j < 11; j++) { // 11bit |
va009039 | 0:0faa55631ffe | 9 | if (r & 1) { |
va009039 | 0:0faa55631ffe | 10 | r = (r>>1) ^ 0x14; |
va009039 | 0:0faa55631ffe | 11 | } else { |
va009039 | 0:0faa55631ffe | 12 | r = r>>1; |
va009039 | 0:0faa55631ffe | 13 | } |
va009039 | 0:0faa55631ffe | 14 | } |
va009039 | 0:0faa55631ffe | 15 | return r ^ 0x1f; |
va009039 | 0:0faa55631ffe | 16 | } |
va009039 | 0:0faa55631ffe | 17 | |
va009039 | 0:0faa55631ffe | 18 | uint16_t crc16usb(const uint8_t data[], int size) |
va009039 | 0:0faa55631ffe | 19 | { |
va009039 | 0:0faa55631ffe | 20 | uint16_t r = 0xffff; |
va009039 | 0:0faa55631ffe | 21 | for(int i = 0; i < size; i++) { |
va009039 | 0:0faa55631ffe | 22 | r ^= data[i]; |
va009039 | 0:0faa55631ffe | 23 | for(int j = 0; j < 8; j++) { |
va009039 | 0:0faa55631ffe | 24 | if (r & 1) { |
va009039 | 0:0faa55631ffe | 25 | r = (r>>1) ^ 0xa001; |
va009039 | 0:0faa55631ffe | 26 | } else { |
va009039 | 0:0faa55631ffe | 27 | r = (r>>1); |
va009039 | 0:0faa55631ffe | 28 | } |
va009039 | 0:0faa55631ffe | 29 | } |
va009039 | 0:0faa55631ffe | 30 | } |
va009039 | 0:0faa55631ffe | 31 | return r ^ 0xffff; |
va009039 | 0:0faa55631ffe | 32 | } |
va009039 | 0:0faa55631ffe | 33 | |
va009039 | 0:0faa55631ffe | 34 | |
va009039 | 0:0faa55631ffe | 35 | BaseUsbProtocolAnalyzer::BaseUsbProtocolAnalyzer() |
va009039 | 0:0faa55631ffe | 36 | { |
va009039 | 0:0faa55631ffe | 37 | init(); |
va009039 | 0:0faa55631ffe | 38 | } |
va009039 | 0:0faa55631ffe | 39 | |
va009039 | 0:0faa55631ffe | 40 | void BaseUsbProtocolAnalyzer::input(uint8_t data) |
va009039 | 0:0faa55631ffe | 41 | { |
va009039 | 0:0faa55631ffe | 42 | char str[32]; |
va009039 | 0:0faa55631ffe | 43 | if (data == 0) { // EOP ? |
va009039 | 0:0faa55631ffe | 44 | if (seq == SEQ_DATA) { |
va009039 | 0:0faa55631ffe | 45 | output("["); |
va009039 | 0:0faa55631ffe | 46 | for(int i = 0; i < data_count-2; i++) { |
va009039 | 0:0faa55631ffe | 47 | snprintf(str, sizeof(str), "%s0x%02x", i == 0 ? "" : " ", packet.data[i]); |
va009039 | 0:0faa55631ffe | 48 | output(str); |
va009039 | 0:0faa55631ffe | 49 | } |
va009039 | 0:0faa55631ffe | 50 | output("]"); |
va009039 | 0:0faa55631ffe | 51 | if (data_count >= 2) { |
va009039 | 0:0faa55631ffe | 52 | uint16_t crc16 = packet.data[data_count-2]|(packet.data[data_count-1]<<8); |
va009039 | 0:0faa55631ffe | 53 | bool crc16_err = (crc16usb(packet.data, data_count-2) == crc16); |
va009039 | 0:0faa55631ffe | 54 | snprintf(str, sizeof(str), "[crc16=0x%04x%s]", crc16, crc16_err ? "" : " ERROR"); |
va009039 | 0:0faa55631ffe | 55 | output(str); |
va009039 | 0:0faa55631ffe | 56 | } |
va009039 | 0:0faa55631ffe | 57 | } |
va009039 | 0:0faa55631ffe | 58 | output("[EOP]"); |
va009039 | 0:0faa55631ffe | 59 | init(); |
va009039 | 0:0faa55631ffe | 60 | return; |
va009039 | 0:0faa55631ffe | 61 | } |
va009039 | 0:0faa55631ffe | 62 | |
va009039 | 0:0faa55631ffe | 63 | if (seq == SEQ_SYNC) { |
va009039 | 0:0faa55631ffe | 64 | if (disp_cycle) { |
va009039 | 0:0faa55631ffe | 65 | snprintf(str, sizeof(str), "(0x%02x)", data); |
va009039 | 0:0faa55631ffe | 66 | output(str); |
va009039 | 0:0faa55631ffe | 67 | } |
va009039 | 0:0faa55631ffe | 68 | output("[SYNC]"); |
va009039 | 0:0faa55631ffe | 69 | packet.pid = (pid_t)data; |
va009039 | 0:0faa55631ffe | 70 | switch(packet.pid) { |
va009039 | 0:0faa55631ffe | 71 | case ACK: |
va009039 | 0:0faa55631ffe | 72 | output("[ACK]"); |
va009039 | 0:0faa55631ffe | 73 | break; |
va009039 | 0:0faa55631ffe | 74 | case NAK: |
va009039 | 0:0faa55631ffe | 75 | output("[NAK]"); |
va009039 | 0:0faa55631ffe | 76 | break; |
va009039 | 0:0faa55631ffe | 77 | case STALL: |
va009039 | 0:0faa55631ffe | 78 | output("[STALL]"); |
va009039 | 0:0faa55631ffe | 79 | break; |
va009039 | 0:0faa55631ffe | 80 | case IN: |
va009039 | 0:0faa55631ffe | 81 | output("[IN]"); |
va009039 | 0:0faa55631ffe | 82 | bit_count = 7; |
va009039 | 0:0faa55631ffe | 83 | break; |
va009039 | 0:0faa55631ffe | 84 | case OUT: |
va009039 | 0:0faa55631ffe | 85 | output("[OUT]"); |
va009039 | 0:0faa55631ffe | 86 | bit_count = 4; |
va009039 | 0:0faa55631ffe | 87 | break; |
va009039 | 0:0faa55631ffe | 88 | case SETUP: |
va009039 | 0:0faa55631ffe | 89 | output("[SETUP]"); |
va009039 | 0:0faa55631ffe | 90 | bit_count = 7; |
va009039 | 0:0faa55631ffe | 91 | break; |
va009039 | 0:0faa55631ffe | 92 | case DATA0: |
va009039 | 0:0faa55631ffe | 93 | output("[DATA0]"); |
va009039 | 0:0faa55631ffe | 94 | bit_count = 5; |
va009039 | 0:0faa55631ffe | 95 | break; |
va009039 | 0:0faa55631ffe | 96 | case DATA1: |
va009039 | 0:0faa55631ffe | 97 | output("[DATA1]"); |
va009039 | 0:0faa55631ffe | 98 | bit_count = 7; |
va009039 | 0:0faa55631ffe | 99 | break; |
va009039 | 0:0faa55631ffe | 100 | default: |
va009039 | 0:0faa55631ffe | 101 | snprintf(str, sizeof(str), "[pid=0x%02x]", packet.pid); |
va009039 | 0:0faa55631ffe | 102 | output(str); |
va009039 | 0:0faa55631ffe | 103 | break; |
va009039 | 0:0faa55631ffe | 104 | } |
va009039 | 0:0faa55631ffe | 105 | seq = SEQ_PID; |
va009039 | 0:0faa55631ffe | 106 | return; |
va009039 | 0:0faa55631ffe | 107 | } |
va009039 | 0:0faa55631ffe | 108 | if (disp_cycle) { |
va009039 | 0:0faa55631ffe | 109 | snprintf(str, sizeof(str), "(%d)", data); |
va009039 | 0:0faa55631ffe | 110 | output(str); |
va009039 | 0:0faa55631ffe | 111 | } |
va009039 | 0:0faa55631ffe | 112 | int n = (data + CYCLE/2) / CYCLE - 1; |
va009039 | 0:0faa55631ffe | 113 | uint8_t pat = 0; |
va009039 | 0:0faa55631ffe | 114 | int len = 0; |
va009039 | 0:0faa55631ffe | 115 | if (bit_stuffing) { |
va009039 | 0:0faa55631ffe | 116 | const uint8_t table[] = {0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff}; |
va009039 | 0:0faa55631ffe | 117 | pat = table[n]; |
va009039 | 0:0faa55631ffe | 118 | len = n; |
va009039 | 0:0faa55631ffe | 119 | } else { |
va009039 | 0:0faa55631ffe | 120 | const uint8_t table[] = {0x00,0x02,0x06,0x0e,0x1e,0x3e,0x7e,0xfe}; |
va009039 | 0:0faa55631ffe | 121 | pat = table[n]; |
va009039 | 0:0faa55631ffe | 122 | len = n + 1; |
va009039 | 0:0faa55631ffe | 123 | } |
va009039 | 0:0faa55631ffe | 124 | bit_stuffing = false; |
va009039 | 0:0faa55631ffe | 125 | if (n >= 6) { |
va009039 | 0:0faa55631ffe | 126 | bit_stuffing = true; |
va009039 | 0:0faa55631ffe | 127 | } |
va009039 | 0:0faa55631ffe | 128 | inputBit(pat, len); |
va009039 | 0:0faa55631ffe | 129 | } |
va009039 | 0:0faa55631ffe | 130 | |
va009039 | 0:0faa55631ffe | 131 | void BaseUsbProtocolAnalyzer::inputBit(uint8_t pat, int len) |
va009039 | 0:0faa55631ffe | 132 | { |
va009039 | 0:0faa55631ffe | 133 | if (disp_bit) { |
va009039 | 0:0faa55631ffe | 134 | output('{'); |
va009039 | 0:0faa55631ffe | 135 | for(int i = 0; i < len; i++) { |
va009039 | 0:0faa55631ffe | 136 | output(((pat>>i) & 1) ? '1' : '0'); |
va009039 | 0:0faa55631ffe | 137 | } |
va009039 | 0:0faa55631ffe | 138 | output('}'); |
va009039 | 0:0faa55631ffe | 139 | } |
va009039 | 0:0faa55631ffe | 140 | for(int i = 0; i < len; i++) { |
va009039 | 0:0faa55631ffe | 141 | inputLSB((pat>>i) & 1); |
va009039 | 0:0faa55631ffe | 142 | } |
va009039 | 0:0faa55631ffe | 143 | } |
va009039 | 0:0faa55631ffe | 144 | |
va009039 | 0:0faa55631ffe | 145 | void BaseUsbProtocolAnalyzer::inputLSB(int lsb) |
va009039 | 0:0faa55631ffe | 146 | { |
va009039 | 0:0faa55631ffe | 147 | char str[32]; |
va009039 | 0:0faa55631ffe | 148 | seq_t prev_seq = seq; |
va009039 | 0:0faa55631ffe | 149 | switch(seq) { |
va009039 | 0:0faa55631ffe | 150 | case SEQ_PID: |
va009039 | 0:0faa55631ffe | 151 | if (++bit_count >= 8) { |
va009039 | 0:0faa55631ffe | 152 | if (packet.pid == IN || packet.pid == OUT || packet.pid == SETUP) { |
va009039 | 0:0faa55631ffe | 153 | seq = SEQ_ADDR; |
va009039 | 0:0faa55631ffe | 154 | } else if (packet.pid == DATA0 || packet.pid == DATA1) { |
va009039 | 0:0faa55631ffe | 155 | seq = SEQ_DATA; |
va009039 | 0:0faa55631ffe | 156 | } |
va009039 | 0:0faa55631ffe | 157 | } |
va009039 | 0:0faa55631ffe | 158 | break; |
va009039 | 0:0faa55631ffe | 159 | case SEQ_ADDR: |
va009039 | 0:0faa55631ffe | 160 | packet.addr >>= 1; |
va009039 | 0:0faa55631ffe | 161 | packet.addr |= lsb ? 0x40 : 0x00; |
va009039 | 0:0faa55631ffe | 162 | if (++bit_count >= 7) { |
va009039 | 0:0faa55631ffe | 163 | snprintf(str, sizeof(str), "[ADDR=%d]", packet.addr & 0x7f); |
va009039 | 0:0faa55631ffe | 164 | output(str); |
va009039 | 0:0faa55631ffe | 165 | seq = SEQ_ENDP; |
va009039 | 0:0faa55631ffe | 166 | } |
va009039 | 0:0faa55631ffe | 167 | break; |
va009039 | 0:0faa55631ffe | 168 | case SEQ_ENDP: |
va009039 | 0:0faa55631ffe | 169 | packet.endp >>= 1; |
va009039 | 0:0faa55631ffe | 170 | packet.endp |= lsb ? 0x08 : 0x00; |
va009039 | 0:0faa55631ffe | 171 | if (++bit_count >= 4) { |
va009039 | 0:0faa55631ffe | 172 | snprintf(str, sizeof(str), "[ENDP=%d]", packet.endp & 0x0f); |
va009039 | 0:0faa55631ffe | 173 | output(str); |
va009039 | 0:0faa55631ffe | 174 | seq = SEQ_CRC5; |
va009039 | 0:0faa55631ffe | 175 | } |
va009039 | 0:0faa55631ffe | 176 | break; |
va009039 | 0:0faa55631ffe | 177 | case SEQ_CRC5: |
va009039 | 0:0faa55631ffe | 178 | if (bit_count < 5) { |
va009039 | 0:0faa55631ffe | 179 | packet.crc5 >>= 1; |
va009039 | 0:0faa55631ffe | 180 | packet.crc5 |= lsb ? 0x10 : 0x00; |
va009039 | 0:0faa55631ffe | 181 | if (++bit_count >= 5) { |
va009039 | 0:0faa55631ffe | 182 | uint16_t u = packet.crc5<<11|packet.endp<<7|packet.addr; |
va009039 | 0:0faa55631ffe | 183 | bool crc5_err = (crc5usb(u) == packet.crc5); |
va009039 | 0:0faa55631ffe | 184 | snprintf(str, sizeof(str), "[CRC5=0x%02x%s]", |
va009039 | 0:0faa55631ffe | 185 | packet.crc5, crc5_err ? "" : " ERROR"); |
va009039 | 0:0faa55631ffe | 186 | output(str); |
va009039 | 0:0faa55631ffe | 187 | } |
va009039 | 0:0faa55631ffe | 188 | } |
va009039 | 0:0faa55631ffe | 189 | break; |
va009039 | 0:0faa55631ffe | 190 | case SEQ_DATA: |
va009039 | 0:0faa55631ffe | 191 | if (data_count < sizeof(packet.data)) { |
va009039 | 0:0faa55631ffe | 192 | packet.data[data_count] >>= 1; |
va009039 | 0:0faa55631ffe | 193 | packet.data[data_count] |= lsb ? 0x80 : 0x00; |
va009039 | 0:0faa55631ffe | 194 | if (++bit_count >= 8) { |
va009039 | 0:0faa55631ffe | 195 | bit_count = 0; |
va009039 | 0:0faa55631ffe | 196 | data_count++; |
va009039 | 0:0faa55631ffe | 197 | } |
va009039 | 0:0faa55631ffe | 198 | } |
va009039 | 0:0faa55631ffe | 199 | break; |
va009039 | 0:0faa55631ffe | 200 | } |
va009039 | 0:0faa55631ffe | 201 | if (prev_seq != seq) { |
va009039 | 0:0faa55631ffe | 202 | bit_count = 0; |
va009039 | 0:0faa55631ffe | 203 | data_count = 0; |
va009039 | 0:0faa55631ffe | 204 | } |
va009039 | 0:0faa55631ffe | 205 | } |
va009039 | 0:0faa55631ffe | 206 | |
va009039 | 0:0faa55631ffe | 207 | void BaseUsbProtocolAnalyzer::init() |
va009039 | 0:0faa55631ffe | 208 | { |
va009039 | 0:0faa55631ffe | 209 | seq = SEQ_SYNC; |
va009039 | 0:0faa55631ffe | 210 | bit_stuffing = false; |
va009039 | 0:0faa55631ffe | 211 | bit_count = 0; |
va009039 | 0:0faa55631ffe | 212 | disp_bit = false; |
va009039 | 0:0faa55631ffe | 213 | disp_cycle = false; |
va009039 | 0:0faa55631ffe | 214 | } |
va009039 | 0:0faa55631ffe | 215 | |
va009039 | 0:0faa55631ffe | 216 | void BaseUsbProtocolAnalyzer::output(const char* s) |
va009039 | 0:0faa55631ffe | 217 | { |
va009039 | 0:0faa55631ffe | 218 | while(*s) { |
va009039 | 0:0faa55631ffe | 219 | output(*s++); |
va009039 | 0:0faa55631ffe | 220 | } |
va009039 | 0:0faa55631ffe | 221 | } |
va009039 | 0:0faa55631ffe | 222 |