1 /* 2 * FreeRTOS Modbus Libary: A Modbus serial implementation for FreeRTOS 3 * Copyright (C) 2006 Christian Walter <[email protected]> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 21 22 /* ----------------------- System includes ----------------------------------*/ 23 #include "stdlib.h" 24 #include "string.h" 25 26 /* ----------------------- Platform includes --------------------------------*/ 27 #include "port.h" 28 29 /* ----------------------- Modbus includes ----------------------------------*/ 30 #include "mb.h" 31 #include "mbframe.h" 32 #include "mbproto.h" 33 #include "mbconfig.h" 34 35 /* ----------------------- Defines ------------------------------------------*/ 36 #define MB_PDU_FUNC_READ_ADDR_OFF ( MB_PDU_DATA_OFF ) 37 #define MB_PDU_FUNC_READ_DISCCNT_OFF ( MB_PDU_DATA_OFF + 2 ) 38 #define MB_PDU_FUNC_READ_SIZE ( 4 ) 39 #define MB_PDU_FUNC_READ_DISCCNT_MAX ( 0x07D0 ) 40 41 /* ----------------------- Static functions ---------------------------------*/ 42 eMBException prveMBError2Exception( eMBErrorCode eErrorCode ); 43 44 /* ----------------------- Start implementation -----------------------------*/ 45 46 #if MB_FUNC_READ_COILS_ENABLED > 0 47 48 eMBException 49 eMBFuncReadDiscreteInputs( UCHAR * pucFrame, USHORT * usLen ) 50 { 51 USHORT usRegAddress; 52 USHORT usDiscreteCnt; 53 UCHAR ucNBytes; 54 UCHAR *pucFrameCur; 55 56 eMBException eStatus = MB_EX_NONE; 57 eMBErrorCode eRegStatus; 58 59 if( *usLen == ( MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN ) ) 60 { 61 usRegAddress = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8 ); 62 usRegAddress |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1] ); 63 usRegAddress++; 64 65 usDiscreteCnt = ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF] << 8 ); 66 usDiscreteCnt |= ( USHORT )( pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1] ); 67 68 /* Check if the number of registers to read is valid. If not 69 * return Modbus illegal data value exception. 70 */ 71 if( ( usDiscreteCnt >= 1 ) && 72 ( usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_MAX ) ) 73 { 74 /* Set the current PDU data pointer to the beginning. */ 75 pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; 76 *usLen = MB_PDU_FUNC_OFF; 77 78 /* First byte contains the function code. */ 79 *pucFrameCur++ = MB_FUNC_READ_DISCRETE_INPUTS; 80 *usLen += 1; 81 82 /* Test if the quantity of coils is a multiple of 8. If not last 83 * byte is only partially field with unused coils set to zero. */ 84 if( ( usDiscreteCnt & 0x0007 ) != 0 ) 85 { 86 ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 + 1 ); 87 } 88 else 89 { 90 ucNBytes = ( UCHAR ) ( usDiscreteCnt / 8 ); 91 } 92 *pucFrameCur++ = ucNBytes; 93 *usLen += 1; 94 95 eRegStatus = 96 eMBRegDiscreteCB( pucFrameCur, usRegAddress, usDiscreteCnt ); 97 98 /* If an error occured convert it into a Modbus exception. */ 99 if( eRegStatus != MB_ENOERR ) 100 { 101 eStatus = prveMBError2Exception( eRegStatus ); 102 } 103 else 104 { 105 /* The response contains the function code, the starting address 106 * and the quantity of registers. We reuse the old values in the 107 * buffer because they are still valid. */ 108 *usLen += ucNBytes;; 109 } 110 } 111 else 112 { 113 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 114 } 115 } 116 else 117 { 118 /* Can't be a valid read coil register request because the length 119 * is incorrect. */ 120 eStatus = MB_EX_ILLEGAL_DATA_VALUE; 121 } 122 return eStatus; 123 } 124 125 #endif 126