Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

471 lines
10 KiB

  1. /*
  2. * pcy30Nov92 - Changed object.h to apcobj.h
  3. * ane02DEC92 - fixed memory corruption problem by allocating more space to
  4. * receive message from UPS
  5. * sja09Dec92 - Will Work with windows now.
  6. * sja10Dec92 - Allocates a proper Stream under windows now.
  7. * pcy11Dec92 - Move Windows stuff out of here
  8. * pcy14Dec92 - #include "cfgmgr.h"
  9. * pcy14Dec92 - Fixed misplaced else due to comment
  10. * pcy27Dec92: GlobalCommDevice can't be static
  11. * jod29Dec92: Edited Retry();
  12. * ane11Jan93: Edited Retry();
  13. * jod13Jan93: Fixed Retry to add the NO_COMM event to the eventList
  14. * ane25Jan93: Added extra error checking and returns on initialization
  15. * jod28Jan93: Fixed the Data and Decrement Sets
  16. * ane03Feb93: Changed error checking
  17. * rct17May93: fixed include files
  18. * cad10Jun93: Changes to allow MUps
  19. * cad14Sep93: Cleaning up theState
  20. * cad15Nov93: Changing how lost comm works
  21. * cad17Nov93: .. more little fixups
  22. * mwh19Nov93: changed EventID to INT
  23. * rct21Dec93: fixed rebuild port - if the open fails, writes won't occur
  24. * cad14Jan94: not including old global stuff
  25. * rct21Dec93: fixed rebuildPort again - if the open fails, writes won't occur
  26. * ajr08Mar94: added some error checking to rebuildPort.
  27. * pcy10Mar94: Got rid of meaningless overides of Get and Set
  28. * pcy08Apr94: Trim size, use static iterators, dead code removal
  29. * pcy13Apr94: Use automatic variables decrease dynamic mem allocation
  30. * cad17Jun94: Flushing UPS Input after retry succeeds, re-syncs conversation
  31. * ajr12Jul94: The Flushing stuff broke BackUps. sendRetryMessage() should
  32. * return true for Backups
  33. * cgm28Feb96: Add override switch for nlm
  34. * cgm04May96: TestResponse now uses BufferSize
  35. * poc28Sep96: Added valuable debugging code.
  36. * tjg10Nov97: Cancel the RetryTimer on RETRY_CONSTRUCT
  37. */
  38. #include "cdefine.h"
  39. extern "C" {
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <malloc.h>
  43. #include <string.h>
  44. }
  45. #include "_defs.h"
  46. #include "codes.h"
  47. #include "apcobj.h"
  48. #include "list.h"
  49. #include "dispatch.h"
  50. #include "comctrl.h"
  51. #include "event.h"
  52. #include "message.h"
  53. #include "pollparm.h"
  54. #include "ulinkdef.h"
  55. #include "trans.h"
  56. #include "protsmrt.h"
  57. #include "cdevice.h"
  58. #include "upsdev.h"
  59. #include "cfgmgr.h"
  60. #include "timerman.h"
  61. #include "protlist.h"
  62. #include "err.h"
  63. #include "stream.h"
  64. #if APCDEBUG
  65. #include "errlogr.h"
  66. #endif
  67. #define UNKNOWN 0
  68. #define RETRY_FAILED 1
  69. #define RETRY_SUCCESS 0
  70. #define ASKUPS_FAILED 1
  71. #define ASKUPS_OK 0
  72. #define RETRY_MAX 3
  73. UpsCommDevice::UpsCommDevice(CommController* control)
  74. : CommDevice(control),
  75. theRetryTimer(0),
  76. theForceCommEventFlag(FALSE),
  77. theCableType(NORMAL)
  78. {
  79. CreateProtocol();
  80. }
  81. UpsCommDevice::~UpsCommDevice()
  82. {
  83. theController->UnregisterEvent(EXIT_THREAD_NOW, this);
  84. if(theRetryTimer) {
  85. _theTimerManager->CancelTimer(theRetryTimer);
  86. theRetryTimer = 0;
  87. }
  88. }
  89. INT UpsCommDevice::Initialize()
  90. {
  91. CHAR value[64], cable_type[10];
  92. _theConfigManager->Get(CFG_UPS_POLL_INTERVAL, value);
  93. thePollInterval = atoi(value);
  94. INT err = rebuildPort();
  95. if (err == ErrNO_ERROR)
  96. {
  97. Connect();
  98. }
  99. // Register here instead of in CommDevice::Initialize() - that method
  100. // does things with the port we don't want to
  101. theController->RegisterEvent(EXIT_THREAD_NOW, this);
  102. return err;
  103. }
  104. /*--------------------------------------------------------------------
  105. *
  106. * Function...: Connect
  107. *
  108. * Description: Opens the device and make a comm connection.
  109. *
  110. *-------------------------------------------------------------------*/
  111. INT UpsCommDevice::Connect()
  112. {
  113. if (!thePollThread) {
  114. StartPollThread();
  115. }
  116. return ErrNO_ERROR;
  117. }
  118. INT UpsCommDevice::Get(INT pid, PCHAR value)
  119. {
  120. INT err = ErrNO_ERROR;
  121. switch(pid) {
  122. case COMMUNICATION_STATE:
  123. sprintf(value, "%d", theLostCommFlag ?
  124. COMMUNICATION_LOST : COMMUNICATION_ESTABLISHED);
  125. break;
  126. default:
  127. err = CommDevice::Get(pid, value);
  128. break;
  129. }
  130. return err;
  131. }
  132. INT UpsCommDevice::Set(INT pid, const PCHAR value)
  133. {
  134. INT err = ErrNO_ERROR;
  135. switch(pid) {
  136. case RETRY_CONSTRUCT:
  137. if (theRetryTimer) {
  138. _theTimerManager->CancelTimer(theRetryTimer);
  139. theRetryTimer = 0;
  140. }
  141. theLostCommFlag = TRUE;
  142. theForceCommEventFlag = TRUE;
  143. _theTimerManager->Wait(2000L); // Allow On-going Operations to Stop
  144. err = rebuildPort();
  145. break;
  146. default:
  147. err = CommDevice::Set(pid, value);
  148. break;
  149. }
  150. return err;
  151. }
  152. INT UpsCommDevice::sendRetryMessage()
  153. {
  154. INT done = FALSE;
  155. if ( !(Set(TURN_ON_SMART_MODE, (CHAR*)NULL)) ) {
  156. done = TRUE;
  157. }
  158. CHAR buf[128];
  159. USHORT len = sizeof(buf);
  160. //
  161. // clearing out extra chars in the serial buffer
  162. //
  163. while (thePort->Read(buf, (USHORT *) &len, 500L) == ErrNO_ERROR);
  164. return done;
  165. }
  166. /*--------------------------------------------------------------------
  167. *
  168. * Function...: Retry
  169. *
  170. * Description: .
  171. *
  172. *-------------------------------------------------------------------*/
  173. INT UpsCommDevice::Retry()
  174. {
  175. INT index = 0;
  176. if(theState != RETRYING) {
  177. theState = RETRYING;
  178. INT done = sendRetryMessage();
  179. if (!done)
  180. {
  181. theLostCommFlag = TRUE;
  182. Event event(COMMUNICATION_STATE, COMMUNICATION_LOST);
  183. event.SetAttributeValue(FAILURE_CAUSE, COMMUNICATION_LOST);
  184. theForceCommEventFlag = FALSE;
  185. UpdateObj::Update(&event);
  186. if (!theRetryTimer)
  187. {
  188. Event retry_event(RETRY_CONSTRUCT, RETRY_PORT);
  189. theRetryTimer =_theTimerManager->SetTheTimer((ULONG)2,
  190. &retry_event,
  191. this);
  192. }
  193. return RETRY_FAILED;
  194. }
  195. theState = NORMAL_STATE;
  196. }
  197. return RETRY_SUCCESS;
  198. }
  199. INT UpsCommDevice::Update(PEvent anEvent)
  200. {
  201. INT err = ErrNO_ERROR;
  202. switch(anEvent->GetCode())
  203. {
  204. case RETRY_CONSTRUCT:
  205. theRetryTimer = 0;
  206. err = rebuildPort();
  207. break;
  208. case EXIT_THREAD_NOW:
  209. _theTimerManager->CancelTimer(theRetryTimer);
  210. theRetryTimer = 0;
  211. err = CommDevice::Update(anEvent);
  212. break;
  213. }
  214. return err;
  215. }
  216. INT UpsCommDevice::rebuildPort()
  217. {
  218. if(thePort)
  219. {
  220. delete thePort;
  221. thePort = (PStream)NULL;
  222. }
  223. INT err = CreatePort();
  224. if (thePort) {
  225. err = thePort->Initialize(); // don't reset this value !!!
  226. }
  227. INT have_comm = FALSE;
  228. if (err == ErrNO_ERROR)
  229. {
  230. have_comm = sendRetryMessage();
  231. }
  232. if (!have_comm) {
  233. // Toggle the cable type
  234. if (theCableType == NORMAL) {
  235. theCableType = PNP;
  236. }
  237. else {
  238. theCableType = NORMAL;
  239. }
  240. }
  241. if (have_comm)
  242. {
  243. theState = NORMAL_STATE;
  244. theLostCommFlag = FALSE;
  245. Event event(COMMUNICATION_STATE, COMMUNICATION_ESTABLISHED);
  246. UpdateObj::Update(&event);
  247. if (theCurrentTransaction == (PTransactionGroup)NULL)
  248. {
  249. theCurrentTransaction = (PTransactionGroup) thePollList->GetHead();
  250. }
  251. }
  252. else
  253. {
  254. if (!theLostCommFlag || theForceCommEventFlag)
  255. {
  256. if (!theLostCommFlag)
  257. {
  258. theState = COMM_STOPPED;
  259. theLostCommFlag = TRUE;
  260. }
  261. theForceCommEventFlag = FALSE;
  262. Event event(COMMUNICATION_STATE, COMMUNICATION_LOST);
  263. UpdateObj::Update(&event);
  264. }
  265. if ((!theRetryTimer) && (err == ErrNO_ERROR))
  266. {
  267. Event retry_event(RETRY_CONSTRUCT, RETRY_PORT);
  268. theRetryTimer =_theTimerManager->SetTheTimer((ULONG)5, &retry_event,
  269. this);
  270. }
  271. }
  272. return err;
  273. }
  274. /*--------------------------------------------------------------------
  275. *
  276. * Function...: AskUps
  277. *
  278. * Description: .
  279. *
  280. *-------------------------------------------------------------------*/
  281. INT UpsCommDevice::AskUps(Message* msg)
  282. {
  283. CHAR Buffer[512];
  284. USHORT BufferSize = 0;
  285. INT writecomplete = FALSE;
  286. INT ret = ErrNO_ERROR;
  287. //
  288. // Clean out old errors
  289. //
  290. msg->setErrcode(ErrNO_ERROR);
  291. if (!thePort)
  292. {
  293. return ret;
  294. }
  295. if (theAbortSem) {
  296. theAbortSem->TimedWait(250);
  297. }
  298. while (!writecomplete) {
  299. thePort->SetRequestCode(msg->getId());
  300. thePort->SetWaitTime(msg->getWaitTime());
  301. ret = thePort->Write(msg->getSubmit());
  302. if (ret == ErrWRITE_FAILED)
  303. {
  304. if (!theLostCommFlag && Retry() )/* If RETY FAILED */
  305. {
  306. msg->setErrcode(ErrCOMMUNICATION_LOST);
  307. return ASKUPS_OK; /* Return Ok-- Let */
  308. } /* UPS do RESTART */
  309. else
  310. {
  311. msg->setErrcode(ErrWRITE_FAILED);
  312. return ASKUPS_FAILED;
  313. }
  314. }
  315. else
  316. writecomplete = TRUE;
  317. }
  318. *Buffer = 0;
  319. BufferSize = 511;
  320. INT readcomplete = FALSE;
  321. ret = 0;
  322. while (!readcomplete) {
  323. int testRet;
  324. ret = thePort->Read(Buffer, &BufferSize, (ULONG)msg->getTimeout());
  325. if ((ret == ErrREAD_FAILED) && (testRet = theProtocol->TestResponse(msg,Buffer,BufferSize)) )
  326. {
  327. if (testRet == ErrNO_MEASURE_UPS)
  328. {
  329. msg->setErrcode(testRet);
  330. return ASKUPS_OK;
  331. }
  332. else
  333. {
  334. if ( Retry() )
  335. { /* If RETRY FAILED */
  336. msg->setErrcode(ErrCOMMUNICATION_LOST);
  337. return ASKUPS_OK;/* Return Ok-- Let */
  338. } /* UPS do RESTART */
  339. else
  340. {
  341. msg->setErrcode(ErrREAD_FAILED);
  342. return ASKUPS_FAILED;
  343. }
  344. }
  345. }
  346. else
  347. {
  348. readcomplete = TRUE;
  349. }
  350. }
  351. Buffer[BufferSize] = '\0';
  352. msg->setResponse(Buffer);
  353. return ASKUPS_OK;
  354. }
  355. INT UpsCommDevice::CreateProtocol()
  356. {
  357. CHAR signal_type[64];
  358. _theConfigManager->Get(CFG_UPS_SIGNALLING_TYPE, signal_type);
  359. if(strcmp((_strupr(signal_type)), "SIMPLE") == 0) {
  360. theProtocol = new SimpleUpsProtocol();
  361. }
  362. else {
  363. CHAR protocol[32];
  364. _theConfigManager->Get(CFG_UPS_PROTOCOL, protocol);
  365. if(strcmp((_strupr(protocol)), "UPSLINK") == 0) {
  366. theProtocol = new UpsLinkProtocol();
  367. }
  368. else if(strcmp((_strupr(protocol)), "GCIP") == 0) {
  369. // theProtocol = new GcipProtocol();
  370. }
  371. else {
  372. theProtocol = new SimpleUpsProtocol();
  373. }
  374. }
  375. return TRUE;
  376. }