1 // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 2 /* 3 * Copyright (c) 2011, 2012, Atheros Communications Inc. 4 * Copyright (c) 2014, I2SE GmbH 5 */ 6 7 /* Atheros ethernet framing. Every Ethernet frame is surrounded 8 * by an atheros frame while transmitted over a serial channel; 9 */ 10 11 #include <linux/init.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 15 #include "qca_7k_common.h" 16 17 u16 18 qcafrm_create_header(u8 *buf, u16 length) 19 { 20 __le16 len; 21 22 if (!buf) 23 return 0; 24 25 len = cpu_to_le16(length); 26 27 buf[0] = 0xAA; 28 buf[1] = 0xAA; 29 buf[2] = 0xAA; 30 buf[3] = 0xAA; 31 buf[4] = len & 0xff; 32 buf[5] = (len >> 8) & 0xff; 33 buf[6] = 0; 34 buf[7] = 0; 35 36 return QCAFRM_HEADER_LEN; 37 } 38 EXPORT_SYMBOL_GPL(qcafrm_create_header); 39 40 u16 41 qcafrm_create_footer(u8 *buf) 42 { 43 if (!buf) 44 return 0; 45 46 buf[0] = 0x55; 47 buf[1] = 0x55; 48 return QCAFRM_FOOTER_LEN; 49 } 50 EXPORT_SYMBOL_GPL(qcafrm_create_footer); 51 52 /* Gather received bytes and try to extract a full ethernet frame by 53 * following a simple state machine. 54 * 55 * Return: QCAFRM_GATHER No ethernet frame fully received yet. 56 * QCAFRM_NOHEAD Header expected but not found. 57 * QCAFRM_INVLEN Atheros frame length is invalid 58 * QCAFRM_NOTAIL Footer expected but not found. 59 * > 0 Number of byte in the fully received 60 * Ethernet frame 61 */ 62 63 s32 64 qcafrm_fsm_decode(struct qcafrm_handle *handle, u8 *buf, u16 buf_len, u8 recv_byte) 65 { 66 s32 ret = QCAFRM_GATHER; 67 u16 len; 68 69 switch (handle->state) { 70 case QCAFRM_HW_LEN0: 71 case QCAFRM_HW_LEN1: 72 /* by default, just go to next state */ 73 handle->state--; 74 75 if (recv_byte != 0x00) { 76 /* first two bytes of length must be 0 */ 77 handle->state = handle->init; 78 } 79 break; 80 case QCAFRM_HW_LEN2: 81 case QCAFRM_HW_LEN3: 82 handle->state--; 83 break; 84 /* 4 bytes header pattern */ 85 case QCAFRM_WAIT_AA1: 86 case QCAFRM_WAIT_AA2: 87 case QCAFRM_WAIT_AA3: 88 case QCAFRM_WAIT_AA4: 89 if (recv_byte != 0xAA) { 90 ret = QCAFRM_NOHEAD; 91 handle->state = handle->init; 92 } else { 93 handle->state--; 94 } 95 break; 96 /* 2 bytes length. */ 97 /* Borrow offset field to hold length for now. */ 98 case QCAFRM_WAIT_LEN_BYTE0: 99 handle->offset = recv_byte; 100 handle->state = QCAFRM_WAIT_LEN_BYTE1; 101 break; 102 case QCAFRM_WAIT_LEN_BYTE1: 103 handle->offset = handle->offset | (recv_byte << 8); 104 handle->state = QCAFRM_WAIT_RSVD_BYTE1; 105 break; 106 case QCAFRM_WAIT_RSVD_BYTE1: 107 handle->state = QCAFRM_WAIT_RSVD_BYTE2; 108 break; 109 case QCAFRM_WAIT_RSVD_BYTE2: 110 len = handle->offset; 111 if (len > buf_len || len < QCAFRM_MIN_LEN) { 112 ret = QCAFRM_INVLEN; 113 handle->state = handle->init; 114 } else { 115 handle->state = (enum qcafrm_state)(len + 1); 116 /* Remaining number of bytes. */ 117 handle->offset = 0; 118 } 119 break; 120 default: 121 /* Receiving Ethernet frame itself. */ 122 buf[handle->offset] = recv_byte; 123 handle->offset++; 124 handle->state--; 125 break; 126 case QCAFRM_WAIT_551: 127 if (recv_byte != 0x55) { 128 ret = QCAFRM_NOTAIL; 129 handle->state = handle->init; 130 } else { 131 handle->state = QCAFRM_WAIT_552; 132 } 133 break; 134 case QCAFRM_WAIT_552: 135 if (recv_byte != 0x55) { 136 ret = QCAFRM_NOTAIL; 137 handle->state = handle->init; 138 } else { 139 ret = handle->offset; 140 /* Frame is fully received. */ 141 handle->state = handle->init; 142 } 143 break; 144 } 145 146 return ret; 147 } 148 EXPORT_SYMBOL_GPL(qcafrm_fsm_decode); 149 150 MODULE_DESCRIPTION("Qualcomm Atheros QCA7000 common"); 151 MODULE_AUTHOR("Qualcomm Atheros Communications"); 152 MODULE_AUTHOR("Stefan Wahren <wahrenst@gmx.net>"); 153 MODULE_LICENSE("Dual BSD/GPL"); 154