/// <summary> /// Check if the request is valid with respect to device type, id, and request length /// </summary> /// <param name="deviceType"></param> /// <param name="deviceId"></param> /// <param name="request"></param> /// <returns></returns> static private bool IsValidRequest(byte deviceType, byte deviceId, ref byte[] request) { if (DeviceTypeChecker.IsValidDeviceType(deviceType) == false) { Tracer.WriteError("Invalid device type: {0}", deviceType); return(false); } if (DeviceIdChecker.IsValidLogicalDeviceId(deviceType, deviceId) == false) { Tracer.WriteError("Invalid device ID: {0}", deviceId); return(false); } if (request == null) { Tracer.WriteError("Null request packet"); return(false); } // For server commands, simply pass through. // Thus, no need to check the request packet length as long as it is not null if (deviceType != (byte)DeviceType.Server) { if (RequestPacketUtil.IsValidRequestLength(ref request) == false) { return(false); } } return(true); }
/// <summary> /// Every component in the higher level of the stack should call this method /// to send/receive data to/from actual hardware devices /// </summary> /// <param name="priorityLevel"></param> /// <param name="deviceType"></param> /// <param name="deviceId"></param> /// <param name="request"> /// Input /// [0]: function code /// [1:2]: byte count (N) /// [3:N+2]: payload /// </param> /// <param name="response"> /// Output /// [0]: completion code /// [1:2]: byte count (N) /// [3:N+2]: payload /// Note: response can be null /// </param> static internal void SendReceive(PriorityLevel priorityLevel, byte deviceType, byte deviceId, byte[] request, out byte[] response) { Tracer.WriteInfo("CommunicationDevice.SendReceive({0})", deviceType); ushort sessionId = IncrementTimeStampAndGetSessionId(); byte physicalId; // If CM is terminating, do not accept any more new requests if (isTerminating == true) { ResponsePacketUtil.GenerateResponsePacket(CompletionCode.ServiceTerminating, out response); return; } if (IsValidRequest(deviceType, deviceId, ref request) == false) { ResponsePacketUtil.GenerateResponsePacket(CompletionCode.InvalidCommand, out response); return; } physicalId = GetPhysicalIdFromLogicalId(deviceType, deviceId); Tracer.WriteInfo("CommunicationDevice.SendReceive PhysicalID ({0})", physicalId); using (WorkItem workItem = new WorkItem(deviceType, physicalId, request, sessionId)) { byte logicalPortId = (byte)LogicalPortId.InvalidLogicalPortId; byte functionCode = RequestPacketUtil.GetFunctionCode(ref request); switch (deviceType) { case (byte)DeviceType.Server: // Fall through case (byte)DeviceType.BladeConsole: logicalPortId = (byte)LogicalPortId.SerialPortServers; break; case (byte)DeviceType.SerialPortConsole: // TODO: Extend the code for more serial consoles if (deviceId == 1) { logicalPortId = (byte)LogicalPortId.SerialPortConsole1; } else if (deviceId == 2) { logicalPortId = (byte)LogicalPortId.SerialPortConsole2; } else if (deviceId == 3) { logicalPortId = (byte)LogicalPortId.SerialPortConsole3; } else if (deviceId == 4) { logicalPortId = (byte)LogicalPortId.SerialPortConsole4; } break; default: logicalPortId = (byte)LogicalPortId.SerialPortOtherDevices; break; } if (logicalPortId == (byte)LogicalPortId.InvalidLogicalPortId) { ResponsePacketUtil.GenerateResponsePacket(CompletionCode.InvalidCommand, out response); return; } // If currently in safe mode, reject all the requests routed to COM4 except for BladeConsole commands if ((isSafeModeEnabled == true) && (logicalPortId == (byte)LogicalPortId.SerialPortServers) && (deviceType != (byte)DeviceType.BladeConsole)) { ResponsePacketUtil.GenerateResponsePacket(CompletionCode.CannotExecuteRequestInSafeMode, out response); return; } if (portManagers[logicalPortId].SendReceive(priorityLevel, workItem) == true) { // Successfully added the request in the work queue Tracer.WriteInfo("[logicalPortId: {0}, priorityLevel: {1}] SendReceive succeeded and wait", logicalPortId, priorityLevel); // Sleep until signaled by the device worker thread // Wait time: wait time in the queue + worker thread processing time workItem.Wait(); // Copy the response to the output buffer workItem.GetResponse(out response); } else { // Could not add the reuqest in the work queue Tracer.WriteWarning("[logicalPortId: {0}, priorityLevel: {1}] SendReceive failed", logicalPortId, priorityLevel); ResponsePacketUtil.GenerateResponsePacket(CompletionCode.OutOfSpace, out response); } } }