/// <summary> /// Allocate the memory for the destination buffer and copy the response /// to the destination buffer /// </summary> /// <param name="dstResponse"></param> internal void GetResponse(out byte[] dstResponse) { if (response != null) { dstResponse = new byte[response.Length]; Buffer.BlockCopy(response, 0, dstResponse, 0, response.Length); } else { ResponsePacketUtil.GenerateResponsePacket(CompletionCode.ResponseNotProvided, out dstResponse); } }
/// <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); } } }