1/* 2 * Copyright (c) 2011, 2012, Atheros Communications Inc. 3 * Copyright (c) 2014, I2SE GmbH 4 * 5 * Permission to use, copy, modify, and/or distribute this software 6 * for any purpose with or without fee is hereby granted, provided 7 * that the above copyright notice and this permission notice appear 8 * in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 13 * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 14 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 16 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 17 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20/* Atheros ethernet framing. Every Ethernet frame is surrounded 21 * by an atheros frame while transmitted over a serial channel; 22 */ 23 24#include <linux/kernel.h> 25 26#include "qca_framing.h" 27 28u16 29qcafrm_create_header(u8 *buf, u16 length) 30{ 31 __le16 len; 32 33 if (!buf) 34 return 0; 35 36 len = cpu_to_le16(length); 37 38 buf[0] = 0xAA; 39 buf[1] = 0xAA; 40 buf[2] = 0xAA; 41 buf[3] = 0xAA; 42 buf[4] = len & 0xff; 43 buf[5] = (len >> 8) & 0xff; 44 buf[6] = 0; 45 buf[7] = 0; 46 47 return QCAFRM_HEADER_LEN; 48} 49 50u16 51qcafrm_create_footer(u8 *buf) 52{ 53 if (!buf) 54 return 0; 55 56 buf[0] = 0x55; 57 buf[1] = 0x55; 58 return QCAFRM_FOOTER_LEN; 59} 60 61/* Gather received bytes and try to extract a full ethernet frame by 62 * following a simple state machine. 63 * 64 * Return: QCAFRM_GATHER No ethernet frame fully received yet. 65 * QCAFRM_NOHEAD Header expected but not found. 66 * QCAFRM_INVLEN Atheros frame length is invalid 67 * QCAFRM_NOTAIL Footer expected but not found. 68 * > 0 Number of byte in the fully received 69 * Ethernet frame 70 */ 71 72s32 73qcafrm_fsm_decode(struct qcafrm_handle *handle, u8 *buf, u16 buf_len, u8 recv_byte) 74{ 75 s32 ret = QCAFRM_GATHER; 76 u16 len; 77 78 switch (handle->state) { 79 case QCAFRM_HW_LEN0: 80 case QCAFRM_HW_LEN1: 81 /* by default, just go to next state */ 82 handle->state--; 83 84 if (recv_byte != 0x00) { 85 /* first two bytes of length must be 0 */ 86 handle->state = QCAFRM_HW_LEN0; 87 } 88 break; 89 case QCAFRM_HW_LEN2: 90 case QCAFRM_HW_LEN3: 91 handle->state--; 92 break; 93 /* 4 bytes header pattern */ 94 case QCAFRM_WAIT_AA1: 95 case QCAFRM_WAIT_AA2: 96 case QCAFRM_WAIT_AA3: 97 case QCAFRM_WAIT_AA4: 98 if (recv_byte != 0xAA) { 99 ret = QCAFRM_NOHEAD; 100 handle->state = QCAFRM_HW_LEN0; 101 } else { 102 handle->state--; 103 } 104 break; 105 /* 2 bytes length. */ 106 /* Borrow offset field to hold length for now. */ 107 case QCAFRM_WAIT_LEN_BYTE0: 108 handle->offset = recv_byte; 109 handle->state = QCAFRM_WAIT_LEN_BYTE1; 110 break; 111 case QCAFRM_WAIT_LEN_BYTE1: 112 handle->offset = handle->offset | (recv_byte << 8); 113 handle->state = QCAFRM_WAIT_RSVD_BYTE1; 114 break; 115 case QCAFRM_WAIT_RSVD_BYTE1: 116 handle->state = QCAFRM_WAIT_RSVD_BYTE2; 117 break; 118 case QCAFRM_WAIT_RSVD_BYTE2: 119 len = handle->offset; 120 if (len > buf_len || len < QCAFRM_ETHMINLEN) { 121 ret = QCAFRM_INVLEN; 122 handle->state = QCAFRM_HW_LEN0; 123 } else { 124 handle->state = (enum qcafrm_state)(len + 1); 125 /* Remaining number of bytes. */ 126 handle->offset = 0; 127 } 128 break; 129 default: 130 /* Receiving Ethernet frame itself. */ 131 buf[handle->offset] = recv_byte; 132 handle->offset++; 133 handle->state--; 134 break; 135 case QCAFRM_WAIT_551: 136 if (recv_byte != 0x55) { 137 ret = QCAFRM_NOTAIL; 138 handle->state = QCAFRM_HW_LEN0; 139 } else { 140 handle->state = QCAFRM_WAIT_552; 141 } 142 break; 143 case QCAFRM_WAIT_552: 144 if (recv_byte != 0x55) { 145 ret = QCAFRM_NOTAIL; 146 handle->state = QCAFRM_HW_LEN0; 147 } else { 148 ret = handle->offset; 149 /* Frame is fully received. */ 150 handle->state = QCAFRM_HW_LEN0; 151 } 152 break; 153 } 154 155 return ret; 156} 157