Leaked source code of windows server 2003
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.

540 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. send.c
  5. Abstract:
  6. This module contains the code that is very specific to initialization
  7. and unload operations in the irenum driver
  8. Author:
  9. Brian Lieuallen, 7-13-2000
  10. Environment:
  11. Kernel mode
  12. Revision History :
  13. --*/
  14. #include "internal.h"
  15. typedef VOID (*CONTROL_CALLBACK)(
  16. PVOID Context,
  17. NTSTATUS Status
  18. );
  19. VOID
  20. SendControlInfo(
  21. CONNECTION_HANDLE ConnectionHandle,
  22. CONTROL_CALLBACK CompletionRoutine,
  23. PVOID Context,
  24. UCHAR PI,
  25. UCHAR PL,
  26. UCHAR *PV
  27. );
  28. VOID
  29. UartStateCompletion(
  30. PVOID Context,
  31. NTSTATUS Status
  32. );
  33. VOID
  34. AccessUartState(
  35. IRDA_HANDLE Handle,
  36. PIRP Irp,
  37. CONNECTION_CALLBACK Callback,
  38. PVOID Context
  39. )
  40. {
  41. PTDI_CONNECTION Connection=Handle;
  42. PIO_STACK_LOCATION IrpSp=IoGetCurrentIrpStackLocation(Irp);
  43. NTSTATUS Status=STATUS_SUCCESS;
  44. CONNECTION_HANDLE ConnectionHandle;
  45. PUCHAR SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
  46. Irp->IoStatus.Information=0;
  47. ADD_REFERENCE_TO_CONNECTION(Connection);
  48. ASSERT(Connection->Uart.CompletionRoutine == NULL);
  49. Connection->Uart.CurrentIrp=Irp;
  50. Connection->Uart.CompletionContext=Context;
  51. Connection->Uart.CompletionRoutine=Callback;
  52. ConnectionHandle=GetCurrentConnection(Connection->LinkHandle);
  53. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  54. case IOCTL_SERIAL_SET_RTS:
  55. case IOCTL_SERIAL_CLR_RTS: {
  56. LONG NewState= IrpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_SERIAL_SET_RTS ? 1 : 0;
  57. LONG OldState;
  58. OldState=InterlockedExchange(&Connection->Uart.RtsState,NewState);
  59. if (NewState != OldState) {
  60. //
  61. // state change
  62. //
  63. UCHAR ControlBuffer[1];
  64. ControlBuffer[0] = PV_DTESetting_Delta_RTS;
  65. ControlBuffer[0] |= NewState ? PV_DTESetting_RTS_High : 0;
  66. ControlBuffer[0] |= Connection->Uart.DtrState ? PV_DTESetting_DTR_High : 0;
  67. Status=STATUS_PENDING;
  68. SendControlInfo(
  69. ConnectionHandle,
  70. UartStateCompletion,
  71. Connection,
  72. PI_DTESettings,
  73. 1,
  74. ControlBuffer
  75. );
  76. }
  77. break;
  78. }
  79. case IOCTL_SERIAL_SET_DTR:
  80. case IOCTL_SERIAL_CLR_DTR: {
  81. LONG NewState= IrpSp->Parameters.DeviceIoControl.IoControlCode==IOCTL_SERIAL_SET_DTR ? 1 : 0;
  82. LONG OldState;
  83. OldState=InterlockedExchange(&Connection->Uart.DtrState,NewState);
  84. if (NewState != OldState) {
  85. //
  86. // state change
  87. //
  88. UCHAR ControlBuffer[1];
  89. ControlBuffer[0] = PV_DTESetting_Delta_DTR;
  90. ControlBuffer[0] |= Connection->Uart.RtsState ? PV_DTESetting_RTS_High : 0;
  91. if (NewState) {
  92. ControlBuffer[0] |= PV_DTESetting_DTR_High;
  93. }
  94. Status=STATUS_PENDING;
  95. SendControlInfo(
  96. ConnectionHandle,
  97. UartStateCompletion,
  98. Connection,
  99. PI_DTESettings,
  100. 1,
  101. ControlBuffer
  102. );
  103. }
  104. break;
  105. }
  106. case IOCTL_SERIAL_GET_DTRRTS:
  107. (*(PULONG)SystemBuffer) = Connection->Uart.DtrState ? SERIAL_DTR_STATE : 0;
  108. (*(PULONG)SystemBuffer) |= Connection->Uart.RtsState ? SERIAL_RTS_STATE : 0;
  109. Irp->IoStatus.Information=sizeof(ULONG);
  110. Status=STATUS_SUCCESS;
  111. break;
  112. case IOCTL_SERIAL_GET_BAUD_RATE:
  113. (*(PULONG)SystemBuffer) = Connection->Uart.BaudRate;
  114. Irp->IoStatus.Information=sizeof(SERIAL_BAUD_RATE);
  115. Status=STATUS_SUCCESS;
  116. break;
  117. case IOCTL_SERIAL_SET_BAUD_RATE: {
  118. ULONG NewRate=(*(PULONG)SystemBuffer);
  119. if (NewRate != Connection->Uart.BaudRate) {
  120. //
  121. // rate change
  122. //
  123. UCHAR ControlBuffer[4];
  124. Connection->Uart.BaudRate=NewRate;
  125. ControlBuffer[0]=(UCHAR)( NewRate >> 24);
  126. ControlBuffer[1]=(UCHAR)( NewRate >> 16);
  127. ControlBuffer[2]=(UCHAR)( NewRate >> 8);
  128. ControlBuffer[3]=(UCHAR)( NewRate >> 0);
  129. Status=STATUS_PENDING;
  130. SendControlInfo(
  131. ConnectionHandle,
  132. UartStateCompletion,
  133. Connection,
  134. PI_DataRate,
  135. 4,
  136. ControlBuffer
  137. );
  138. }
  139. break;
  140. }
  141. case IOCTL_SERIAL_GET_LINE_CONTROL: {
  142. PSERIAL_LINE_CONTROL LineControl=(PSERIAL_LINE_CONTROL)SystemBuffer;
  143. RtlCopyMemory(
  144. LineControl,
  145. &Connection->Uart.LineControl,
  146. sizeof(*LineControl)
  147. );
  148. Irp->IoStatus.Information=sizeof(*LineControl);
  149. Status=STATUS_SUCCESS;
  150. break;
  151. }
  152. case IOCTL_SERIAL_SET_LINE_CONTROL: {
  153. PSERIAL_LINE_CONTROL LineControl=(PSERIAL_LINE_CONTROL)SystemBuffer;
  154. if ((LineControl->StopBits != Connection->Uart.LineControl.StopBits)
  155. ||
  156. (LineControl->Parity != Connection->Uart.LineControl.Parity)
  157. ||
  158. (LineControl->WordLength != Connection->Uart.LineControl.WordLength)
  159. ) {
  160. UCHAR ControlBuffer[1];
  161. RtlCopyMemory(
  162. &Connection->Uart.LineControl,
  163. LineControl,
  164. sizeof(*LineControl)
  165. );
  166. ControlBuffer[0] = (LineControl->WordLength - 5) & 0x03;
  167. ControlBuffer[0] |= (LineControl->Parity == NO_PARITY) ? PV_DataFormat_No_Parity : PV_DataFormat_Yes_Parity;
  168. ControlBuffer[0] |= (LineControl->StopBits == STOP_BIT_1) ? PV_DataFormat_1_Stop : PV_DataFormat_2_Stop;
  169. if (LineControl->Parity != NO_PARITY) {
  170. //
  171. // set the parity type
  172. //
  173. ControlBuffer[0] |= ((LineControl->Parity -1) & 0x03) << 4;
  174. }
  175. Status=STATUS_PENDING;
  176. SendControlInfo(
  177. ConnectionHandle,
  178. UartStateCompletion,
  179. Connection,
  180. PI_DataFormat,
  181. 1,
  182. ControlBuffer
  183. );
  184. }
  185. break;
  186. }
  187. case IOCTL_SERIAL_GET_MODEMSTATUS:
  188. *(PULONG)SystemBuffer=Connection->Uart.ModemStatus;
  189. Irp->IoStatus.Information=sizeof(ULONG);
  190. Status=STATUS_SUCCESS;
  191. break;
  192. default:
  193. ASSERT(0);
  194. Status=STATUS_UNSUCCESSFUL;
  195. break;
  196. }
  197. if (Status != STATUS_PENDING) {
  198. Irp->IoStatus.Status=Status;
  199. UartStateCompletion(
  200. Connection,
  201. Status
  202. );
  203. }
  204. if (ConnectionHandle != NULL) {
  205. ReleaseConnection(ConnectionHandle);
  206. }
  207. return;
  208. }
  209. VOID
  210. UartStateCompletion(
  211. PVOID Context,
  212. NTSTATUS Status
  213. )
  214. {
  215. PTDI_CONNECTION Connection = Context;
  216. CONNECTION_CALLBACK Callback = Connection->Uart.CompletionRoutine;
  217. PVOID UartContext= Connection->Uart.CompletionContext;
  218. PIRP Irp = Connection->Uart.CurrentIrp;
  219. Connection->Uart.CompletionRoutine=NULL;
  220. Irp->IoStatus.Status=Status;
  221. (Callback)(
  222. UartContext,
  223. Irp
  224. );
  225. REMOVE_REFERENCE_TO_CONNECTION(Connection);
  226. return;
  227. }
  228. NTSTATUS
  229. SendControlIrpCompletionRoutine(
  230. PDEVICE_OBJECT DeviceObject,
  231. PIRP BufferIrp,
  232. PVOID Context
  233. )
  234. {
  235. PIRCOMM_BUFFER Buffer=Context;
  236. CONTROL_CALLBACK CompletionRoutine=Buffer->Context2;
  237. PVOID CompletionContext=Buffer->Context;
  238. NTSTATUS Status=BufferIrp->IoStatus.Status;
  239. D_TRACE(DbgPrint("IRCOMM: ControlCompletionRoutine\n");)
  240. Buffer->FreeBuffer(Buffer);
  241. (CompletionRoutine)(
  242. CompletionContext,
  243. Status
  244. );
  245. return STATUS_MORE_PROCESSING_REQUIRED;
  246. }
  247. VOID
  248. SendControlInfo(
  249. CONNECTION_HANDLE ConnectionHandle,
  250. CONTROL_CALLBACK CompletionRoutine,
  251. PVOID Context,
  252. UCHAR PI,
  253. UCHAR PL,
  254. UCHAR *PV
  255. )
  256. {
  257. PFILE_OBJECT FileObject;
  258. PUCHAR Current;
  259. PIRCOMM_BUFFER Buffer;
  260. D_TRACE(
  261. DbgPrint("IRCOMM: send Control, PI=%x, PL=%d, PV= ",PI,PL);
  262. DumpBuffer(PV,PL);
  263. DbgPrint("\n");
  264. )
  265. if (ConnectionHandle == NULL) {
  266. //
  267. // link down
  268. //
  269. (*CompletionRoutine)(
  270. Context,
  271. STATUS_SUCCESS
  272. );
  273. return;
  274. }
  275. Buffer=ConnectionGetBuffer(ConnectionHandle,BUFFER_TYPE_CONTROL);
  276. //
  277. // Make sure the buffer is big enough to actually hold the data that's going
  278. // to be put into it.
  279. //
  280. if (Buffer == NULL || Buffer->BufferLength < ( (ULONG) PL + 3 ) ) {
  281. (*CompletionRoutine)(
  282. Context,
  283. STATUS_INSUFFICIENT_RESOURCES
  284. );
  285. return;
  286. }
  287. FileObject=ConnectionGetFileObject(ConnectionHandle);
  288. //
  289. // actual data starts one byte in, after the length byte
  290. //
  291. Current=&Buffer->Data[1];
  292. *Current=PI;
  293. *(Current+1)=PL;
  294. RtlCopyMemory(
  295. Current+2,
  296. &PV[0],
  297. PL
  298. );
  299. //
  300. // set the length of the control data, 2 bytes for PI and PL plus the length of PV
  301. //
  302. Buffer->Data[0]=2+PL;
  303. //
  304. // Length of the control data plus 1 for the length
  305. //
  306. Buffer->Mdl->ByteCount = Buffer->Data[0] + 1;
  307. Buffer->Context = Context;
  308. Buffer->Context2 = CompletionRoutine;
  309. {
  310. PDEVICE_OBJECT IrdaDeviceObject=IoGetRelatedDeviceObject(FileObject);
  311. ULONG SendLength;
  312. IoReuseIrp(Buffer->Irp,STATUS_SUCCESS);
  313. Buffer->Irp->Tail.Overlay.OriginalFileObject = FileObject;
  314. SendLength = MmGetMdlByteCount(Buffer->Mdl);
  315. TdiBuildSend(
  316. Buffer->Irp,
  317. IrdaDeviceObject,
  318. FileObject,
  319. SendControlIrpCompletionRoutine,
  320. Buffer,
  321. Buffer->Mdl,
  322. 0, // send flags
  323. SendLength
  324. );
  325. IoCallDriver(IrdaDeviceObject, Buffer->Irp);
  326. }
  327. ConnectionReleaseFileObject(ConnectionHandle,FileObject);
  328. return;
  329. }
  330. typedef struct _SYNC_COMPLETION_BLOCK {
  331. KEVENT Event;
  332. NTSTATUS Status;
  333. } SYNC_COMPLETION_BLOCK, *PSYNC_COMPLETION_BLOCK;
  334. VOID
  335. SetEventCompletion(
  336. PVOID Context,
  337. NTSTATUS Status
  338. )
  339. {
  340. PSYNC_COMPLETION_BLOCK CompletionBlock=Context;
  341. D_TRACE(DbgPrint("IRCOMM: SetEventCompletionRoutine\n");)
  342. CompletionBlock->Status=Status;
  343. KeSetEvent(&CompletionBlock->Event,IO_NO_INCREMENT,FALSE);
  344. return;
  345. }
  346. NTSTATUS
  347. SendSynchronousControlInfo(
  348. CONNECTION_HANDLE ConnectionHandle,
  349. UCHAR PI,
  350. UCHAR PL,
  351. UCHAR *PV
  352. )
  353. {
  354. SYNC_COMPLETION_BLOCK CompletionBlock;
  355. KeInitializeEvent(
  356. &CompletionBlock.Event,
  357. NotificationEvent,
  358. FALSE
  359. );
  360. SendControlInfo(
  361. ConnectionHandle,
  362. SetEventCompletion,
  363. &CompletionBlock,
  364. PI,
  365. PL,
  366. PV
  367. );
  368. KeWaitForSingleObject(
  369. &CompletionBlock.Event,
  370. Executive,
  371. KernelMode,
  372. FALSE,
  373. NULL
  374. );
  375. return CompletionBlock.Status;
  376. }