// Text of project Basic Serial written on 4/25/97 at 1:42 PM // Beginning of text file Project Data // Copyright © 1994-1995 Apple Computer, Inc. All rights reserved constant kAction_Connect := 'connect; constant kAction_Listen := 'listen; constant kState_Disconnected := 0; // ready-to-go (default state) constant kState_Listen := 1; // preparation for (asynchronous) listen constant kState_Listening := 2; // in-process of (asynchronous) listen constant kState_Connect := 3; // preparation for (asynchronous) connect constant kState_Connecting := 4; // in-process of (asynchronous) connect constant kState_Connected := 5; // connected (requires disconnect) constant kState_Disconnecting := 6; // in-process of (asynchronous) disconnect constant kMessage_Disconnected := "Ready to connectÉ"; constant kMessage_Listening := "Waiting for connection..."; constant kMessage_Connecting := "Connecting..."; constant kMessage_Connected := "Connected, awaiting disconnect..."; constant kMessage_Disconnecting := "Disconnecting, please wait..."; constant kMessage_ConnectFailed := "Connection not established; no response."; constant kMessage_BufferOverrun := "The communications data buffer was overrun and has been reset."; constant kMessage_Timeout := "The connection seems to have timed out."; constant kMessage_PortInUse := "Another application seems to be using the communications port."; constant kMessage_PortDoesNotExist := "The requested communications port does not exist."; constant kMessage_OutputTooFast := "Synchronous outputs are occuring too quickly; some data was not output."; // End of text file Project Data // Beginning of file protoDisconnectSlip // Before Script for "_userproto000" // Copyright © 1994-1995 Apple Computer, Inc. All rights reserved. _userproto000 := {viewBounds: {left: 0, top: 0, right: 108, bottom: 44}, viewJustify: 80, ReorientToScreen: ROM_DefRotateFunc, _proto: @179 }; _view000 := {viewBounds: {left: 8, top: 8, right: 104, bottom: 40}, viewJustify: 2, text: "Disconnecting... Please Wait...", _proto: @218 }; AddStepForm(_userproto000, _view000); constant |layout_protoDisconnectSlip| := _userproto000; // End of file protoDisconnectSlip // Beginning of file Basic Serial.t // Before Script for "vMainApp" // Copyright © 1994-1995 Apple Computer, Inc. All rights reserved. vMainApp := { viewSetupDoneScript: func() begin :MSetEndPointState(fEndPointState); // do NOT change the endpoint state -- just update any views that depend on it if fEndPointState = kState_Disconnected then :MMessage(kMessage_Disconnected); else :MMessage(""); end, MMessage: func(message) // this routine can be called regardless of the value of SELF begin local appBaseView := GetRoot().(kAppSymbol); if call kViewIsOpenFunc with (appBaseView) then begin SetValue(appBaseView.vMessage, 'text, Clone(message)); RefreshViews(); end end, viewFormat: 83951953, viewQuitScript: func() begin :MDisconnect(); RemoveSlot(GetRoot().(kAppSymbol), 'fEndPoint); end, MConnect: func(connectAction) begin if fEndPointState <> kState_Disconnected then return; fEndPoint.fConnectAction := connectAction; fEndPoint.fQuiet := nil; if connectAction = kAction_Listen then :MSetEndPointState(kState_Listen); else if connectAction = kAction_Connect then :MSetEndPointState(kState_Connect); else return; fEndPoint:MConnectAction(); end, MDisconnectCompProc: func(options, result) // SELF is the endpoint frame begin try :UnBind(nil) onexception |evt.ex.comm| do nil; try :Dispose() onexception |evt.ex.comm| do nil; if fDisconnectSlip then begin fDisconnectSlip:Close(); fDisconnectSlip := nil; end; :MMessage(kMessage_Disconnected); :MSetEndPointState(kState_Disconnected); if fPowerOffState then begin fPowerOffState := nil; PowerOffResume(kAppSymbol); end; UnRegPowerOff(kAppSymbol); end, MShowSerialInfo: DefConst('kSerialInfoOptions, [ { label: kCMOSerialChipSpec, type: 'option, opCode: opGetCurrent, result: nil, form: 'template, data: { arglist: [ 0, // chip location 0, // features supported by this chip 0, // output signals supported by chip 0, // input signals supported by chip 0, // parity supported 0, // data and stop bits supported 0, // serial chip type nil, // chip in use 0, // reserved 0, // reserved 0, // PCMCIA card CIS manufacturer ID 0, ], // PCMCIA card CIS manufacturer ID info typelist: ['struct, 'ulong, // fHWLoc 'ulong, // fSerFeatures 'byte, // fSerOutSupported 'byte, // fSerInSupported 'byte, // fParitySupport 'byte, // fDataStopBitSupport 'byte, // fUARTType 'boolean, // fChipNotInUse 'byte, // reserved 'byte, // reserved 'short, // fCIS_ManFID 'short, ], }, }, // fCIS_ManFIDInfo ]); func() begin if fEndPointState <> kState_Connected then return :MNotify("Not connected."); local option := fEndPoint:Option(kSerialInfoOptions, nil); if not option then return; local result, message := ""; if (result := option[0].result) <> nil then message := message & "Get serial chip info failed: (" & NumberStr(result) & ")" & unicodeCR; else begin local serialChipType := option[0].data.arglist[6]; message := message & "Serial Chip: " & ( if serialChipType = 0x00 then "8250" else if serialChipType = 0x01 then "16450" else if serialChipType = 0x02 then "16550" else if serialChipType = 0x20 then "8530" else if serialChipType = 0x21 then "6850" else if serialChipType = 0x22 then "6402" else if serialChipType = 0x23 then "Reserved" else "Unknown" ) & " UART" & unicodeCR; end; :MMessage(message); end, fEndPointOptions: nil // see MBuildConfigOptions & MConnectAction for more info , MDisconnectAction: func(fromState) // SELF is the endpoint frame begin try :Cancel(nil) onexception |evt.ex.comm| do nil; if fromState = kState_Connected then try :Disconnect(nil, { async: true, // reqTimeout: 3600, completionScript: func(ep, options, result) ep:MDisconnectCompProc(options, result), }) onexception |evt.ex.comm| do :MDisconnectCompProc(nil, CurrentException().error); else :MDisconnectCompProc(nil, nil); end, MBuildConfigOptions: func() // SELF can be any frame that inherits to the app base view begin local options := [ { label: kCMSAsyncSerial, type: 'service, opCode: opSetRequired, result: nil, }, { label: kCMOSerialHWChipLoc, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { argList: [ vPort.clusterValue, // kHWLocExternalSerial, kHWLocBuiltInIR, kHWLocPCMCIASlot1 0, ], typeList: ['struct, ['array, 'char, 4], 'ulong, ], }, }, { label: kCMOSerialIOParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ k1StopBits, // 1 stop bit kNoParity, // no parity bit k8DataBits, // 8 data bits k19200bps, ], // date rate in bps typelist: ['struct, 'long, // stop bits 'long, // parity 'long, // data bits 'long, ], }, }, // bps { label: kCMOInputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ unicodeDC1, // xonChar unicodeDC3, // xoffChar nil, // useSoftFlowControl nil, // useHardFlowControl 0, // not needed; returned 0, ], // not needed; returned typelist: ['struct, 'byte, // XON character 'byte, // XOFF character 'boolean, // software flow control 'boolean, // hardware flow control 'boolean, // hardware flow blocked 'boolean, ], }, }, // software flow blocked { label: kCMOOutputFlowControlParms, type: 'option, opCode: opSetRequired, result: nil, form: 'template, data: { arglist: [ unicodeDC1, // xonChar unicodeDC3, // xoffChar nil, // useSoftFlowControl nil, // useHardFlowControl 0, // not needed; returned 0, ], // not needed; returned typelist: ['struct, 'byte, // XON character 'byte, // XOFF character 'boolean, // software flow control 'boolean, // hardware flow control 'boolean, // hardware flow blocked 'boolean, ], }, }, // software flow blocked ]; options; end, viewBounds: {left: -2, top: -2, right: 230, bottom: 310}, MExceptionHandler: func(exceptionFrame) // SELF is the endpoint frame begin if exceptionFrame and exceptionFrame.data and exceptionFrame.data <> -16005 then // ignore -16005 (just the result of calling Cancel) if exceptionFrame.data = -18003 then // I/O buffer overrun begin AddDeferredCall(func(ep) ep:MResetConnection(true), [self]); :MNotifyError(exceptionFrame.data); end; else begin // handle all other (unexptected) exceptions by disconnecting the endpoint AddDeferredCall(func(ep) ep:MDisconnect(), [self]); :MNotifyError(exceptionFrame.data); end; true; end, _proto: @157, MNotifyError: func(error) begin if not error or (fEndPoint and fEndPoint.fQuiet) then return; if error = -10017 then :MNotify(kMessage_OutputTooFast); else if error = -10078 then :MNotify(kMessage_PortInUse); else if error = -16013 then :MNotify(kMessage_Timeout); else if error = -16022 then :MNotify(kMessage_PortDoesNotExist); else if error = -18003 then :MNotify(kMessage_BufferOverrun); else if error = -38001 then :MNotify(kMessage_ConnectFailed); else :MNotify("An unexpected error has occured. Error code = " & NumberStr(error)); end, MResetConnection: func(cancel) // SELF is the endpoint frame begin if fEndPointState <> kState_Connected then return; if cancel then try :Cancel(nil) onexception |evt.ex.comm| do nil; :SetInputSpec(fEndPointInputSpec); end, viewJustify: 80, title: kAppName, fEndPointState: kState_Disconnected, fEndPointOutputSpec: { form: 'string, }, MDisconnect: func() begin if not fEndPoint or fEndPointState <> kState_Connected and fEndPointState <> kState_Connecting and fEndPointState <> kState_Listening then return; fEndPoint.fQuiet := true; // supress user alerts and other interactions while disconnecting local fromState := fEndPointState; :MSetEndPointState(kState_Disconnecting); :MMessage(kMessage_Disconnecting); fEndPoint.fDisconnectSlip := BuildContext(GetLayout("protoDisconnectSlip")); fEndPoint.fDisconnectSlip:Open(); fEndPoint:MDisconnectAction(fromState); end, fEndPoint: nil, fEndPointInputSpec: { form: 'string, termination: { endSequence: [unicodeCR], }, discardAfter: 256, inputScript: func(ep, data, terminator, options) ep:MInput(data), }, viewSetupFormScript: func() begin // make view no bigger than the original MP local b := GetAppParams(); viewBounds := RelBounds( b.appAreaLeft, b.appAreaTop, MIN( b.appAreaWidth, 240 ), MIN( b.appAreaHeight, 336 )); self.fEndPoint := { _proto: protoBasicEndPoint, _parent: self, exceptionHandler: MExceptionHandler, fConnectAction: nil, fConnectAddress: nil, fDisconnectSlip: nil, fPowerOffState: nil, fQuiet: nil, }; end, MOutput: func(data) // SELF can be any frame that inherits to the base app view begin if fEndPointState = kState_Connected then try fEndPoint:Output(data & unicodeCR, nil, fEndPointOutputSpec) onexception |evt.ex.comm| do :MExceptionHandler(CurrentException()); else :MNotify("Not connected."); end, MSetEndpointState: func(newState) // this routine can be called regardless of the value of SELF begin local appBaseView := GetRoot().(kAppSymbol); // NOTE: We must be absolutely certain fEndPointState gets created/overridden in the app base view frame! appBaseView.fEndPointState := newState; if not call kViewIsOpenFunc with (appBaseView) then return; if appBaseView.fEndPointState = kState_Disconnected then begin appBaseView.vConnect:Show(); appBaseView.vListen:Show(); appBaseView:MSetButtons("Connect", "Listen"); end; else if appBaseView.fEndPointState = kState_Listen then begin appBaseView.vConnect:Hide(); appBaseView:MSetButtons("Listening", nil); end; else if appBaseView.fEndPointState = kState_Listening then appBaseView:MSetButtons("Stop Listening", nil); else if appBaseView.fEndPointState = kState_Connect then begin appBaseView.vListen:Hide(); appBaseView:MSetButtons("Connecting", nil); end; else if appBaseView.fEndPointState = kState_Connecting then appBaseView:MSetButtons("Stop Connecting", nil); else if appBaseView.fEndPointState = kState_Connected then appBaseView:MSetButtons("Disconnect", nil); else if appBaseView.fEndPointState = kState_Disconnecting then appBaseView:MSetButtons("Disconnecting", nil); else appBaseView:MSetButtons("I Am Confused", nil); RefreshViews(); end, MInput: func(data) // SELF is the endpoint frame begin PlaySound(ROM_PlinkBeep); :MMessage(data); end, MConnectCompProc: func(options, result) // SELF is the endpoint frame begin if result then begin :MNotifyError(result); :MDisconnect(); return; end; if fConnectAction = kAction_Listen then try :Accept(nil, nil) onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MDisconnect(); return; end; :MSetEndPointState(kState_Connected); :MMessage(kMessage_Connected); :MResetConnection(nil); :MShowSerialInfo(); end, MConnectAction: func() // SELF is the endpoint frame begin fEndPointOptions := :MBuildConfigOptions(); try :Instantiate(self, fEndPointOptions) onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MSetEndPointState(kState_Disconnected); return; end; try :Bind(nil, nil) onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MSetEndPointState(kState_Disconnected); :Dispose(); return; end; RegPowerOff(kAppSymbol, func(what, why) // we create the closure here so as to set up SELF as the endpoint frame in the closure begin if what = 'okToPowerOff then begin if why <> 'idle // keep the unit awake whenever we're connected or fEndPointState = kState_Disconnected then // unless the user or an application explicitly return true; // wants it to sleep end; else if what = 'powerOff then begin if why <> 'idle // if we simply must go to sleep but we're still and fEndPointState <> kState_Disconnected then // connected then begin the disconnect process begin fPowerOffState := 'holdYourHorses; // set a flag to indicate we're powering down :MDisconnect(); return 'holdYourHorses; end; end; nil; // ALWAYS return nil here! end ); try begin if fConnectAction = kAction_Listen then begin :MSetEndPointState(kState_Listening); :MMessage(kMessage_Listening); :Listen( nil, { async: true, reqTimeout: 90000, // 90 seconds -- for DEMO purposes only completionScript: func(ep, options, result) ep:MConnectCompProc(options, result) }); end; else if fConnectAction = kAction_Connect then begin :MSetEndPointState(kState_Connecting); :MMessage(kMessage_Connecting); :Connect( [ fConnectAddress ], { async: true, reqTimeout: 45000, // 45 seconds -- for DEMO purposes only completionScript: func(ep, options, result) ep:MConnectCompProc(options, result), }); end; end onexception |evt.ex.comm| do begin :MNotifyError(CurrentException().error); :MDisconnect(); end; end, debug: "vMainApp", MNotify: func(message) begin GetRoot():Notify(kNotifyAlert, kAppName, message); // no longer necessary to EnsureInternal params end, MSetButtons: func(connectText, listenText) begin SetValue(vConnect, 'text, connectText); if listenText then SetValue(vListen, 'text, listenText); else SetValue(vListen, 'text, connectText); end }; _view001 := {viewBounds: {left: 8, top: 16, right: 224, bottom: 32}, text: "Messages & Received Data:", _proto: @218 }; AddStepForm(vMainApp, _view001); vMessage := {viewBounds: {left: 9, top: 33, right: 223, bottom: 119}, viewJustify: 0, viewFormat: 337, viewFont: simpleFont12, text: "", viewClickScript: func(unit) begin SetValue(self, 'text, ""); true; end, viewFlags: 515, debug: "vMessage", _proto: @218 }; AddStepForm(vMainApp, vMessage); StepDeclare(vMainApp, vMessage, 'vMessage); _view002 := {viewBounds: {left: 8, top: 128, right: 168, bottom: 144}, text: "Message To Send:", _proto: @218 }; AddStepForm(vMainApp, _view002); vInputArea := {viewFlags: 64001, viewFormat: 12625, viewLineSpacing: 20, viewFont: 18434, viewBounds: {left: 9, top: 145, right: 167, bottom: 195}, text: "This is a test!", debug: "vInputArea", viewClass: 81 }; AddStepForm(vMainApp, vInputArea); StepDeclare(vMainApp, vInputArea, 'vInputArea); vConnect := { buttonClickScript: func() begin if fEndPointState = kState_Disconnected then :MConnect(kAction_Connect); else :MDisconnect(); end, viewBounds: {left: 122, top: 214, right: 222, bottom: 234}, text: "" , debug: "vConnect", _proto: @226 }; AddStepForm(vMainApp, vConnect); StepDeclare(vMainApp, vConnect, 'vConnect); vListen := { buttonClickScript: func() begin if fEndPointState = kState_Disconnected then :MConnect(kAction_Listen); else :MDisconnect(); end, viewBounds: {left: 122, top: 242, right: 222, bottom: 262}, text: "" , debug: "vListen", _proto: @226 }; AddStepForm(vMainApp, vListen); StepDeclare(vMainApp, vListen, 'vListen); vSend := { buttonClickScript: func() begin :MOutput(if vInputArea.text then vInputArea.text else ""); end, viewBounds: {left: 178, top: 146, right: 222, bottom: 166}, text: "Send", debug: "vSend", _proto: @226 }; AddStepForm(vMainApp, vSend); StepDeclare(vMainApp, vSend, 'vSend); _view003 := {viewBounds: {left: 8, top: 204, right: 112, bottom: 220}, text: "Serial Port To Use:", _proto: @218 }; AddStepForm(vMainApp, _view003); vPort := {viewBounds: {left: 16, top: 220, right: 112, bottom: 276}, clusterValue: kHWLocExternalSerial, debug: "vPort", _proto: @203 }; AddStepForm(vMainApp, vPort); StepDeclare(vMainApp, vPort, 'vPort); _view004 := {buttonValue: kHWLocExternalSerial, viewBounds: {left: 0, top: 0, right: 96, bottom: 16}, text: "RS422 (Port A)", _proto: @202 }; AddStepForm(vPort, _view004); _view005 := {buttonValue: kHWLocBuiltInIR, viewBounds: {left: 0, top: 16, right: 96, bottom: 32}, text: "IR (Port B)", _proto: @202 }; AddStepForm(vPort, _view005); _view006 := {buttonValue: kHWLocPCMCIASlot1, viewBounds: {left: 0, top: 32, right: 96, bottom: 48}, text: "Serial Card In Slot 1", _proto: @202 }; AddStepForm(vPort, _view006); constant |layout_Basic Serial.t| := vMainApp; // End of file Basic Serial.t