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.

908 lines
26 KiB

  1. /*
  2. (C) Copyright 1998
  3. All rights reserved.
  4. Portions of this software are:
  5. (C) Copyright 1995, 1999 TriplePoint, Inc. -- http://www.TriplePoint.com
  6. License to use this software is granted under the terms outlined in
  7. the TriplePoint Software Services Agreement.
  8. (C) Copyright 1992 Microsoft Corp. -- http://www.Microsoft.com
  9. License to use this software is granted under the terms outlined in
  10. the Microsoft Windows Device Driver Development Kit.
  11. @doc INTERNAL DChannel DChannel_c
  12. @module DChannel.c |
  13. This module implements the interface to the <t DCHANNEL_OBJECT>.
  14. Supports the high-level channel control functions used by the NDIS WAN
  15. Minport driver. This module isolates most the vendor specific Call
  16. Control interfaces. It will require some changes to accomodate your
  17. hardware device's call control mechanism.
  18. @head3 Contents |
  19. @index class,mfunc,func,msg,mdata,struct,enum | DChannel_c
  20. @end
  21. */
  22. #define __FILEID__ DCHANNEL_OBJECT_TYPE
  23. // Unique file ID for error logging
  24. #include "Miniport.h" // Defines all the miniport objects
  25. #if defined(NDIS_LCODE)
  26. # pragma NDIS_LCODE // Windows 95 wants this code locked down!
  27. # pragma NDIS_LDATA
  28. #endif
  29. DBG_STATIC ULONG g_DChannelInstanceCounter // @globalv
  30. // Keeps track of how many <t DCHANNEL_OBJECT>s are created.
  31. = 0;
  32. /* @doc EXTERNAL INTERNAL DChannel DChannel_c g_DChannelParameters
  33. @topic 5.4 DChannel Parameters |
  34. This section describes the registry parameters read into the
  35. <t DCHANNEL_OBJECT>.
  36. @globalv PARAM_TABLE | g_DChannelParameters |
  37. This table defines the registry based parameters to be assigned to data
  38. members of the <t DCHANNEL_OBJECT>.
  39. <f Note>:
  40. If you add any registry based data members to <t DCHANNEL_OBJECT>
  41. you will need to modify <f DChannelReadParameters> and add the parameter
  42. definitions to the <f g_DChannelParameters> table.
  43. */
  44. DBG_STATIC PARAM_TABLE g_DChannelParameters[] =
  45. {
  46. PARAM_ENTRY(DCHANNEL_OBJECT,
  47. TODO, PARAM_TODO,
  48. FALSE, NdisParameterInteger, 0,
  49. 0, 0, 0),
  50. /* The last entry must be an empty string! */
  51. { { 0 } }
  52. };
  53. /* @doc INTERNAL DChannel DChannel_c DChannelReadParameters
  54. @func
  55. <f DChannelReadParameters> reads the DChannel parameters from the registry
  56. and initializes the associated data members. This should only be called
  57. by <f DChannelCreate>.
  58. <f Note>:
  59. If you add any registry based data members to <t DCHANNEL_OBJECT>
  60. you will need to modify <f DChannelReadParameters> and add the parameter
  61. definitions to the <f g_DChannelParameters> table.
  62. @rdesc
  63. <f DChannelReadParameters> returns zero if it is successful.<nl>
  64. Otherwise, a non-zero return value indicates an error condition.
  65. */
  66. DBG_STATIC NDIS_STATUS DChannelReadParameters(
  67. IN PDCHANNEL_OBJECT pDChannel // @parm
  68. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  69. )
  70. {
  71. DBG_FUNC("DChannelReadParameters")
  72. NDIS_STATUS Status;
  73. // Status result returned from an NDIS function call.
  74. PMINIPORT_ADAPTER_OBJECT pAdapter;
  75. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  76. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  77. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  78. DBG_ENTER(pAdapter);
  79. /*
  80. // Parse the registry parameters.
  81. */
  82. Status = ParamParseRegistry(
  83. pAdapter->MiniportAdapterHandle,
  84. pAdapter->WrapperConfigurationContext,
  85. (PUCHAR)pDChannel,
  86. g_DChannelParameters
  87. );
  88. if (Status == NDIS_STATUS_SUCCESS)
  89. {
  90. /*
  91. // Make sure the parameters are valid.
  92. */
  93. if (pDChannel->TODO)
  94. {
  95. DBG_ERROR(pAdapter,("Invalid parameter\n"
  96. ));
  97. NdisWriteErrorLogEntry(
  98. pAdapter->MiniportAdapterHandle,
  99. NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,
  100. 3,
  101. pDChannel->TODO,
  102. __FILEID__,
  103. __LINE__
  104. );
  105. Status = NDIS_STATUS_FAILURE;
  106. }
  107. else
  108. {
  109. /*
  110. // Finish setting up data members based on registry settings.
  111. */
  112. }
  113. }
  114. DBG_RETURN(pAdapter, Status);
  115. return (Status);
  116. }
  117. /* @doc INTERNAL DChannel DChannel_c DChannelCreateObjects
  118. @func
  119. <f DChannelCreateObjects> calls the create routines for all the objects
  120. contained in <t DCHANNEL_OBJECT>. This should only be called
  121. by <f DChannelCreate>.
  122. <f Note>:
  123. If you add any new objects to <t DCHANNEL_OBJECT> you will need
  124. to modify <f DChannelCreateObjects> and <f DChannelDestroyObjects> so they
  125. will get created and destroyed properly.
  126. @rdesc
  127. <f DChannelCreateObjects> returns zero if it is successful.<nl>
  128. Otherwise, a non-zero return value indicates an error condition.
  129. */
  130. DBG_STATIC NDIS_STATUS DChannelCreateObjects(
  131. IN PDCHANNEL_OBJECT pDChannel // @parm
  132. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  133. )
  134. {
  135. DBG_FUNC("DChannelCreateObjects")
  136. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  137. // Holds the result code returned by this function.
  138. PMINIPORT_ADAPTER_OBJECT pAdapter;
  139. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  140. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  141. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  142. DBG_ENTER(pAdapter);
  143. // TODO - Add code here to allocate any sub-objects needed to support
  144. // your physical DChannels.
  145. DBG_RETURN(pAdapter, Result);
  146. return (Result);
  147. }
  148. /* @doc INTERNAL DChannel DChannel_c DChannelCreate
  149. @func
  150. <f DChannelCreate> allocates memory for a <t DCHANNEL_OBJECT> and then
  151. initializes the data members to their starting state.
  152. If successful, <p ppDChannel> will be set to point to the newly created
  153. <t DCHANNEL_OBJECT>. Otherwise, <p ppDChannel> will be set to NULL.
  154. @comm
  155. This function should be called only once when the Miniport is loaded.
  156. Before the Miniport is unloaded, <f DChannelDestroy> must be called to
  157. release the <t DCHANNEL_OBJECT> created by this function.
  158. @rdesc
  159. <f DChannelCreate> returns zero if it is successful.<nl>
  160. Otherwise, a non-zero return value indicates an error condition.
  161. */
  162. NDIS_STATUS DChannelCreate(
  163. OUT PDCHANNEL_OBJECT * ppDChannel, // @parm
  164. // Points to a caller-defined memory location to which this function
  165. // writes the virtual address of the allocated <t DCHANNEL_OBJECT>.
  166. IN PMINIPORT_ADAPTER_OBJECT pAdapter // @parm
  167. // A pointer to the <t MINIPORT_ADAPTER_OBJECT> instance.
  168. )
  169. {
  170. DBG_FUNC("DChannelCreate")
  171. PDCHANNEL_OBJECT pDChannel;
  172. // Pointer to our newly allocated object.
  173. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  174. // Holds the result code returned by this function.
  175. ASSERT(pAdapter && pAdapter->ObjectType == MINIPORT_ADAPTER_OBJECT_TYPE);
  176. DBG_ENTER(pAdapter);
  177. /*
  178. // Make sure the caller's object pointer is NULL to begin with.
  179. // It will be set later only if everything is successful.
  180. */
  181. *ppDChannel = NULL;
  182. /*
  183. // Allocate memory for the object.
  184. */
  185. Result = ALLOCATE_OBJECT(pDChannel, pAdapter->MiniportAdapterHandle);
  186. if (Result == NDIS_STATUS_SUCCESS)
  187. {
  188. /*
  189. // Zero everything to begin with.
  190. // Then set the object type and assign a unique ID .
  191. */
  192. pDChannel->ObjectType = DCHANNEL_OBJECT_TYPE;
  193. pDChannel->ObjectID = ++g_DChannelInstanceCounter;
  194. /*
  195. // Initialize the member variables to their default settings.
  196. */
  197. pDChannel->pAdapter = pAdapter;
  198. // TODO - Add code here to allocate any resources needed to support
  199. // your physical DChannels.
  200. /*
  201. // Parse the registry parameters.
  202. */
  203. Result = DChannelReadParameters(pDChannel);
  204. /*
  205. // If all goes well, we are ready to create the sub-components.
  206. */
  207. if (Result == NDIS_STATUS_SUCCESS)
  208. {
  209. Result = DChannelCreateObjects(pDChannel);
  210. }
  211. if (Result == NDIS_STATUS_SUCCESS)
  212. {
  213. /*
  214. // All is well, so return the object pointer to the caller.
  215. */
  216. *ppDChannel = pDChannel;
  217. }
  218. else
  219. {
  220. /*
  221. // Something went wrong, so let's make sure everything is
  222. // cleaned up.
  223. */
  224. DChannelDestroy(pDChannel);
  225. }
  226. }
  227. DBG_RETURN(pAdapter, Result);
  228. return (Result);
  229. }
  230. /* @doc INTERNAL DChannel DChannel_c DChannelDestroyObjects
  231. @func
  232. <f DChannelDestroyObjects> calls the destroy routines for all the objects
  233. contained in <t DCHANNEL_OBJECT>. This should only be called by
  234. <f DChannelDestroy>.
  235. <f Note>: If you add any new objects to <t PDCHANNEL_OBJECT> you will need to
  236. modify <f DChannelCreateObjects> and <f DChannelDestroyObjects> so they
  237. will get created and destroyed properly.
  238. */
  239. DBG_STATIC void DChannelDestroyObjects(
  240. IN PDCHANNEL_OBJECT pDChannel // @parm
  241. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  242. )
  243. {
  244. DBG_FUNC("DChannelDestroyObjects")
  245. PMINIPORT_ADAPTER_OBJECT pAdapter;
  246. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  247. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  248. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  249. DBG_ENTER(pAdapter);
  250. // TODO - Add code here to release any sub-objects allocated by
  251. // DChannelCreateObjects.
  252. DBG_LEAVE(pAdapter);
  253. }
  254. /* @doc INTERNAL DChannel DChannel_c DChannelDestroy
  255. @func
  256. <f DChannelDestroy> frees the memory for this <t DCHANNEL_OBJECT>.
  257. All memory allocated by <f DChannelCreate> will be released back to the
  258. OS.
  259. */
  260. void DChannelDestroy(
  261. IN PDCHANNEL_OBJECT pDChannel // @parm
  262. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  263. )
  264. {
  265. DBG_FUNC("DChannelDestroy")
  266. PMINIPORT_ADAPTER_OBJECT pAdapter;
  267. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  268. if (pDChannel)
  269. {
  270. ASSERT(pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  271. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  272. DBG_ENTER(pAdapter);
  273. // TODO - Add code here to release any resources allocated by
  274. // DChannelCreate.
  275. /*
  276. // Release all objects allocated within this object.
  277. */
  278. DChannelDestroyObjects(pDChannel);
  279. /*
  280. // Make sure we fail the ASSERT if we see this object again.
  281. */
  282. pDChannel->ObjectType = 0;
  283. FREE_OBJECT(pDChannel);
  284. DBG_LEAVE(pAdapter);
  285. }
  286. }
  287. /* @doc INTERNAL DChannel DChannel_c DChannelInitialize
  288. @func
  289. <f DChannelInitialize> resets all the internal data members contained
  290. in <t BCHANNEL_OBJECT> back to their initial state.
  291. <f Note>:
  292. If you add any new members to <t DCHANNEL_OBJECT> you will need to
  293. modify <f DChannelInitialize> to initialize your new data mamebers.
  294. */
  295. void DChannelInitialize(
  296. IN PDCHANNEL_OBJECT pDChannel // @parm
  297. // A pointer to the <t BCHANNEL_OBJECT> returned by <f DChannelCreate>.
  298. )
  299. {
  300. DBG_FUNC("DChannelInitialize")
  301. PMINIPORT_ADAPTER_OBJECT pAdapter;
  302. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  303. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  304. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  305. DBG_ENTER(pAdapter);
  306. // TODO - Add code here to initialize all the physical D-Channels on
  307. // your adapter.
  308. DBG_LEAVE(pAdapter);
  309. }
  310. /* @doc INTERNAL DChannel DChannel_c DChannelOpen
  311. @func
  312. <f DChannelOpen> establishes a communications path between the miniport
  313. and the DChannel.
  314. @rdesc
  315. <f DChannelOpen> returns zero if it is successful.<nl>
  316. Otherwise, a non-zero return value indicates an error condition.
  317. */
  318. NDIS_STATUS DChannelOpen(
  319. IN PDCHANNEL_OBJECT pDChannel // @parm
  320. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  321. )
  322. {
  323. DBG_FUNC("DChannelOpen")
  324. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  325. // Holds the result code returned by this function.
  326. PMINIPORT_ADAPTER_OBJECT pAdapter;
  327. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  328. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  329. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  330. DBG_ENTER(pAdapter);
  331. if (!pDChannel->IsOpen)
  332. {
  333. DBG_NOTICE(pAdapter,("Opening DChannel #%d\n",
  334. pDChannel->ObjectID));
  335. // TODO - Add code here to open all the physical D-Channels on
  336. // your adapter.
  337. pDChannel->IsOpen = TRUE;
  338. }
  339. else
  340. {
  341. DBG_ERROR(pAdapter,("DChannel #%d already opened\n",
  342. pDChannel->ObjectID));
  343. }
  344. DBG_RETURN(pAdapter, Result);
  345. return (Result);
  346. }
  347. /* @doc INTERNAL DChannel DChannel_c DChannelClose
  348. @func
  349. <f DChannelClose> tears down the communications path between the miniport
  350. and the DChannel.
  351. */
  352. void DChannelClose(
  353. IN PDCHANNEL_OBJECT pDChannel // @parm
  354. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  355. )
  356. {
  357. DBG_FUNC("DChannelClose")
  358. PMINIPORT_ADAPTER_OBJECT pAdapter;
  359. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  360. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  361. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  362. DBG_ENTER(pAdapter);
  363. if (pDChannel->IsOpen)
  364. {
  365. DBG_NOTICE(pAdapter,("Closing DChannel #%d\n",
  366. pDChannel->ObjectID));
  367. // TODO - Add code here to close all the physical D-Channels on
  368. // your adapter.
  369. pDChannel->IsOpen = FALSE;
  370. }
  371. else
  372. {
  373. DBG_WARNING(pAdapter,("DChannel #%d already closed\n",
  374. pDChannel->ObjectID));
  375. }
  376. DBG_LEAVE(pAdapter);
  377. }
  378. /* @doc INTERNAL DChannel DChannel_c DChannelMakeCall
  379. @func
  380. <f DChannelMakeCall> places a call over the selected line device.
  381. @rdesc
  382. <f DChannelMakeCall> returns zero if it is successful.<nl>
  383. Otherwise, a non-zero return value indicates an error condition.
  384. */
  385. NDIS_STATUS DChannelMakeCall(
  386. IN PDCHANNEL_OBJECT pDChannel, // @parm
  387. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  388. IN PBCHANNEL_OBJECT pBChannel, // @parm
  389. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  390. IN PUCHAR DialString, // @parm
  391. // A pointer to an ASCII null-terminated string of digits.
  392. IN USHORT DialStringLength, // @parm
  393. // Number of bytes in dial string.
  394. IN PLINE_CALL_PARAMS pLineCallParams // @parm
  395. // A pointer to the TAPI <t LINE_CALL_PARAMS> to be used for this call.
  396. )
  397. {
  398. DBG_FUNC("DChannelMakeCall")
  399. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  400. // Holds the result code returned by this function.
  401. PMINIPORT_ADAPTER_OBJECT pAdapter;
  402. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  403. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  404. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  405. DBG_ENTER(pAdapter);
  406. ASSERT(pDChannel->IsOpen);
  407. pDChannel->TotalMakeCalls++;
  408. #if defined(SAMPLE_DRIVER)
  409. // This sample code uses the phone number to select one of the other
  410. // BChannels on which to complete the connection.
  411. {
  412. PBCHANNEL_OBJECT pPeerBChannel;
  413. PCARD_EVENT_OBJECT pEvent;
  414. pPeerBChannel = GET_BCHANNEL_FROM_PHONE_NUMBER(DialString);
  415. if (pPeerBChannel)
  416. {
  417. pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
  418. if (pEvent)
  419. {
  420. /*
  421. // Start the call state sequence so we don't leave it in the
  422. // IDLE state.
  423. */
  424. TspiCallStateHandler(pAdapter, pBChannel,
  425. LINECALLSTATE_DIALING,
  426. 0);
  427. /*
  428. // We should get an answer within N seconds if the call has gone
  429. // through.
  430. */
  431. NdisMSetTimer(&pBChannel->CallTimer, pAdapter->NoAnswerTimeOut);
  432. pEvent->ulEventCode = CARD_EVENT_RING;
  433. pEvent->pSendingObject = pBChannel;
  434. pEvent->pReceivingObject = pPeerBChannel;
  435. pBChannel->pPeerBChannel = pPeerBChannel;
  436. CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
  437. }
  438. else
  439. {
  440. Result = NDIS_STATUS_TAPI_RESOURCEUNAVAIL;
  441. }
  442. }
  443. else
  444. {
  445. DBG_ERROR(pAdapter,("Cannot map phone number '%s' to BChannel\n",
  446. DialString));
  447. Result = NDIS_STATUS_TAPI_INVALPARAM;
  448. }
  449. }
  450. #else // SAMPLE_DRIVER
  451. // TODO - Add code here to place a call.
  452. #endif // SAMPLE_DRIVER
  453. if (Result == NDIS_STATUS_SUCCESS)
  454. {
  455. LinkLineUp(pBChannel);
  456. }
  457. DBG_RETURN(pAdapter, Result);
  458. return (Result);
  459. }
  460. /* @doc INTERNAL DChannel DChannel_c DChannelAnswer
  461. @func
  462. <f DChannelAnswer> answers the incoming call so it can be connected.
  463. @rdesc
  464. <f DChannelAnswer> returns zero if it is successful.<nl>
  465. Otherwise, a non-zero return value indicates an error condition.
  466. */
  467. NDIS_STATUS DChannelAnswer(
  468. IN PDCHANNEL_OBJECT pDChannel, // @parm
  469. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  470. IN PBCHANNEL_OBJECT pBChannel // @parm
  471. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  472. )
  473. {
  474. DBG_FUNC("DChannelAnswer")
  475. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  476. // Holds the result code returned by this function.
  477. PMINIPORT_ADAPTER_OBJECT pAdapter;
  478. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  479. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  480. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  481. DBG_ENTER(pAdapter);
  482. ASSERT(pDChannel->IsOpen);
  483. pDChannel->TotalAnswers++;
  484. #if defined(SAMPLE_DRIVER)
  485. // This sample code sends a connect over to the calling BChannel.
  486. {
  487. PCARD_EVENT_OBJECT pEvent;
  488. PBCHANNEL_OBJECT pPeerBChannel = pBChannel->pPeerBChannel;
  489. if (pPeerBChannel)
  490. {
  491. pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
  492. if (pEvent)
  493. {
  494. pEvent->ulEventCode = CARD_EVENT_CONNECT;
  495. pEvent->pSendingObject = pBChannel;
  496. pEvent->pReceivingObject = pPeerBChannel;
  497. CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
  498. // Indicate call connected to the calling channel.
  499. TspiCallStateHandler(pAdapter, pBChannel,
  500. LINECALLSTATE_CONNECTED,
  501. 0);
  502. }
  503. else
  504. {
  505. Result = NDIS_STATUS_TAPI_CALLUNAVAIL;
  506. }
  507. }
  508. else
  509. {
  510. DBG_ERROR(pAdapter,("pPeerBChannel == NULL\n"));
  511. Result = NDIS_STATUS_TAPI_CALLUNAVAIL;
  512. }
  513. }
  514. #else // SAMPLE_DRIVER
  515. // TODO - Add code here to answer a call.
  516. #endif // SAMPLE_DRIVER
  517. if (Result == NDIS_STATUS_SUCCESS)
  518. {
  519. LinkLineUp(pBChannel);
  520. }
  521. DBG_RETURN(pAdapter, Result);
  522. return (Result);
  523. }
  524. /* @doc INTERNAL DChannel DChannel_c DChannelDropCall
  525. @func
  526. <f DChannelDropCall> drops a previously opened call instance. The call
  527. remains open and can be queried after the call is dropped.
  528. @rdesc
  529. <f DChannelDropCall> returns zero if it is successful.<nl>
  530. Otherwise, a non-zero return value indicates an error condition.
  531. */
  532. NDIS_STATUS DChannelDropCall(
  533. IN PDCHANNEL_OBJECT pDChannel, // @parm
  534. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  535. IN PBCHANNEL_OBJECT pBChannel // @parm
  536. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  537. )
  538. {
  539. DBG_FUNC("DChannelDropCall")
  540. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  541. // Holds the result code returned by this function.
  542. PMINIPORT_ADAPTER_OBJECT pAdapter;
  543. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  544. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  545. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  546. DBG_ENTER(pAdapter);
  547. ASSERT(pDChannel->IsOpen);
  548. // Tell NDIS that the link is no longer available.
  549. LinkLineDown(pBChannel);
  550. // This routine may be called several times during line/call cleanup.
  551. // If the call is already closed, just return success.
  552. if (pBChannel->CallState != 0 &&
  553. pBChannel->CallState != LINECALLSTATE_IDLE)
  554. {
  555. #if defined(SAMPLE_DRIVER)
  556. // This sample code sends a disconnect over to the connected BChannel.
  557. PCARD_EVENT_OBJECT pEvent;
  558. PBCHANNEL_OBJECT pPeerBChannel = pBChannel->pPeerBChannel;
  559. if (pPeerBChannel)
  560. {
  561. pEvent = CardEventAllocate(pPeerBChannel->pAdapter->pCard);
  562. if (pEvent)
  563. {
  564. pEvent->ulEventCode = CARD_EVENT_DISCONNECT;
  565. pEvent->pSendingObject = pBChannel;
  566. pEvent->pReceivingObject = pPeerBChannel;
  567. CardNotifyEvent(pPeerBChannel->pAdapter->pCard, pEvent);
  568. }
  569. pBChannel->pPeerBChannel = NULL;
  570. // Indicate call discconect to the calling channel.
  571. TspiCallStateHandler(pAdapter, pBChannel,
  572. LINECALLSTATE_DISCONNECTED,
  573. LINEDISCONNECTMODE_NORMAL);
  574. TspiCallStateHandler(pAdapter, pBChannel,
  575. LINECALLSTATE_IDLE,
  576. 0);
  577. }
  578. else
  579. {
  580. DBG_WARNING(pAdapter,("#%d NO PEER CHANNEL - CALLSTATE=%X\n",
  581. pBChannel->BChannelIndex, pBChannel->CallState));
  582. }
  583. #else // SAMPLE_DRIVER
  584. // TODO - Add code here to drop a call.
  585. #endif // SAMPLE_DRIVER
  586. }
  587. else
  588. {
  589. DBG_NOTICE(pAdapter,("#%d ALREADY IDLE - CALLSTATE=%X\n",
  590. pBChannel->BChannelIndex, pBChannel->CallState));
  591. }
  592. DBG_RETURN(pAdapter, Result);
  593. return (Result);
  594. }
  595. /* @doc INTERNAL DChannel DChannel_c DChannelCloseCall
  596. @func
  597. <f DChannelCloseCall> closes a previously opened call instance as
  598. initiated from <f DChannelMakeCall> or <f DChannelAnswer>. After the
  599. call is closed, no one else should reference it.
  600. @rdesc
  601. <f DChannelCloseCall> returns zero if it is successful.<nl>
  602. Otherwise, a non-zero return value indicates an error condition.
  603. */
  604. NDIS_STATUS DChannelCloseCall(
  605. IN PDCHANNEL_OBJECT pDChannel, // @parm
  606. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  607. IN PBCHANNEL_OBJECT pBChannel // @parm
  608. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  609. )
  610. {
  611. DBG_FUNC("DChannelCloseCall")
  612. NDIS_STATUS Result = NDIS_STATUS_SUCCESS;
  613. // Holds the result code returned by this function.
  614. PMINIPORT_ADAPTER_OBJECT pAdapter;
  615. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  616. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  617. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  618. DBG_ENTER(pAdapter);
  619. ASSERT(pDChannel->IsOpen);
  620. // This routine may be called several times during line/call cleanup.
  621. // If the call is already closed, just return success.
  622. if (pBChannel->CallState != 0)
  623. {
  624. // Make sure the call is dropped before closing.
  625. DChannelDropCall(pDChannel, pBChannel);
  626. pBChannel->CallState = 0;
  627. }
  628. DBG_RETURN(pAdapter, Result);
  629. return (Result);
  630. }
  631. /* @doc INTERNAL DChannel DChannel_c DChannelRejectCall
  632. @func
  633. <f DChannelRejectCall> rejects an incoming call as initiated from a
  634. LINEDEVSTATE_RINGING event sent to <f TspiLineDevStateHandler>.
  635. */
  636. VOID DChannelRejectCall(
  637. IN PDCHANNEL_OBJECT pDChannel, // @parm
  638. // A pointer to the <t DCHANNEL_OBJECT> returned by <f DChannelCreate>.
  639. IN PBCHANNEL_OBJECT pBChannel // @parm
  640. // A pointer to the <t BCHANNEL_OBJECT> returned by <f BChannelCreate>.
  641. )
  642. {
  643. DBG_FUNC("DChannelRejectCall")
  644. PMINIPORT_ADAPTER_OBJECT pAdapter;
  645. // A pointer to the <t MINIPORT_ADAPTER_OBJECT>.
  646. ASSERT(pDChannel && pDChannel->ObjectType == DCHANNEL_OBJECT_TYPE);
  647. pAdapter = GET_ADAPTER_FROM_DCHANNEL(pDChannel);
  648. DBG_ENTER(pAdapter);
  649. // TODO - Add code here to reject an incoming call.
  650. DBG_LEAVE(pAdapter);
  651. }