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.

2214 lines
81 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 2000
  3. Module Name:
  4. MsTpAvc.c
  5. Abstract:
  6. Interface code with for issuing external device control commands.
  7. Last changed by:
  8. Author: Yee J. Wu
  9. Environment:
  10. Kernel mode only
  11. Revision History:
  12. $Revision:: $
  13. $Date:: $
  14. --*/
  15. #include "strmini.h"
  16. #include "ksmedia.h"
  17. #include "1394.h"
  18. #include "61883.h"
  19. #include "avc.h"
  20. #include "dbg.h"
  21. #include "MsTpFmt.h"
  22. #include "MsTpDef.h"
  23. #include "MsTpUtil.h"
  24. #include "MsTpAvc.h"
  25. #include "EDevCtrl.h"
  26. PAVCCmdEntry
  27. DVCRFindCmdEntryCompleted(
  28. PDVCR_EXTENSION pDevExt,
  29. DVCR_AVC_COMMAND idxDVCRCmd,
  30. BYTE OpCodeToMatch,
  31. AvcCommandType cmdTypeToMatch
  32. );
  33. NTSTATUS
  34. DVGetExtDeviceProperty(
  35. IN PDVCR_EXTENSION pDevExt,
  36. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  37. OUT PULONG pulActualBytesTransferred
  38. );
  39. NTSTATUS
  40. DVSetExtDeviceProperty(
  41. IN PDVCR_EXTENSION pDevExt,
  42. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  43. OUT ULONG *pulActualBytesTransferred
  44. );
  45. NTSTATUS
  46. DVGetExtTransportProperty(
  47. IN PDVCR_EXTENSION pDevExt,
  48. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  49. OUT ULONG *pulActualBytesTransferred
  50. );
  51. NTSTATUS
  52. DVSetExtTransportProperty(
  53. IN PDVCR_EXTENSION pDevExt,
  54. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  55. OUT ULONG *pulActualBytesTransferred
  56. );
  57. NTSTATUS
  58. DVGetTimecodeReaderProperty(
  59. IN PDVCR_EXTENSION pDevExt,
  60. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  61. OUT PULONG pulActualBytesTransferred
  62. );
  63. NTSTATUS
  64. DVMediaSeekingProperty(
  65. IN PDVCR_EXTENSION pDevExt,
  66. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  67. OUT PULONG pulActualBytesTransferred
  68. );
  69. #if 0 // Enable later
  70. #ifdef ALLOC_PRAGMA
  71. #pragma alloc_text(PAGE, DVCRFindCmdEntryCompleted)
  72. // #pragma alloc_text(PAGE, DVIssueAVCCommand)
  73. #pragma alloc_text(PAGE, DVGetExtDeviceProperty)
  74. #pragma alloc_text(PAGE, DVSetExtDeviceProperty)
  75. #pragma alloc_text(PAGE, DVGetExtTransportProperty)
  76. #pragma alloc_text(PAGE, DVSetExtTransportProperty)
  77. #pragma alloc_text(PAGE, DVGetTimecodeReaderProperty)
  78. #pragma alloc_text(PAGE, DVMediaSeekingProperty)
  79. #pragma alloc_text(PAGE, AVCTapeGetDeviceProperty)
  80. #pragma alloc_text(PAGE, AVCTapeSetDeviceProperty)
  81. #endif
  82. #endif
  83. KSFCP_PACKET DVcrAVCCmdTable[] = {
  84. // ctype subunitaddr opcode operands
  85. { DV_UNIT_INFO, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_DV, 0x30, 0xff, 0xff, 0xff, 0xff, 0xff}
  86. ,{ DV_SUBUNIT_INFO, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_DV, 0x31, 0x07, 0xff, 0xff, 0xff, 0xff}
  87. ,{ DV_CONNECT_AV_MODE, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_DV, 0x20, 0xf0, 0xff, 0xff, 0x20, 0x20}
  88. ,{ DV_VEN_DEP_CANON_MODE, -1, 0, CMD_STATUS, 7, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0x00, 0x00, 0x00, 0x85, 0x00, 0x10, 0x08, 0xff}
  89. ,{ DV_VEN_DEP_DVCPRO, -1, 0, CMD_STATUS, 7, AVC_CTYPE_STATUS, UNIT_TYPE_ID_DV, 0x00, 0x00, 0x80, 0x45, 0x82, 0x48, 0xff, 0xff}
  90. ,{ DV_IN_PLUG_SIGNAL_FMT, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_DV, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff}
  91. ,{ DV_OUT_PLUG_SIGNAL_FMT, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_DV, 0x18, 0x00, 0xff, 0xff, 0xff, 0xff}
  92. ,{ DV_GET_POWER_STATE, -1, 0, CMD_STATUS, 1, AVC_CTYPE_STATUS, UNIT_TYPE_ID_DV, 0xb2, 0x7f}
  93. ,{ DV_SET_POWER_STATE_ON, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_DV, 0xb2, 0x70}
  94. ,{ DV_SET_POWER_STATE_OFF, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_DV, 0xb2, 0x60}
  95. ,{ VCR_TIMECODE_SEARCH, -1, 0, CMD_CONTROL, 5, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x51, 0x20, 0x00, 0x00, 0x00, 0x00}
  96. ,{ VCR_TIMECODE_READ, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0x51, 0x71, 0xff, 0xff, 0xff, 0xff}
  97. ,{ VCR_ATN_SEARCH, -1, 0, CMD_CONTROL, 5, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x52, 0x20, 0x00, 0x00, 0x00, 0x00}
  98. ,{ VCR_ATN_READ, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0x52, 0x71, 0xff, 0xff, 0xff, 0xff}
  99. ,{ VCR_RTC_SEARCH, -1, 0, CMD_CONTROL, 5, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x57, 0x20, 0x00, 0x00, 0x00, 0x00}
  100. ,{ VCR_RTC_READ, -1, 0, CMD_STATUS, 5, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0x57, 0x71, 0xff, 0xff, 0xff, 0xff}
  101. ,{ VCR_OPEN_MIC_CLOSE, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x60, 0x00}
  102. ,{ VCR_OPEN_MIC_READ, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x60, 0x01}
  103. ,{ VCR_OPEN_MIC_WRITE, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x60, 0x03}
  104. ,{ VCR_OPEN_MIC_STATUS, -1, 0, CMD_STATUS, 1, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0x60, 0xff}
  105. ,{ VCR_READ_MIC, -1, 0, CMD_CONTROL, -1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x61}
  106. ,{ VCR_WRITE_MIC, -1, 0, CMD_CONTROL, -1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0x62}
  107. ,{ VCR_OUTPUT_SIGNAL_MODE, -1, 0, CMD_STATUS, 1, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0x78, 0xff}
  108. ,{ VCR_INPUT_SIGNAL_MODE, -1, 0, CMD_STATUS, 1, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0x79, 0xff}
  109. ,{ VCR_LOAD_MEDIUM_EJECT, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc1, 0x60}
  110. ,{ VCR_RECORD, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc2, 0x75}
  111. ,{ VCR_RECORD_PAUSE, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc2, 0x7d}
  112. ,{ VCR_PLAY_FORWARD_STEP, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x30} // 00=AVC, 20=VCR, c3=Opcode, 30=Operand[0]
  113. ,{ VCR_PLAY_FORWARD_SLOWEST, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x31}
  114. ,{ VCR_PLAY_FORWARD_SLOWEST2, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x33}
  115. ,{ VCR_PLAY_FORWARD_FASTEST, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x3f}
  116. ,{ VCR_PLAY_REVERSE_STEP, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x40}
  117. ,{ VCR_PLAY_REVERSE_SLOWEST, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x41}
  118. ,{ VCR_PLAY_REVERSE_SLOWEST2, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x43}
  119. ,{ VCR_PLAY_REVERSE_FASTEST, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x4f}
  120. ,{ VCR_PLAY_FORWARD, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x75}
  121. ,{ VCR_PLAY_FORWARD_PAUSE, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc3, 0x7d}
  122. ,{ VCR_WIND_STOP, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc4, 0x60}
  123. ,{ VCR_WIND_REWIND, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc4, 0x65}
  124. ,{ VCR_WIND_FAST_FORWARD, -1, 0, CMD_CONTROL, 1, AVC_CTYPE_CONTROL,UNIT_TYPE_ID_VCR, 0xc4, 0x75}
  125. ,{ VCR_TRANSPORT_STATE, -1, 0, CMD_STATUS, 1, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0xd0, 0x7f}
  126. ,{ VCR_TRANSPORT_STATE_NOTIFY, -1, 0, CMD_NOTIFY, 1, AVC_CTYPE_NOTIFY, UNIT_TYPE_ID_VCR, 0xd0, 0x7f}
  127. ,{ VCR_MEDIUM_INFO, -1, 0, CMD_STATUS, 2, AVC_CTYPE_STATUS, UNIT_TYPE_ID_VCR, 0xda, 0x7f,0x7f}
  128. ,{ VCR_RAW_AVC, 1, 0, CMD_CONTROL | CMD_STATUS | CMD_NOTIFY | CMD_SPEC_INQ | CMD_GEN_INQ, 0}
  129. };
  130. void
  131. DVCRXlateGetMediumInfo(
  132. PMEDIUM_INFO pMediumInfo,
  133. PBYTE pbOperand0,
  134. PBYTE pbOperand1
  135. )
  136. {
  137. TRACE(TL_FCP_TRACE,("GetMediumInfo: Type:%x; WriteProtect:%x\n", *pbOperand0, *pbOperand1));
  138. switch(*pbOperand0) {
  139. // Support for DigitalHi8; if we get this query, we treat DHi8 as a mini DV tape.
  140. case 0x12: // DHi8
  141. case 0x31:// DVCR standard cassette
  142. case 0x32:// DVCR small cassette
  143. case 0x33:// DVCR medium cassette
  144. pMediumInfo->MediaPresent = TRUE;
  145. pMediumInfo->MediaType = ED_MEDIA_DVC;
  146. pMediumInfo->RecordInhibit = (*pbOperand1 & 0x01) == 0x01;
  147. break;
  148. case 0x22: // VHS cassette
  149. pMediumInfo->MediaPresent = TRUE;
  150. pMediumInfo->MediaType = ED_MEDIA_VHS;
  151. pMediumInfo->RecordInhibit = (*pbOperand1 & 0x01) == 0x01;
  152. break;
  153. case 0x23:
  154. pMediumInfo->MediaPresent = TRUE;
  155. pMediumInfo->MediaType = ED_MEDIA_VHSC;
  156. pMediumInfo->RecordInhibit = (*pbOperand1 & 0x01) == 0x01;
  157. break;
  158. case 0x60:
  159. pMediumInfo->MediaPresent = FALSE;
  160. pMediumInfo->MediaType = ED_MEDIA_NOT_PRESENT;
  161. pMediumInfo->RecordInhibit = TRUE; // Cannot record if there is no tape.
  162. break;
  163. case 0x7e:
  164. pMediumInfo->MediaPresent = TRUE;
  165. pMediumInfo->MediaType = ED_MEDIA_UNKNOWN;
  166. pMediumInfo->RecordInhibit = TRUE; // Actually cannot be determined
  167. break;
  168. // Sony's NEO device
  169. case 0x41:
  170. pMediumInfo->MediaPresent = TRUE;
  171. pMediumInfo->MediaType = ED_MEDIA_NEO;
  172. pMediumInfo->RecordInhibit = (*pbOperand1 & 0x01) == 0x01;
  173. break;
  174. default:
  175. pMediumInfo->MediaPresent = TRUE;
  176. pMediumInfo->MediaType = ED_MEDIA_UNKNOWN;
  177. pMediumInfo->RecordInhibit = TRUE;
  178. break;
  179. }
  180. // Reset command opcode/operands
  181. *pbOperand0 = 0x7f;
  182. *pbOperand1 = 0x7f;
  183. }
  184. void
  185. DVCRXlateGetTransportState(
  186. PTRANSPORT_STATE pXPrtState,
  187. PBYTE pbOpcode,
  188. PBYTE pbOperand0
  189. )
  190. {
  191. TRACE(TL_FCP_TRACE,("XlateGetTransportState: OpCode %x, Operand %x\n", *pbOpcode, *pbOperand0));
  192. switch(*pbOpcode) {
  193. case OPC_LOAD_MEDIUM:
  194. pXPrtState->Mode = ED_MEDIA_UNLOAD;
  195. ASSERT(*pbOperand0 == 0x60);
  196. break;
  197. case OPC_RECORD:
  198. pXPrtState->Mode = ED_MODE_RECORD;
  199. switch(*pbOperand0) {
  200. case 0x75: // RECORD
  201. pXPrtState->State = ED_MODE_RECORD;
  202. break;
  203. case 0x7d: // RECORD_FREEZE
  204. pXPrtState->State = ED_MODE_RECORD_FREEZE;
  205. break;
  206. default:
  207. ASSERT(FALSE && "OPC_RECORD: Operand0 undefined!");
  208. break;
  209. }
  210. break;
  211. case OPC_PLAY:
  212. pXPrtState->Mode = ED_MODE_PLAY;
  213. switch(*pbOperand0) {
  214. case 0x30: // NEXT FRAME
  215. pXPrtState->State = ED_MODE_STEP_FWD;
  216. break;
  217. case 0x31: // SLOWEST FORWARD
  218. case 0x32: // SLOW FORWARD 6
  219. case 0x33: // SLOW FORWARD 5
  220. case 0x34: // SLOW FORWARD 4
  221. case 0x35: // SLOW FORWARD 3
  222. case 0x36: // SLOW FORWARD 2
  223. case 0x37: // SLOW FORWARD 1
  224. pXPrtState->State = ED_MODE_PLAY_SLOWEST_FWD;
  225. break;
  226. case 0x38: // PLAY FORWARD 1
  227. pXPrtState->State = ED_MODE_PLAY;
  228. break;
  229. case 0x39: // FAST FORWARD 1
  230. case 0x3a: // FAST FORWARD 2
  231. case 0x3b: // FAST FORWARD 3
  232. case 0x3c: // FAST FORWARD 4
  233. case 0x3d: // FAST FORWARD 5
  234. case 0x3e: // FAST FORWARD 6
  235. case 0x3f: // FASTEST FORWARD
  236. pXPrtState->State = ED_MODE_PLAY_FASTEST_FWD;
  237. break;
  238. case 0x40: // PREVIOUS FRAME
  239. pXPrtState->State = ED_MODE_STEP_REV;
  240. break;
  241. case 0x41: // SLOWEST REVERSE
  242. case 0x42: // SLOW REVERSE 6
  243. case 0x43: // SLOW REVERSE 5
  244. case 0x44: // SLOW REVERSE 4
  245. case 0x45: // SLOW REVERSE 3
  246. case 0x46: // SLOW REVERSE 2
  247. case 0x47: // SLOW REVERSE 1
  248. pXPrtState->State = ED_MODE_PLAY_SLOWEST_REV;
  249. break;
  250. case 0x48: // X1 REVERSE
  251. case 0x65: // REVERSE
  252. pXPrtState->State = ED_MODE_REV_PLAY;
  253. break;
  254. case 0x49: // FAST REVERSE 1
  255. case 0x4a: // FAST REVERSE 2
  256. case 0x4b: // FAST REVERSE 3
  257. case 0x4c: // FAST REVERSE 4
  258. case 0x4d: // FAST REVERSE 5
  259. case 0x4e: // FAST REVERSE 6
  260. case 0x4f: // FASTEST REVERSE
  261. pXPrtState->State = ED_MODE_PLAY_FASTEST_REV;
  262. break;
  263. case 0x75: // FORWARD
  264. pXPrtState->State = ED_MODE_PLAY;
  265. break;
  266. case 0x6d: // REVERSE PAUSE
  267. case 0x7d: // FORWARD PAUSE
  268. pXPrtState->State = ED_MODE_FREEZE;
  269. break;
  270. default:
  271. pXPrtState->State = 0;
  272. ASSERT(FALSE && "OPC_PLAY: Operand0 undefined!");
  273. break;
  274. }
  275. break;
  276. case OPC_WIND:
  277. //pXPrtState->Mode = ED_MODE_WIND;
  278. switch(*pbOperand0) {
  279. case 0x45: // HIGH SPEED REWIND
  280. pXPrtState->State = ED_MODE_REW_FASTEST;
  281. break;
  282. case 0x60: // STOP
  283. pXPrtState->State = ED_MODE_STOP;
  284. break;
  285. case 0x65: // REWIND
  286. pXPrtState->State = ED_MODE_REW;
  287. break;
  288. case 0x75: // FAST FORWARD
  289. pXPrtState->State = ED_MODE_FF;
  290. break;
  291. default:
  292. TRACE(TL_FCP_ERROR,("XlateGetTransportState: OPC_WIND with unknown operand0 %x\n", *pbOperand0));
  293. break;
  294. }
  295. // Thre is not a state defined for WIND
  296. pXPrtState->Mode = pXPrtState->State;
  297. break;
  298. case OPC_TRANSPORT_STATE: // As a result of the notify command
  299. break;
  300. default:
  301. ASSERT(FALSE && "OpCode undefined!");
  302. break;
  303. }
  304. // Reset command opcode/operands
  305. *pbOpcode = 0xd0;
  306. *pbOperand0 = 0x7f;
  307. }
  308. void
  309. DVCRXlateGetIOSignalMode(
  310. PULONG pIOSignalMode,
  311. PBYTE pbOperand0
  312. )
  313. {
  314. TRACE(TL_FCP_WARNING,("IOSignalMode: IoSignal:%x\n", *pbOperand0));
  315. switch(*pbOperand0) {
  316. case 0x00: // SD 525-60
  317. case 0x06: // Analog 8mm NTSC
  318. case 0x0e: // Analog Hi8 NTSC
  319. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_525_60_SD;
  320. break;
  321. case 0x04: // SDL 525-60
  322. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_525_60_SDL;
  323. break;
  324. case 0x80: // SD 625-50
  325. case 0x86: // Analog 8mm NTSC
  326. case 0x8e: // Analog Hi8 NTSC
  327. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_625_50_SD;
  328. break;
  329. case 0x84: // SDL 625-50
  330. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_625_50_SDL;
  331. break;
  332. // Various MPEG2 format
  333. case 0x05: // Analog VHS NTSC 525/60
  334. case 0x25: // Analog VHS M-NTSC 525/60
  335. case 0xA5: // Analog VHS PAL 625/50
  336. case 0xB5: // Analog VHS M-PAL 625/50
  337. case 0xC5: // Analog VHS SECAM 625/50
  338. case 0xD5: // Analog VHS ME-SECAM 625/50
  339. case 0x01: // D-VHS
  340. case 0x0d: // Analob S-VHS 525/60
  341. case 0xed: // Analog S-VHS 625/50
  342. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_MPEG2TS;
  343. break;
  344. case 0x10: // MPEG 25 Mbps-60
  345. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_2500_60_MPEG;
  346. break;
  347. case 0x14: // MPEG 12.5 Mbps-60
  348. case 0x24: // MPEG 12.5 Mbps-60 (NEO)
  349. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_1250_60_MPEG;
  350. break;
  351. case 0x18: // MPEG 6.25Mbps-60
  352. case 0x28: // MPEG 6.25Mbps-60 (NEO)
  353. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_0625_60_MPEG;
  354. break;
  355. case 0x90: // MPEG 25Mbps-50
  356. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_2500_50_MPEG;
  357. break;
  358. case 0x94: // MPEG 12.5Mbps-50
  359. case 0xa4: // MPEG 12.5Mbps-50 (NEO)
  360. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_1250_50_MPEG;
  361. break;
  362. case 0x98: // MPEG 6.25Mbps-50
  363. case 0xa8: // MPEG 6.25Mbps-50 (NEO)
  364. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_0625_50_MPEG;
  365. break;
  366. case 0x0f: // Unknown data
  367. *pIOSignalMode = ED_TRANSBASIC_SIGNAL_UNKNOWN;
  368. break;
  369. default:
  370. // This driver does not understand other format;
  371. TRACE(TL_FCP_ERROR,("Unknown IoSignal:%x\n", *pbOperand0));
  372. ASSERT(FALSE && "Unknown IoSignal!");
  373. break;
  374. }
  375. // Reset command opcode/operands
  376. *pbOperand0 = 0xff;
  377. }
  378. NTSTATUS
  379. DVCRXlateRAwAVC(
  380. PAVCCmdEntry pCmdEntry,
  381. PVOID pProperty
  382. )
  383. {
  384. PAVC_COMMAND_IRB pAvcIrb = pCmdEntry->pAvcIrb;
  385. UCHAR ucRespCode = pAvcIrb->ResponseCode;
  386. NTSTATUS Status;
  387. PUCHAR pbRtnBuf;
  388. PKSPROPERTY_EXTDEVICE_S pXDevProperty;
  389. PKSPROPERTY_EXTXPORT_S pXPrtProperty;
  390. PKSPROPERTY_TIMECODE_S pTmCdReaderProperty;
  391. if(STATUS_SUCCESS != pCmdEntry->Status) {
  392. TRACE(TL_FCP_ERROR,("XlateRAwAVC: Status:%x\n", pCmdEntry->Status));
  393. return pCmdEntry->Status;
  394. }
  395. switch (pCmdEntry->idxDVCRCmd) {
  396. case DV_UNIT_INFO:
  397. pbRtnBuf = (PBYTE) pProperty;
  398. memcpy(pbRtnBuf, pAvcIrb->Operands+1, 4);
  399. break;
  400. case DV_SUBUNIT_INFO:
  401. case DV_IN_PLUG_SIGNAL_FMT:
  402. case DV_OUT_PLUG_SIGNAL_FMT:
  403. pbRtnBuf = (PBYTE) pProperty;
  404. memcpy(pbRtnBuf, pAvcIrb->Operands+1, 4);
  405. break;
  406. // special case, return the response code in the first byte
  407. case DV_CONNECT_AV_MODE:
  408. pbRtnBuf = (PBYTE) pProperty;
  409. pbRtnBuf[0] = ucRespCode;
  410. memcpy(&pbRtnBuf[1], pAvcIrb->Operands, 5);
  411. break;
  412. // special case, return the response code in the first byte
  413. case DV_VEN_DEP_CANON_MODE:
  414. pbRtnBuf = (PBYTE) pProperty;
  415. pbRtnBuf[0] = ucRespCode;
  416. memcpy(&pbRtnBuf[1], pAvcIrb->Operands, 7);
  417. break;
  418. case DV_GET_POWER_STATE:
  419. pXDevProperty = (PKSPROPERTY_EXTDEVICE_S) pProperty;
  420. TRACE(TL_FCP_WARNING,("GET_POWER_STATE: OperandsStatus:%x\n", pAvcIrb->Operands[0]));
  421. switch(pAvcIrb->Operands[0]) {
  422. case AVC_POWER_STATE_OFF: // 0x60
  423. // If the device is OFF, it cannot give us this response so it must be in standby mode.
  424. pXDevProperty->u.PowerState = ED_POWER_OFF;
  425. break;
  426. case AVC_POWER_STATE_ON: // 0x70
  427. pXDevProperty->u.PowerState = ED_POWER_ON;
  428. break;
  429. default:
  430. // If it is not ON or OFF, we "guess" it is a new power state of "Standby".
  431. pXDevProperty->u.PowerState = ED_POWER_STANDBY;
  432. break;
  433. }
  434. break;
  435. case VCR_TIMECODE_READ:
  436. pTmCdReaderProperty = (PKSPROPERTY_TIMECODE_S) pProperty;
  437. if(pAvcIrb->Operands[1] == 0xff ||
  438. pAvcIrb->Operands[2] == 0xff ||
  439. pAvcIrb->Operands[3] == 0xff ||
  440. pAvcIrb->Operands[4] == 0xff ) {
  441. TRACE(TL_FCP_ERROR,("TimeCodeRead: %.2x:%.2x:%.2x,%.2x\n", pAvcIrb->Operands[4], pAvcIrb->Operands[3], pAvcIrb->Operands[2], pAvcIrb->Operands[1]));
  442. // Even though command succeded, but the data is not valid!
  443. Status = STATUS_UNSUCCESSFUL;
  444. } else {
  445. // bswap them.
  446. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames =
  447. (((DWORD) pAvcIrb->Operands[4]) << 24) |
  448. (((DWORD) pAvcIrb->Operands[3]) << 16) |
  449. (((DWORD) pAvcIrb->Operands[2]) << 8) |
  450. ((DWORD) pAvcIrb->Operands[1]);
  451. TRACE(TL_FCP_TRACE,("TimeCodeRead: %.2x:%.2x:%.2x,%.2x\n", pAvcIrb->Operands[4], pAvcIrb->Operands[3], pAvcIrb->Operands[2], pAvcIrb->Operands[1]));
  452. }
  453. break;
  454. case VCR_RTC_READ:
  455. pTmCdReaderProperty = (PKSPROPERTY_TIMECODE_S) pProperty;
  456. if(// 0xFF is valid for RTC: pAvcIrb->Operands[1] == 0xff ||
  457. pAvcIrb->Operands[2] == 0xff ||
  458. pAvcIrb->Operands[3] == 0xff ||
  459. pAvcIrb->Operands[4] == 0xff ) {
  460. TRACE(TL_FCP_ERROR,("RTC_Read: %.2x:%.2x:%.2x,%.2x\n", pAvcIrb->Operands[4], pAvcIrb->Operands[3], pAvcIrb->Operands[2], pAvcIrb->Operands[1]));
  461. // Even though command succeded, but the data is not valid!
  462. Status = STATUS_UNSUCCESSFUL;
  463. } else {
  464. // bswap them.
  465. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames =
  466. (((DWORD) pAvcIrb->Operands[4]) << 24) |
  467. (((DWORD) pAvcIrb->Operands[3]) << 16) |
  468. (((DWORD) pAvcIrb->Operands[2]) << 8) |
  469. ((DWORD) pAvcIrb->Operands[1]);
  470. TRACE(TL_FCP_TRACE,("RTC_Read: %.2x:%.2x:%.2x,%.2x\n", pAvcIrb->Operands[4], pAvcIrb->Operands[3], pAvcIrb->Operands[2], pAvcIrb->Operands[1]));
  471. }
  472. break;
  473. case VCR_ATN_READ:
  474. pTmCdReaderProperty = (PKSPROPERTY_TIMECODE_S) pProperty;
  475. if(pAvcIrb->Operands[1] == 0x00 &&
  476. pAvcIrb->Operands[2] == 0x00 &&
  477. pAvcIrb->Operands[3] == 0x00 ) {
  478. // Even though command succeded, but the data is not valid!
  479. Status = STATUS_UNSUCCESSFUL;
  480. } else {
  481. #define MEDIUM_TYPE_MASK 0xf8 // 11111000b
  482. #define MEDIUM_TYPE_DVHS 0x08 // 00001000b
  483. #define MEDIUM_TYPE_DVCR 0xf8 // 11111000b
  484. #define MEDIUM_TYPE_NEO 0x10 // 00010000b
  485. switch(pAvcIrb->Operands[4] & MEDIUM_TYPE_MASK) {
  486. case MEDIUM_TYPE_DVCR:
  487. pTmCdReaderProperty->TimecodeSamp.dwUser =
  488. pAvcIrb->Operands[1] & 0x01; // Get the Blank flag
  489. // bswap them.
  490. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames =
  491. ( (((DWORD) pAvcIrb->Operands[3]) << 16) |
  492. (((DWORD) pAvcIrb->Operands[2]) << 8) |
  493. (((DWORD) pAvcIrb->Operands[1]))
  494. ) >> 1;
  495. break;
  496. case MEDIUM_TYPE_DVHS:
  497. pTmCdReaderProperty->TimecodeSamp.dwUser =
  498. (pAvcIrb->Operands[1] >> 6) & 0x03; // Get the SF
  499. // bswap them.
  500. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames =
  501. ( (((DWORD) (pAvcIrb->Operands[1] & 0x3f)) << 16) |
  502. (((DWORD) pAvcIrb->Operands[2]) << 8) |
  503. (((DWORD) pAvcIrb->Operands[3]))
  504. );
  505. break;
  506. case MEDIUM_TYPE_NEO:
  507. pTmCdReaderProperty->TimecodeSamp.dwUser =
  508. (pAvcIrb->Operands[3] >> 7) & 0x01; // Get the Blank flag
  509. // bswap them.
  510. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames =
  511. ( (((DWORD) (pAvcIrb->Operands[3] & 0x7f)) << 16) |
  512. (((DWORD) pAvcIrb->Operands[2]) << 8) |
  513. (((DWORD) pAvcIrb->Operands[1]))
  514. );
  515. TRACE(TL_FCP_TRACE, ("ATN (NEO):bf:%d ATN:%d\n",
  516. pTmCdReaderProperty->TimecodeSamp.dwUser,
  517. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames
  518. ));
  519. break;
  520. default:
  521. // Unknown medium type
  522. Status = STATUS_UNSUCCESSFUL;
  523. TRACE(TL_FCP_ERROR, ("Operand4:%x; Unknown Medium type for ATN: %x\n",
  524. pAvcIrb->Operands[4], pAvcIrb->Operands[4] & MEDIUM_TYPE_MASK));
  525. break;
  526. }
  527. }
  528. break;
  529. case VCR_INPUT_SIGNAL_MODE:
  530. case VCR_OUTPUT_SIGNAL_MODE:
  531. pXPrtProperty = (PKSPROPERTY_EXTXPORT_S) pProperty;
  532. DVCRXlateGetIOSignalMode(&pXPrtProperty->u.SignalMode, &pAvcIrb->Operands[0]);
  533. break;
  534. case VCR_TRANSPORT_STATE:
  535. case VCR_TRANSPORT_STATE_NOTIFY:
  536. pXPrtProperty = (PKSPROPERTY_EXTXPORT_S) pProperty;
  537. DVCRXlateGetTransportState(&pXPrtProperty->u.XPrtState, &pAvcIrb->Opcode, &pAvcIrb->Operands[0]);
  538. break;
  539. case VCR_MEDIUM_INFO:
  540. pXPrtProperty = (PKSPROPERTY_EXTXPORT_S) pProperty;
  541. DVCRXlateGetMediumInfo(&pXPrtProperty->u.MediumInfo, &pAvcIrb->Operands[0], &pAvcIrb->Operands[1]);
  542. break;
  543. case VCR_RAW_AVC:
  544. // Do nothing.
  545. break;
  546. default:
  547. // No translation necessary
  548. TRACE(TL_FCP_TRACE,("No tranlsation: pCmdEntry:%x; idx:%d\n", pCmdEntry, pCmdEntry->idxDVCRCmd));
  549. break;
  550. }
  551. return pCmdEntry->Status;
  552. }
  553. PAVCCmdEntry
  554. DVCRFindCmdEntryCompleted(
  555. PDVCR_EXTENSION pDevExt,
  556. DVCR_AVC_COMMAND idxDVCRCmd,
  557. BYTE OpCodeToMatch,
  558. AvcCommandType cmdTypeToMatch
  559. )
  560. /*++
  561. Routine Description:
  562. Arguments:
  563. Return Value:
  564. PLIST_ENTRY
  565. --*/
  566. {
  567. LIST_ENTRY *pEntry;
  568. KIRQL OldIrql;
  569. PAGED_CODE();
  570. //
  571. // Special case:
  572. //
  573. // ATN: Status 01 20 52; Control 00 20 52
  574. // (resp) 0c 20 52 0f 20 52 (CtrlInterim)
  575. //
  576. // XPrtState: Status 01 20 d0; Notify 03 20 d0
  577. // (resp) 0c 20 xx 0f 20 xx xx (NotifyInterim)
  578. //
  579. // Summary: if we keep cmdType and OpCode, it is unique.
  580. //
  581. KeAcquireSpinLock(&pDevExt->AVCCmdLock, &OldIrql);
  582. pEntry = pDevExt->AVCCmdList.Flink;
  583. while(pEntry != &pDevExt->AVCCmdList) {
  584. PAVCCmdEntry pCmdEntry = (PAVCCmdEntry)pEntry;
  585. if (pCmdEntry->idxDVCRCmd == idxDVCRCmd) {
  586. //
  587. // We only fetch if it is completed!
  588. //
  589. if(pCmdEntry->cmdState != CMD_STATE_ISSUED) {
  590. if (pCmdEntry->cmdType == cmdTypeToMatch) {
  591. // Control/GenInq/SpecInq: OpCode and Operand[n] remina unchanged.
  592. if (pCmdEntry->OpCode == OpCodeToMatch) {
  593. TRACE(TL_FCP_TRACE,("FindCmdEntryCompleted: (1) Found pCmdEntry:%x (%x, %x, %x)\n",
  594. pCmdEntry, pCmdEntry->pAvcIrb, cmdTypeToMatch, OpCodeToMatch));
  595. RemoveEntryList(&pCmdEntry->ListEntry); pDevExt->cntCommandQueued--;
  596. InitializeListHead(&pCmdEntry->ListEntry); // used as a flag for ownership
  597. #if DBG
  598. // pIrp should be NULL (completed).
  599. if(pCmdEntry->pIrp) {
  600. TRACE(TL_FCP_ERROR,("Error: FindCmdEntry: pCmdEntry:%x; pIrp:%x not completed\n", pCmdEntry, pCmdEntry->pIrp));
  601. }
  602. #endif
  603. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  604. return pCmdEntry; // Found
  605. }
  606. } else {
  607. TRACE(TL_FCP_WARNING,("FindCmdEntryCompleted: cmdType %x != %x\n", pCmdEntry->cmdType, cmdTypeToMatch));
  608. }
  609. }
  610. else {
  611. TRACE(TL_FCP_TRACE,("FindCmdEntryCompleted: (0) Skip %x not completed (%x, %x) match entry %x\n",
  612. pCmdEntry, cmdTypeToMatch, OpCodeToMatch));
  613. }
  614. }
  615. pEntry = pEntry->Flink;
  616. }
  617. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  618. TRACE(TL_FCP_TRACE,("FindCmdEntryCompleted: (a) No match\n"));
  619. return NULL; // No match
  620. }
  621. void
  622. DVAVCCmdResetAfterBusReset(
  623. PDVCR_EXTENSION pDevExt
  624. )
  625. /*++
  626. Routine Description:
  627. Arguments:
  628. Return Value:
  629. Nothing
  630. --*/
  631. {
  632. KIRQL OldIrql;
  633. KeAcquireSpinLock(&pDevExt->AVCCmdLock, &OldIrql);
  634. TRACE(TL_FCP_TRACE,("BusReset: <enter> AVCCmd [completed %d]; CmdList:%x\n", pDevExt->cntCommandQueued, pDevExt->AVCCmdList));
  635. // Clear the command list
  636. while (!IsListEmpty(&pDevExt->AVCCmdList)) {
  637. PAVCCmdEntry pCmdEntry = (PAVCCmdEntry)RemoveHeadList(&pDevExt->AVCCmdList); pDevExt->cntCommandQueued--;
  638. InitializeListHead(&pCmdEntry->ListEntry);
  639. TRACE(TL_FCP_TRACE,("BusReset: AbortAVC: Completed:%d; pCmdEntry:%x; cmdState:%d; cmdSt:%x\n",
  640. pDevExt->cntCommandQueued, pCmdEntry, pCmdEntry->cmdState, pCmdEntry->Status));
  641. switch(pCmdEntry->cmdState) {
  642. case CMD_STATE_ISSUED:
  643. case CMD_STATE_RESP_INTERIM: // AVC.sys may still has it!
  644. TRACE(TL_FCP_WARNING,("BusReset: AbortAVC: IoCancelIrp(%x)!\n", pCmdEntry->pIrp));
  645. ASSERT(pCmdEntry->pIrp != NULL);
  646. IoCancelIrp(pCmdEntry->pIrp); // Calls DVIssueAVCCommandCR() with pIrp->Cancel
  647. break;
  648. // Completed command
  649. case CMD_STATE_UNDEFINED:
  650. TRACE(TL_FCP_ERROR,("AVCCmdResetAfterBusReset: Unexpected CMD state %d; pCmdEntry %x\n", pCmdEntry->cmdState, pCmdEntry));
  651. case CMD_STATE_RESP_ACCEPTED:
  652. case CMD_STATE_RESP_REJECTED:
  653. case CMD_STATE_RESP_NOT_IMPL:
  654. case CMD_STATE_ABORTED:
  655. break;
  656. default:
  657. TRACE(TL_FCP_ERROR,("AVCCmdResetAfterBusReset: Unknown CMD state %d; pCmdEntry %x\n", pCmdEntry->cmdState, pCmdEntry));
  658. ASSERT(FALSE && "Unknown cmdState\n");
  659. break;
  660. }
  661. // We are guaranteed at this point that no one needs the
  662. // results anymore so we will free the resources.
  663. ExFreePool(pCmdEntry->pAvcIrb);
  664. ExFreePool(pCmdEntry);
  665. }
  666. #if DBG
  667. //
  668. // Should have no more entry !
  669. //
  670. if(pDevExt->cntCommandQueued != 0) {
  671. TRACE(TL_FCP_ERROR,("BusReset: <exit> AVCCmd [completed %d]; CmdList:%x\n", pDevExt->cntCommandQueued, pDevExt->AVCCmdList));
  672. ASSERT(pDevExt->cntCommandQueued == 0);
  673. }
  674. #endif
  675. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  676. }
  677. NTSTATUS
  678. DVIssueAVCCommandCR(
  679. IN PDEVICE_OBJECT DeviceObject,
  680. IN PIRP pIrp,
  681. IN PAVCCmdEntry pCmdEntry
  682. )
  683. /*++
  684. Routine Description:
  685. This is the completion routine for the AVC command when it is completed which imply that
  686. the interim response will not be called here.
  687. Arguments:
  688. Note: pCmdEntry cannot be used if pIrp->Cancel.
  689. Return Value:
  690. Always STATUS_MORE_PROCESSING_REQUIRED.
  691. Note: the real return is in pCmdEntry->Status.
  692. --*/
  693. {
  694. KIRQL oldIrql;
  695. if (!pIrp->Cancel) {
  696. PDVCR_EXTENSION pDevExt = pCmdEntry->pDevExt;
  697. BOOL bSignalInterimCotrolCompleted = FALSE;
  698. BOOL bSignalInterimNotifyCompleted = FALSE;
  699. PKSEVENT_ENTRY pEvent;
  700. // Serialize AVC command response processing
  701. KeAcquireSpinLock(&pDevExt->AVCCmdLock, &oldIrql);
  702. ASSERT(pCmdEntry->pIrp == pIrp);
  703. pCmdEntry->pIrp = NULL; // don't need this anymore
  704. // Check if it's worthwhile to examine the response buffer
  705. if (STATUS_SUCCESS == pIrp->IoStatus.Status) {
  706. PAVC_COMMAND_IRB pAvcIrb = pCmdEntry->pAvcIrb;
  707. // Check Opcode for return state
  708. switch(pAvcIrb->ResponseCode) {
  709. case AVC_RESPONSE_NOTIMPL:
  710. pCmdEntry->cmdState = CMD_STATE_RESP_NOT_IMPL;
  711. pCmdEntry->Status = STATUS_NOT_SUPPORTED; // -> ERROR_NOT_SUPPORTED
  712. break;
  713. case AVC_RESPONSE_ACCEPTED:
  714. if(pCmdEntry->cmdState == CMD_STATE_RESP_INTERIM) {
  715. if(pCmdEntry->cmdType == AVC_CTYPE_CONTROL) {
  716. bSignalInterimCotrolCompleted = TRUE;
  717. TRACE(TL_FCP_TRACE,("--> Accept: for control interim\n"));
  718. } else {
  719. TRACE(TL_FCP_ERROR,("pCmdExtry %x\n", pCmdEntry));
  720. ASSERT(pCmdEntry->cmdType == AVC_CTYPE_CONTROL && "Accept+Interim but not control cmd");
  721. }
  722. }
  723. pCmdEntry->cmdState = CMD_STATE_RESP_ACCEPTED;
  724. pCmdEntry->Status = STATUS_SUCCESS; // -> NOERROR
  725. break;
  726. case AVC_RESPONSE_REJECTED:
  727. if(pCmdEntry->cmdState == CMD_STATE_RESP_INTERIM) {
  728. if(pCmdEntry->cmdType == AVC_CTYPE_CONTROL) {
  729. TRACE(TL_FCP_TRACE,("--> Reject: for control interim\n"));
  730. bSignalInterimCotrolCompleted = TRUE;
  731. } else if(pCmdEntry->cmdType == AVC_CTYPE_NOTIFY) {
  732. TRACE(TL_FCP_TRACE,("--> Reject: for notify interim\n"));
  733. bSignalInterimNotifyCompleted = TRUE;
  734. } else {
  735. TRACE(TL_FCP_ERROR,("pCmdExtry %x\n", pCmdEntry));
  736. ASSERT((pCmdEntry->cmdType == AVC_CTYPE_CONTROL || pCmdEntry->cmdType == AVC_CTYPE_NOTIFY) && "Reject+Interim but not control or notify cmd");
  737. }
  738. }
  739. pCmdEntry->cmdState = CMD_STATE_RESP_REJECTED;
  740. pCmdEntry->Status = STATUS_REQUEST_NOT_ACCEPTED; // ERROR_REQ_NOT_ACCEPTED
  741. break;
  742. case AVC_RESPONSE_IN_TRANSITION:
  743. pCmdEntry->cmdState = CMD_STATE_RESP_ACCEPTED;
  744. pCmdEntry->Status = STATUS_SUCCESS; // -> NOERROR
  745. break;
  746. case AVC_RESPONSE_STABLE: // == AVC_RESPONSE_IMPLEMENTED:
  747. pCmdEntry->cmdState = CMD_STATE_RESP_ACCEPTED;
  748. pCmdEntry->Status = STATUS_SUCCESS; // -> NOERROR
  749. break;
  750. case AVC_RESPONSE_CHANGED:
  751. #if DBG
  752. if(pCmdEntry->cmdState != CMD_STATE_RESP_INTERIM) {
  753. TRACE(TL_FCP_ERROR,("Err: Changed; pCmdExtry:%x; cmdState:%d\n", pCmdEntry, pCmdEntry->cmdState));
  754. ASSERT(pCmdEntry->cmdState == CMD_STATE_RESP_INTERIM);
  755. }
  756. #endif
  757. if(pCmdEntry->cmdType == AVC_CTYPE_NOTIFY) {
  758. TRACE(TL_FCP_TRACE,("--> Changed: for notify interim\n"));
  759. bSignalInterimNotifyCompleted = TRUE;
  760. } else {
  761. TRACE(TL_FCP_ERROR,("pCmdExtry %x\n", pCmdEntry));
  762. ASSERT(pCmdEntry->cmdType == AVC_CTYPE_NOTIFY && "Changed but not notify cmd!");
  763. }
  764. pCmdEntry->cmdState = CMD_STATE_RESP_ACCEPTED;
  765. pCmdEntry->Status = STATUS_SUCCESS; // -> NOERROR
  766. break;
  767. // AVC.sys should never return this response !!
  768. case AVC_RESPONSE_INTERIM:
  769. ASSERT( pAvcIrb->ResponseCode != AVC_RESPONSE_INTERIM && "CmpRoutine should not has this response!");
  770. pCmdEntry->cmdState = CMD_STATE_RESP_INTERIM;
  771. pCmdEntry->Status = STATUS_MORE_ENTRIES; // ov.Internal
  772. break;
  773. default:
  774. TRACE(TL_FCP_ERROR,("pCmdEntry%x; State:%d; pAvcIrb:%x; RespCode:%x\n", pCmdEntry, pCmdEntry->cmdState, pAvcIrb, pAvcIrb->ResponseCode));
  775. ASSERT(FALSE && "Undefined cmdState");
  776. pCmdEntry->cmdState = CMD_STATE_UNDEFINED;
  777. pCmdEntry->Status = STATUS_NOT_SUPPORTED; // ov.Internal
  778. break;
  779. }
  780. #if DBG
  781. if(pCmdEntry->cmdState != CMD_STATE_UNDEFINED) {
  782. TRACE(TL_FCP_WARNING,("<<<< AVCResp: pCmdEntry:%x; pAvcIrb:%x, cmdSt:%d; St:%x; %d:[%.2x %.2x %.2x %.2x]:[%.2x %.2x %.2x %.2x]\n",
  783. pCmdEntry, pCmdEntry->pAvcIrb,
  784. pCmdEntry->cmdState,
  785. pCmdEntry->Status,
  786. pAvcIrb->OperandLength+3, // Resp+SuID+OpCd+Opr[]
  787. pAvcIrb->ResponseCode,
  788. pAvcIrb->SubunitAddr[0],
  789. pAvcIrb->Opcode,
  790. pAvcIrb->Operands[0],
  791. pAvcIrb->Operands[1],
  792. pAvcIrb->Operands[2],
  793. pAvcIrb->Operands[3],
  794. pAvcIrb->Operands[4]
  795. ));
  796. }
  797. #endif
  798. } else {
  799. TRACE(TL_FCP_ERROR,("AVCCmdCR: pIrp->IoStatus.Status return error:%x\n", pIrp->IoStatus.Status));
  800. // Irp returns ERROR !!
  801. if (STATUS_BUS_RESET == pIrp->IoStatus.Status || STATUS_REQUEST_ABORTED == pIrp->IoStatus.Status) {
  802. TRACE(TL_FCP_ERROR,("Bus-Reset or abort (IoStatus.St:%x); pCmdEntry:%x; OpC:%x\n", pIrp->IoStatus.Status, pCmdEntry, pCmdEntry->OpCode));
  803. // Busreset while there is an interim pending, signal its client to wake up
  804. // and get the "final" (busreset) result.
  805. if(pCmdEntry->cmdState == CMD_STATE_RESP_INTERIM) {
  806. if(pCmdEntry->cmdType == AVC_CTYPE_CONTROL) {
  807. TRACE(TL_FCP_TRACE,("--> BusRest: for control interim\n"));
  808. bSignalInterimCotrolCompleted = TRUE;
  809. } else if(pCmdEntry->cmdType == AVC_CTYPE_NOTIFY) {
  810. TRACE(TL_FCP_TRACE,("--> BusRest: for notify interim\n"));
  811. bSignalInterimNotifyCompleted = TRUE;
  812. } else {
  813. //
  814. // Unexpected command state for a interim response
  815. //
  816. ASSERT(FALSE && "Unknow command state");
  817. }
  818. }
  819. }
  820. else {
  821. TRACE(TL_FCP_ERROR,("IOCTL_AVC_CLASS Failed 0x%x\n", pIrp->IoStatus.Status));
  822. }
  823. pCmdEntry->cmdState = CMD_STATE_ABORTED;
  824. pCmdEntry->Status = STATUS_REQUEST_ABORTED; // -> ERROR_REQUERT_ABORT
  825. }
  826. //
  827. // If suceeded, translate the AVC response to COM property. if not
  828. // interim's final reponse.
  829. // raw AVC command response
  830. //
  831. if(STATUS_SUCCESS == pCmdEntry->Status &&
  832. !bSignalInterimNotifyCompleted &&
  833. !bSignalInterimCotrolCompleted &&
  834. pCmdEntry->idxDVCRCmd != VCR_RAW_AVC
  835. )
  836. DVCRXlateRAwAVC(
  837. pCmdEntry,
  838. pCmdEntry->pProperty
  839. );
  840. // Signal a KS event to inform its client that the final response
  841. // has returned and come and get it.
  842. if(bSignalInterimNotifyCompleted) {
  843. pEvent = NULL;
  844. if(pEvent = StreamClassGetNextEvent((PVOID) pDevExt, 0, \
  845. (GUID *)&KSEVENTSETID_EXTDEV_Command, KSEVENT_EXTDEV_COMMAND_NOTIFY_INTERIM_READY, pEvent)) {
  846. // Make sure the right event and then signal it
  847. if(pEvent->EventItem->EventId == KSEVENT_EXTDEV_COMMAND_NOTIFY_INTERIM_READY) {
  848. StreamClassDeviceNotification(SignalDeviceEvent, pDevExt, pEvent);
  849. TRACE(TL_FCP_TRACE,("->Signal NOTIFY_INTERIM ready; EventId %d.\n", pEvent->EventItem->EventId));
  850. }
  851. }
  852. } else if(bSignalInterimCotrolCompleted) {
  853. pEvent = NULL;
  854. if(pEvent = StreamClassGetNextEvent((PVOID) pDevExt, 0, \
  855. (GUID *)&KSEVENTSETID_EXTDEV_Command, KSEVENT_EXTDEV_COMMAND_CONTROL_INTERIM_READY, pEvent)) {
  856. // Make sure the right event and then signal it
  857. if(pEvent->EventItem->EventId == KSEVENT_EXTDEV_COMMAND_CONTROL_INTERIM_READY) {
  858. StreamClassDeviceNotification(SignalDeviceEvent, pDevExt, pEvent);
  859. TRACE(TL_FCP_TRACE,("->Signal CONTROL_INTERIM ready; EventId %d.\n", pEvent->EventItem->EventId));
  860. }
  861. }
  862. }
  863. // Check that the command entry is ours only to process
  864. // When a command is completed, it will be added to the list and therefore not empty.
  865. // It is designed to be added to the list in this completino routine.
  866. if (!IsListEmpty(&pCmdEntry->ListEntry)) {
  867. if(bSignalInterimNotifyCompleted || bSignalInterimCotrolCompleted) {
  868. // If final reponse is returned, we need to keep them in the list.
  869. TRACE(TL_FCP_TRACE,("Final response is completed; stay in the list\n"));
  870. KeReleaseSpinLock(&pDevExt->AVCCmdLock, oldIrql);
  871. }
  872. else {
  873. // This is a undefined path!!!
  874. // The command entry can only be in the list if it is interim of anykind.
  875. // If it is an interim, it will not be removed in the completion routine.
  876. ASSERT(FALSE && "Cannot complete an interim in CR\n");
  877. }
  878. }
  879. else {
  880. // This means that we have completed, but the code that issued the
  881. // command is still executing, and hasn't had a chance to look at
  882. // the results yet. Put this in the command list as a signal that
  883. // we have completed and updated the command state, but are not
  884. // planning to free the command resources.
  885. InsertTailList(&pDevExt->AVCCmdList, &pCmdEntry->ListEntry); pDevExt->cntCommandQueued++;
  886. TRACE(TL_FCP_TRACE,("Command completed and Queued(%d); pCmdEntry:%x.\n", pDevExt->cntCommandQueued, pCmdEntry));
  887. KeReleaseSpinLock(&pDevExt->AVCCmdLock, oldIrql);
  888. }
  889. }
  890. else {
  891. TRACE(TL_FCP_WARNING,("IssueAVCCommandCR: pCmdEntry:%x; pIrp:%x cancelled\n", pCmdEntry, pIrp));
  892. }
  893. IoFreeIrp(pIrp);
  894. return STATUS_MORE_PROCESSING_REQUIRED;
  895. } // DVIssueAVCCommandCR
  896. NTSTATUS
  897. DVIssueAVCCommand (
  898. IN PDVCR_EXTENSION pDevExt,
  899. IN AvcCommandType cType,
  900. IN DVCR_AVC_COMMAND idxAVCCmd,
  901. IN PVOID pProperty
  902. )
  903. /*++
  904. Routine Description:
  905. Issue a FCP/AVC command.
  906. Arguments:
  907. Return Value:
  908. NTSTATUS
  909. --*/
  910. {
  911. NTSTATUS Status;
  912. PAVCCmdEntry pCmdEntry;
  913. PAVC_COMMAND_IRB pAvcIrb;
  914. PIRP pIrp;
  915. PIO_STACK_LOCATION NextIrpStack;
  916. #if DBG
  917. ULONGLONG tmStart;
  918. DWORD dwElapsed;
  919. #endif
  920. PAGED_CODE();
  921. if(pDevExt->bDevRemoved)
  922. return STATUS_DEVICE_NOT_CONNECTED;
  923. //
  924. // Validate Command type; the command type that each entry of the command table support.
  925. //
  926. switch(cType) {
  927. case AVC_CTYPE_CONTROL:
  928. if((DVcrAVCCmdTable[idxAVCCmd].ulCmdSupported & CMD_CONTROL) != CMD_CONTROL)
  929. return STATUS_NOT_SUPPORTED;
  930. break;
  931. case AVC_CTYPE_STATUS:
  932. if((DVcrAVCCmdTable[idxAVCCmd].ulCmdSupported & CMD_STATUS) != CMD_STATUS)
  933. return STATUS_NOT_SUPPORTED;
  934. break;
  935. case AVC_CTYPE_SPEC_INQ:
  936. if((DVcrAVCCmdTable[idxAVCCmd].ulCmdSupported & CMD_SPEC_INQ) != CMD_SPEC_INQ)
  937. return STATUS_NOT_SUPPORTED;
  938. break;
  939. case AVC_CTYPE_GEN_INQ:
  940. if((DVcrAVCCmdTable[idxAVCCmd].ulCmdSupported & CMD_GEN_INQ) != CMD_GEN_INQ)
  941. return STATUS_NOT_SUPPORTED;
  942. break;
  943. case AVC_CTYPE_NOTIFY:
  944. if((DVcrAVCCmdTable[idxAVCCmd].ulCmdSupported & CMD_NOTIFY) != CMD_NOTIFY)
  945. return STATUS_NOT_SUPPORTED;
  946. break;
  947. default:
  948. TRACE(TL_FCP_ERROR,("IssueAVCCommand: idx %d, ctype (%02x) not supported; (%02x %02x %02x) %d:[%.8x]\n",
  949. idxAVCCmd,
  950. cType,
  951. DVcrAVCCmdTable[idxAVCCmd].CType,
  952. DVcrAVCCmdTable[idxAVCCmd].SubunitAddr,
  953. DVcrAVCCmdTable[idxAVCCmd].Opcode,
  954. DVcrAVCCmdTable[idxAVCCmd].OperandLength,
  955. (DWORD) *(&DVcrAVCCmdTable[idxAVCCmd].Operands[0])
  956. ));
  957. return STATUS_NOT_SUPPORTED;
  958. }
  959. // Create an AVC IRB and initialize it -
  960. pAvcIrb = ExAllocatePool(NonPagedPool, sizeof(AVC_COMMAND_IRB));
  961. if(!pAvcIrb) {
  962. TRACE(TL_FCP_ERROR,("IssueAVCCommand: Allocate Irb (%d bytes) failed\n", sizeof(AVC_COMMAND_IRB)));
  963. return STATUS_INSUFFICIENT_RESOURCES;
  964. }
  965. RtlZeroMemory(pAvcIrb, sizeof(AVC_COMMAND_IRB));
  966. pAvcIrb->Function = AVC_FUNCTION_COMMAND;
  967. // - set the AVC command type (Control, Status, Notify, General Inquiry, Specific Inquiry)
  968. pAvcIrb->CommandType = cType;
  969. // - override the subunit address in the avc unit driver (if it even has one for us)
  970. pAvcIrb->SubunitAddrFlag = 1;
  971. pAvcIrb->SubunitAddr = &DVcrAVCCmdTable[idxAVCCmd].SubunitAddr;
  972. pAvcIrb->Opcode = DVcrAVCCmdTable[idxAVCCmd].Opcode;
  973. // - include alternate opcodes for the transport state opcode
  974. if (pAvcIrb->Opcode == OPC_TRANSPORT_STATE) {
  975. pAvcIrb->AlternateOpcodesFlag = 1;
  976. pAvcIrb->AlternateOpcodes = pDevExt->TransportModes;
  977. }
  978. // - set up the operand list
  979. pAvcIrb->OperandLength = DVcrAVCCmdTable[idxAVCCmd].OperandLength;
  980. ASSERT(pAvcIrb->OperandLength <= MAX_AVC_OPERAND_BYTES);
  981. RtlCopyMemory(pAvcIrb->Operands, DVcrAVCCmdTable[idxAVCCmd].Operands, pAvcIrb->OperandLength);
  982. // Create an Irp and initialize it
  983. pIrp = IoAllocateIrp(pDevExt->pBusDeviceObject->StackSize, FALSE);
  984. if(!pIrp) {
  985. TRACE(TL_FCP_ERROR,("IssueAVCCommand: Allocate Irb (%d bytes) failed\n", sizeof(AVC_COMMAND_IRB)));
  986. ExFreePool(pAvcIrb);
  987. return STATUS_INSUFFICIENT_RESOURCES;
  988. }
  989. // Create an AVC Command entry and initialize it
  990. pCmdEntry = (AVCCmdEntry *) ExAllocatePool(NonPagedPool, sizeof(AVCCmdEntry));
  991. if(!pCmdEntry) {
  992. TRACE(TL_FCP_ERROR,("IssueAVCCommand: Allocate CmdEntry (%d bytes) failed\n", sizeof(AVCCmdEntry)));
  993. ExFreePool(pAvcIrb);
  994. IoFreeIrp(pIrp);
  995. return STATUS_INSUFFICIENT_RESOURCES;
  996. }
  997. RtlZeroMemory(pCmdEntry, sizeof(AVCCmdEntry));
  998. pCmdEntry->pDevExt = pDevExt; // So we can access pDevExt->AVCCmdList;
  999. pCmdEntry->pProperty = pProperty;
  1000. pCmdEntry->cmdState = CMD_STATE_ISSUED;
  1001. pCmdEntry->Status = STATUS_UNSUCCESSFUL;
  1002. pCmdEntry->cmdType = cType;
  1003. pCmdEntry->OpCode = DVcrAVCCmdTable[idxAVCCmd].Opcode;
  1004. pCmdEntry->idxDVCRCmd = idxAVCCmd;
  1005. pCmdEntry->pAvcIrb = pAvcIrb;
  1006. pCmdEntry->pIrp = pIrp;
  1007. InitializeListHead(&pCmdEntry->ListEntry); // used as a flag for ownership
  1008. TRACE(TL_FCP_WARNING,(">>>> AVCCmd: %d:[%.2x %.2x %.2x %.2x]:[%.2x %.2x %.2x %.2x]\n",
  1009. pAvcIrb->OperandLength+3, // Resp+SuID+OpCd+Opr[]
  1010. cType,
  1011. pAvcIrb->SubunitAddr[0],
  1012. pAvcIrb->Opcode,
  1013. pAvcIrb->Operands[0],
  1014. pAvcIrb->Operands[1],
  1015. pAvcIrb->Operands[2],
  1016. pAvcIrb->Operands[3],
  1017. pAvcIrb->Operands[4]
  1018. ));
  1019. // Finish initializing the Irp
  1020. NextIrpStack = IoGetNextIrpStackLocation(pIrp);
  1021. NextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1022. NextIrpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_AVC_CLASS;
  1023. NextIrpStack->Parameters.Others.Argument1 = pAvcIrb;
  1024. IoSetCompletionRoutine(pIrp, DVIssueAVCCommandCR, pCmdEntry, TRUE, TRUE, TRUE);
  1025. pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1026. #if DBG
  1027. tmStart = GetSystemTime();
  1028. #endif
  1029. // Now make the call
  1030. // If encounter an interim response, STATUS_PENDING will be returned.
  1031. Status =
  1032. IoCallDriver(
  1033. pDevExt->pBusDeviceObject,
  1034. pIrp
  1035. );
  1036. #if DBG
  1037. #define MAX_RESPONSE_TIME_FOR_ALERT 500 // msec
  1038. dwElapsed = (DWORD) ((GetSystemTime() - tmStart)/10000); // Convert 100nsec unit to msec
  1039. if(dwElapsed > MAX_RESPONSE_TIME_FOR_ALERT) {
  1040. TRACE(TL_FCP_ERROR,("ST:%x; AVC Cmd took %d msec to response; CmdType:%d; OpCd:%x\n", Status, dwElapsed, cType, DVcrAVCCmdTable[idxAVCCmd].Opcode));
  1041. ASSERT(dwElapsed < MAX_RESPONSE_TIME_FOR_ALERT * 8 && "Exceeded max response time!"); // It should be 100, but let's detect the really slow one.
  1042. }
  1043. #endif
  1044. // Interim response...
  1045. if (STATUS_PENDING == Status) {
  1046. KIRQL OldIrql;
  1047. #if 1 // WORKITEM: control command can be in interim for a while!!!
  1048. // Some DV will return interim but it will completed it with a change quickly.
  1049. if(cType == AVC_CTYPE_CONTROL) {
  1050. #define MSDV_WAIT_CONTROL_CMD_INTERIM 300
  1051. TRACE(TL_FCP_WARNING,("!!!!!!!!!!! Control Interim-- Wait %d msec !!!!!!!!\n", MSDV_WAIT_CONTROL_CMD_INTERIM));
  1052. DVDelayExecutionThread(MSDV_WAIT_CONTROL_CMD_INTERIM);
  1053. ASSERT(!IsListEmpty(&pCmdEntry->ListEntry) && "Control Cmd was interim after wait.");
  1054. }
  1055. #endif
  1056. KeAcquireSpinLock(&pDevExt->AVCCmdLock, &OldIrql);
  1057. // Check that the Irp didn't complete between the return of IoCallDriver and now
  1058. if (IsListEmpty(&pCmdEntry->ListEntry)) {
  1059. // Enter INTERIM state
  1060. pCmdEntry->cmdState = CMD_STATE_RESP_INTERIM;
  1061. // Return STATUS_MORE_ENTRIES to inform caller that the command is pending.
  1062. pCmdEntry->Status = STATUS_MORE_ENTRIES; // xlate to ERROR_MORE_DATA; No yet done with this command so keep the entry in the list
  1063. // We have submitted a control or notify command, and have gotten
  1064. // an Interim response. Put the command in the list so it can be
  1065. // tracked for possible cancellation, and as an indication to the
  1066. // completion routine that we won't be releasing any resources here.
  1067. InsertTailList(&pDevExt->AVCCmdList, &pCmdEntry->ListEntry); pDevExt->cntCommandQueued++;
  1068. pCmdEntry->pProperty = NULL; // won't be using this, so get rid of it
  1069. TRACE(TL_FCP_TRACE,("->AVC command Irp is pending!\n"));
  1070. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  1071. return pCmdEntry->Status;
  1072. } else {
  1073. // Although IoCallDriver indicated that the command was pending,
  1074. // it has since been completed. The completion routine saw that
  1075. // the command entry had not yet been added to the command list,
  1076. // so put it there to let us know that we need to retain control
  1077. // and free the resources.
  1078. //
  1079. // Temporarily change the status so the cleanup code path will
  1080. // be followed.
  1081. TRACE(TL_FCP_TRACE,("-> Cmd Rtns Pending but completed; treat as non-pending! ST:%x\n", pCmdEntry->Status));
  1082. Status = STATUS_SUCCESS;
  1083. }
  1084. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  1085. }
  1086. // Status from IoCallDriver can return:
  1087. // STATUS_PENDING (process above) // If control, we wait and see if it get completed (risky!!)
  1088. // STATUS_TIMEOUT
  1089. // STATUS_SUCCESS
  1090. if(STATUS_PENDING != Status) {
  1091. // The completion routine is usually the only one that frees the Irp. Is
  1092. // it possible that the completion routine never got called? This will let
  1093. // us know, since the completion routine will always make sure that the
  1094. // command entry's Irp pointer is cleared.
  1095. if(pCmdEntry->pIrp) {
  1096. // If for some reason the completion routine never got called, free the Irp
  1097. if(pCmdEntry->pIrp)
  1098. IoFreeIrp(pCmdEntry->pIrp);
  1099. pCmdEntry->pIrp = NULL;
  1100. }
  1101. }
  1102. //
  1103. // pCmdEntry->Status is the command response Status set in the completion routine, which can be
  1104. // STATUS_SUCCESS
  1105. // STATUS_REQ_NOT_ACCEP
  1106. // STATUS_NOT_SUPPORTED
  1107. // STATUS_MORE_ENTRIES // Should not happen!!
  1108. // STATUS_REQUEST_ABORTED
  1109. //
  1110. // One possible valid command from IoCallDriver is STATUS_TIMEOUT, and
  1111. // this shoull be returned, anything else we will get the status from pCmdEntry->Status
  1112. // which was set in the completion routine.
  1113. if (Status != STATUS_TIMEOUT)
  1114. Status = pCmdEntry->Status; // This Status is being returned from this functino
  1115. // Desiding if leaving the command response (entry) in the command list
  1116. // Not if it is an (1) interim (all STATUS_MORE_ENTRIES); or (2) any RAW AVC response regardless of its status.
  1117. if(STATUS_MORE_ENTRIES == Status ||
  1118. VCR_RAW_AVC == pCmdEntry->idxDVCRCmd) {
  1119. TRACE(TL_FCP_TRACE,("Status:%x; Do not remove (1) interim response or (2) a raw AVC response\n", Status));
  1120. }
  1121. // Else we are done!
  1122. else {
  1123. KIRQL OldIrql;
  1124. // It's time to clean up the command
  1125. KeAcquireSpinLock(&pDevExt->AVCCmdLock, &OldIrql);
  1126. if (!IsListEmpty(&pCmdEntry->ListEntry)) {
  1127. RemoveEntryList(&pCmdEntry->ListEntry); pDevExt->cntCommandQueued--;
  1128. InitializeListHead(&pCmdEntry->ListEntry); // used as a flag for ownership
  1129. }
  1130. KeReleaseSpinLock(&pDevExt->AVCCmdLock, OldIrql);
  1131. // Free the resources
  1132. ExFreePool(pCmdEntry);
  1133. ExFreePool(pAvcIrb);
  1134. } // else
  1135. TRACE(TL_FCP_TRACE,("**** DVIssueAVCCmd (exit): St:%x; pCmdEntry:%x; cmdQueued:%d\n", Status, pCmdEntry, pDevExt->cntCommandQueued));
  1136. return Status;
  1137. }
  1138. #ifndef OATRUE
  1139. #define OATRUE (-1)
  1140. #endif
  1141. #ifndef OAFALSE
  1142. #define OAFALSE (0)
  1143. #endif
  1144. NTSTATUS
  1145. DVGetExtDeviceProperty(
  1146. IN PDVCR_EXTENSION pDevExt,
  1147. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1148. OUT PULONG pulActualBytesTransferred
  1149. )
  1150. /*++
  1151. Routine Description:
  1152. Handle Get external device property.
  1153. Arguments:
  1154. pDevExt - Device's extension
  1155. pSPD - Stream property descriptor
  1156. pulActualBytesTransferred - Number of byte transferred.
  1157. Return Value:
  1158. NTSTATUS
  1159. --*/
  1160. {
  1161. NTSTATUS Status = STATUS_SUCCESS;
  1162. PKSPROPERTY_EXTDEVICE_S pExtDeviceProperty;
  1163. DVCR_AVC_COMMAND idxDVCRCmd;
  1164. AvcCommandType cType = AVC_CTYPE_STATUS;
  1165. PAGED_CODE();
  1166. ASSERT(pDevExt);
  1167. ASSERT(pSPD);
  1168. ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_EXTDEVICE_S));
  1169. pExtDeviceProperty = (PKSPROPERTY_EXTDEVICE_S) pSPD->PropertyInfo; // pointer to the data
  1170. switch (pSPD->Property->Id) {
  1171. case KSPROPERTY_EXTDEVICE_ID:
  1172. if(pDevExt->ulVendorID) {
  1173. // It was not bswap in the monolithic version so for competibility,
  1174. // we will bswap this.
  1175. pExtDeviceProperty->u.NodeUniqueID[0] = pDevExt->UniqueID.LowPart;
  1176. pExtDeviceProperty->u.NodeUniqueID[1] = pDevExt->UniqueID.HighPart;
  1177. TRACE(TL_FCP_WARNING,("Low:%x; High:%x of UniqueID\n", pDevExt->UniqueID.LowPart, pDevExt->UniqueID.HighPart ));
  1178. Status = STATUS_SUCCESS;
  1179. } else {
  1180. TRACE(TL_FCP_ERROR,("Failed: Vid:%x; Mid:%x\n", bswap(pDevExt->ulVendorID) >> 8, pDevExt->ulModelID ));
  1181. Status = STATUS_UNSUCCESSFUL;
  1182. }
  1183. goto ExitGetDeviceProperty;
  1184. break;
  1185. case KSPROPERTY_EXTDEVICE_VERSION:
  1186. // AV/C VCR Subunit Specification 2.1.0
  1187. // Change from 2.0.1:
  1188. // Add Hi8 support
  1189. wcscpy(pExtDeviceProperty->u.pawchString, L"2.1.0");
  1190. Status = STATUS_SUCCESS;
  1191. goto ExitGetDeviceProperty;
  1192. break;
  1193. case KSPROPERTY_EXTDEVICE_POWER_STATE:
  1194. idxDVCRCmd = DV_GET_POWER_STATE;
  1195. break;
  1196. case KSPROPERTY_EXTDEVICE_PORT:
  1197. pExtDeviceProperty->u.DevPort = DEV_PORT_1394;
  1198. Status = STATUS_SUCCESS;
  1199. goto ExitGetDeviceProperty;
  1200. break;
  1201. case KSPROPERTY_EXTDEVICE_CAPABILITIES:
  1202. // Refresh mode of operation whenever capabilities is queried
  1203. // since the mode of operation might have changed and is returned..
  1204. DVGetDevModeOfOperation(pDevExt);
  1205. // Can record only in VCR mode and has input plug(s).
  1206. pExtDeviceProperty->u.Capabilities.CanRecord = pDevExt->ulDevType == ED_DEVTYPE_VCR ? (pDevExt->pDevInPlugs->NumPlugs > 0 ? OATRUE : OAFALSE): OAFALSE;
  1207. pExtDeviceProperty->u.Capabilities.CanRecordStrobe = OAFALSE;
  1208. pExtDeviceProperty->u.Capabilities.HasAudio = OATRUE;
  1209. pExtDeviceProperty->u.Capabilities.HasVideo = OATRUE;
  1210. pExtDeviceProperty->u.Capabilities.UsesFiles = OAFALSE;
  1211. pExtDeviceProperty->u.Capabilities.CanSave = OAFALSE;
  1212. pExtDeviceProperty->u.Capabilities.DeviceType = pDevExt->ulDevType;
  1213. pExtDeviceProperty->u.Capabilities.TCRead = OATRUE;
  1214. pExtDeviceProperty->u.Capabilities.TCWrite = OAFALSE; // DV decided
  1215. pExtDeviceProperty->u.Capabilities.CTLRead = OAFALSE;
  1216. pExtDeviceProperty->u.Capabilities.IndexRead = OAFALSE;
  1217. pExtDeviceProperty->u.Capabilities.Preroll = 0L; // NOT implemented, supposely can reg in INF and then read from registry
  1218. pExtDeviceProperty->u.Capabilities.Postroll = 0L; // NOT implemented, supposely can reg in INF and then read from registry
  1219. pExtDeviceProperty->u.Capabilities.SyncAcc = ED_CAPABILITY_UNKNOWN;
  1220. pExtDeviceProperty->u.Capabilities.NormRate = pDevExt->VideoFormatIndex == AVCSTRM_FORMAT_SDDV_NTSC ? ED_RATE_2997 : ED_RATE_25;
  1221. pExtDeviceProperty->u.Capabilities.CanPreview = OAFALSE; // View what is in the bus or tape
  1222. pExtDeviceProperty->u.Capabilities.CanMonitorSrc = OATRUE; // ViewFinder
  1223. pExtDeviceProperty->u.Capabilities.CanTest = OAFALSE; // To see if a function is iplemented
  1224. pExtDeviceProperty->u.Capabilities.VideoIn = OAFALSE;
  1225. pExtDeviceProperty->u.Capabilities.AudioIn = OAFALSE;
  1226. pExtDeviceProperty->u.Capabilities.Calibrate = OAFALSE;
  1227. pExtDeviceProperty->u.Capabilities.SeekType = ED_CAPABILITY_UNKNOWN;
  1228. TRACE(TL_FCP_TRACE,("GetExtDeviceProperty: DeviceType %x\n", pExtDeviceProperty->u.Capabilities.DeviceType));
  1229. Status = STATUS_SUCCESS;
  1230. goto ExitGetDeviceProperty;
  1231. break;
  1232. default:
  1233. Status = STATUS_NOT_SUPPORTED;
  1234. goto ExitGetDeviceProperty;
  1235. break;
  1236. }
  1237. Status = DVIssueAVCCommand(pDevExt, cType, idxDVCRCmd, (PVOID) pExtDeviceProperty);
  1238. TRACE(TL_FCP_TRACE,("GetExtDevice: idxDVCRCmd %d, cmdType %d, Status %x\n", idxDVCRCmd, cType, Status));
  1239. ExitGetDeviceProperty:
  1240. *pulActualBytesTransferred = (Status == STATUS_SUCCESS ? sizeof (KSPROPERTY_EXTDEVICE_S) : 0);
  1241. return Status;
  1242. }
  1243. NTSTATUS
  1244. DVSetExtDeviceProperty(
  1245. IN PDVCR_EXTENSION pDevExt,
  1246. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1247. OUT ULONG *pulActualBytesTransferred
  1248. )
  1249. /*++
  1250. Routine Description:
  1251. Handle Set external device property.
  1252. Arguments:
  1253. pDevExt - Device's extension
  1254. pSPD - Stream property descriptor
  1255. pulActualBytesTransferred - Number of byte transferred.
  1256. Return Value:
  1257. NTSTATUS
  1258. --*/
  1259. {
  1260. NTSTATUS Status = STATUS_SUCCESS;
  1261. PKSPROPERTY_EXTDEVICE_S pExtDeviceProperty;
  1262. DVCR_AVC_COMMAND idxDVCRCmd;
  1263. AvcCommandType cType = AVC_CTYPE_CONTROL;
  1264. PAGED_CODE();
  1265. ASSERT(pDevExt);
  1266. ASSERT(pSPD);
  1267. ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_EXTDEVICE_S));
  1268. pExtDeviceProperty = (PKSPROPERTY_EXTDEVICE_S) pSPD->PropertyInfo; // pointer to the data
  1269. switch (pSPD->Property->Id) {
  1270. case KSPROPERTY_EXTDEVICE_POWER_STATE:
  1271. switch(pExtDeviceProperty->u.PowerState) {
  1272. case ED_POWER_ON:
  1273. idxDVCRCmd = DV_SET_POWER_STATE_ON;
  1274. break;
  1275. case ED_POWER_STANDBY:
  1276. Status = STATUS_NOT_SUPPORTED; // AVC spec does not have a stanby power mode
  1277. goto ExitSetDeviceProperty;
  1278. break;
  1279. case ED_POWER_OFF:
  1280. idxDVCRCmd = DV_SET_POWER_STATE_OFF;
  1281. break;
  1282. default:
  1283. Status = STATUS_INVALID_PARAMETER;
  1284. goto ExitSetDeviceProperty;
  1285. }
  1286. break;
  1287. default:
  1288. Status = STATUS_NOT_SUPPORTED; ;
  1289. goto ExitSetDeviceProperty;
  1290. }
  1291. Status = DVIssueAVCCommand(pDevExt, cType, idxDVCRCmd, (PVOID) pExtDeviceProperty);
  1292. TRACE(TL_FCP_TRACE,("SetExtDevice: idxDVCRCmd %d, cmdType %d, Status %x\n", idxDVCRCmd, cType, Status));
  1293. ExitSetDeviceProperty:
  1294. *pulActualBytesTransferred = (Status == STATUS_SUCCESS ? sizeof (KSPROPERTY_EXTDEVICE_S) : 0);
  1295. return Status;
  1296. }
  1297. NTSTATUS
  1298. DVGetExtTransportProperty(
  1299. IN PDVCR_EXTENSION pDevExt,
  1300. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1301. OUT ULONG *pulActualBytesTransferred
  1302. )
  1303. /*++
  1304. Routine Description:
  1305. Handle Get external transport property.
  1306. Arguments:
  1307. pDevExt - Device's extension
  1308. pSPD - Stream property descriptor
  1309. pulActualBytesTransferred - Number of byte transferred.
  1310. Return Value:
  1311. NTSTATUS
  1312. --*/
  1313. {
  1314. NTSTATUS Status = STATUS_NOT_SUPPORTED;
  1315. PKSPROPERTY_EXTXPORT_S pXPrtProperty;
  1316. DVCR_AVC_COMMAND idxDVCRCmd;
  1317. AvcCommandType cType = AVC_CTYPE_STATUS;
  1318. BOOL bHasTape = pDevExt->bHasTape;
  1319. PAVCCmdEntry pCmdEntry;
  1320. PAGED_CODE();
  1321. ASSERT(pDevExt);
  1322. ASSERT(pSPD);
  1323. ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_EXTXPORT_S));
  1324. pXPrtProperty = (PKSPROPERTY_EXTXPORT_S) pSPD->PropertyInfo; // pointer to the data
  1325. *pulActualBytesTransferred = 0;
  1326. switch (pSPD->Property->Id) {
  1327. case KSPROPERTY_EXTXPORT_CAPABILITIES:
  1328. return STATUS_NOT_IMPLEMENTED;
  1329. case KSPROPERTY_RAW_AVC_CMD:
  1330. pCmdEntry = DVCRFindCmdEntryCompleted(
  1331. pDevExt,
  1332. VCR_RAW_AVC,
  1333. DVcrAVCCmdTable[VCR_RAW_AVC].Opcode,
  1334. DVcrAVCCmdTable[VCR_RAW_AVC].CType
  1335. );
  1336. if(pCmdEntry) {
  1337. PAVC_COMMAND_IRB pAvcIrb;
  1338. pAvcIrb = pCmdEntry->pAvcIrb;
  1339. ASSERT(pAvcIrb);
  1340. if (pCmdEntry->cmdState == CMD_STATE_RESP_ACCEPTED ||
  1341. pCmdEntry->cmdState == CMD_STATE_RESP_REJECTED ||
  1342. pCmdEntry->cmdState == CMD_STATE_RESP_NOT_IMPL ||
  1343. pCmdEntry->cmdState == CMD_STATE_RESP_INTERIM
  1344. ) {
  1345. // bytes for operands plus response, subunit addr, and opcode
  1346. pXPrtProperty->u.RawAVC.PayloadSize = pAvcIrb->OperandLength + 3;
  1347. pXPrtProperty->u.RawAVC.Payload[0] = pAvcIrb->ResponseCode;
  1348. pXPrtProperty->u.RawAVC.Payload[1] = pAvcIrb->SubunitAddr[0];
  1349. pXPrtProperty->u.RawAVC.Payload[2] = pAvcIrb->Opcode;
  1350. RtlCopyMemory(&pXPrtProperty->u.RawAVC.Payload[3], pAvcIrb->Operands, pAvcIrb->OperandLength);
  1351. TRACE(TL_FCP_WARNING,("RawAVCResp: pEntry:%x; State:%x; Status:%x; Sz:%d; Rsp:%x;SuId:%x;OpCd:%x; Opr:[%x %x %x %x]\n",
  1352. pCmdEntry, pCmdEntry->cmdState, pCmdEntry->Status,
  1353. pXPrtProperty->u.RawAVC.PayloadSize,
  1354. pXPrtProperty->u.RawAVC.Payload[0],
  1355. pXPrtProperty->u.RawAVC.Payload[1],
  1356. pXPrtProperty->u.RawAVC.Payload[2],
  1357. pXPrtProperty->u.RawAVC.Payload[3],
  1358. pXPrtProperty->u.RawAVC.Payload[4],
  1359. pXPrtProperty->u.RawAVC.Payload[5],
  1360. pXPrtProperty->u.RawAVC.Payload[6]
  1361. ));
  1362. // If not success, bytes transferred and data will not returned!
  1363. Status = STATUS_SUCCESS;
  1364. *pulActualBytesTransferred = sizeof (KSPROPERTY_EXTXPORT_S);
  1365. } else {
  1366. TRACE(TL_FCP_ERROR,("RawAVCResp: Found; but pCmdEntry:%x, unexpected cmdState:%d; ST:%x\n", pCmdEntry, pCmdEntry->cmdState, pCmdEntry->Status));
  1367. ASSERT(pCmdEntry->cmdState == CMD_STATE_RESP_ACCEPTED && "Unexpected command state\n");
  1368. Status = STATUS_REQUEST_ABORTED;
  1369. *pulActualBytesTransferred = 0;
  1370. }
  1371. // pIrp is NULL if it has been completed.
  1372. if(pCmdEntry->pIrp) {
  1373. TRACE(TL_FCP_ERROR,("RawAVCResp: pCmdEntry %x; ->pIrp:%x not completd yet!\n", pCmdEntry, pCmdEntry->pIrp));
  1374. ASSERT(pCmdEntry->pIrp == NULL && "pIrp is not completed!");
  1375. IoCancelIrp(pCmdEntry->pIrp);
  1376. }
  1377. // Not used in the completion routine if pIrp->Cancel
  1378. ExFreePool(pCmdEntry);
  1379. ExFreePool(pAvcIrb);
  1380. }
  1381. else {
  1382. TRACE(TL_FCP_ERROR,("KSPROPERTY_RAW_AVC_CMD, did not find a match[%x]!\n",
  1383. *((DWORD *) &DVcrAVCCmdTable[VCR_RAW_AVC].CType) ));
  1384. *pulActualBytesTransferred = 0;
  1385. Status = STATUS_NOT_FOUND; // ERROR_MR_MID_NOT_FOUND
  1386. }
  1387. return Status;
  1388. case KSPROPERTY_EXTXPORT_INPUT_SIGNAL_MODE: // MPEG, D-VHS, Analog VHS etc.
  1389. idxDVCRCmd = VCR_INPUT_SIGNAL_MODE;
  1390. break;
  1391. case KSPROPERTY_EXTXPORT_OUTPUT_SIGNAL_MODE: // MPEG, D-VHS, Analog VHS etc.
  1392. idxDVCRCmd = VCR_OUTPUT_SIGNAL_MODE;
  1393. break;
  1394. case KSPROPERTY_EXTXPORT_MEDIUM_INFO: // cassettte_type and tape_grade_and_write_protect
  1395. idxDVCRCmd = VCR_MEDIUM_INFO;
  1396. break;
  1397. case KSPROPERTY_EXTXPORT_STATE:
  1398. idxDVCRCmd = VCR_TRANSPORT_STATE;
  1399. break;
  1400. case KSPROPERTY_EXTXPORT_STATE_NOTIFY:
  1401. // Get final result from previous set command
  1402. pCmdEntry = DVCRFindCmdEntryCompleted(
  1403. pDevExt,
  1404. VCR_TRANSPORT_STATE_NOTIFY,
  1405. DVcrAVCCmdTable[VCR_TRANSPORT_STATE_NOTIFY].Opcode,
  1406. DVcrAVCCmdTable[VCR_TRANSPORT_STATE_NOTIFY].CType
  1407. );
  1408. if(pCmdEntry) {
  1409. PAVC_COMMAND_IRB pAvcIrb;
  1410. pAvcIrb = pCmdEntry->pAvcIrb;
  1411. ASSERT(pCmdEntry->pAvcIrb);
  1412. TRACE(TL_FCP_WARNING,("->Notify Resp: pCmdEntry:%x; pIrb:%x; %d:[%.2x %.2x %.2x %.2x]\n",
  1413. pCmdEntry, pAvcIrb,
  1414. pAvcIrb->OperandLength + 3,
  1415. pAvcIrb->ResponseCode,
  1416. pAvcIrb->SubunitAddr[0],
  1417. pAvcIrb->Opcode,
  1418. pAvcIrb->Operands[0]
  1419. ));
  1420. if(pCmdEntry->cmdState == CMD_STATE_RESP_ACCEPTED)
  1421. Status =
  1422. DVCRXlateRAwAVC(
  1423. pCmdEntry,
  1424. pXPrtProperty
  1425. );
  1426. // pIrp is NULL if it has been completed.
  1427. if(pCmdEntry->pIrp) {
  1428. TRACE(TL_FCP_ERROR,("XPrtNotifyResp: pCmdEntry %x; ->pIrp:%x not completed; IoCancelIrp(pIrp)\n", pCmdEntry, pCmdEntry->pIrp));
  1429. IoCancelIrp(pCmdEntry->pIrp);
  1430. }
  1431. // These two are not touched in the CompletionRoutine if pIrp->Cancel
  1432. ExFreePool(pCmdEntry);
  1433. ExFreePool(pAvcIrb);
  1434. *pulActualBytesTransferred = STATUS_SUCCESS == Status ? sizeof (KSPROPERTY_EXTXPORT_S) : 0;
  1435. }
  1436. else {
  1437. TRACE(TL_FCP_ERROR,("EXTXPORT_STATE_NOTIFY: no match!\n"));
  1438. *pulActualBytesTransferred = 0;
  1439. Status = STATUS_NOT_FOUND; // ERROR_MR_MID_NOT_FOUND
  1440. }
  1441. return Status;
  1442. default:
  1443. TRACE(TL_FCP_ERROR,("GetExtTransportProperty: NOT_IMPLEMENTED Property->Id %d\n", pSPD->Property->Id));
  1444. return STATUS_NOT_SUPPORTED;
  1445. }
  1446. Status = DVIssueAVCCommand(pDevExt, cType, idxDVCRCmd, (PVOID) pXPrtProperty);
  1447. TRACE(TL_FCP_TRACE,("GetExtTransportProperty: idxDVCRCmd %d, cmdType %d, Status %x\n", idxDVCRCmd, cType, Status));
  1448. *pulActualBytesTransferred = (Status == STATUS_SUCCESS ? sizeof (KSPROPERTY_EXTXPORT_S) : 0);
  1449. if(STATUS_SUCCESS == Status &&
  1450. idxDVCRCmd == VCR_MEDIUM_INFO) {
  1451. // Update Media info
  1452. pDevExt->bHasTape = pXPrtProperty->u.MediumInfo.MediaPresent;
  1453. pDevExt->bWriteProtected = pXPrtProperty->u.MediumInfo.RecordInhibit;
  1454. TRACE(TL_FCP_TRACE,("bHasTape: IN(%d):OUT(%d), ulDevType %d\n", bHasTape, pDevExt->bHasTape, pDevExt->ulDevType));
  1455. }
  1456. return Status;
  1457. }
  1458. NTSTATUS
  1459. DVSetExtTransportProperty(
  1460. IN PDVCR_EXTENSION pDevExt,
  1461. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1462. OUT ULONG *pulActualBytesTransferred
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Handle Set external transport property.
  1467. Arguments:
  1468. pDevExt - Device's extension
  1469. pSPD - Stream property descriptor
  1470. pulActualBytesTransferred - Number of byte transferr
  1471. Return Value:
  1472. NTSTATUS
  1473. --*/
  1474. {
  1475. NTSTATUS Status = STATUS_SUCCESS;
  1476. PKSPROPERTY_EXTXPORT_S pXPrtProperty;
  1477. DVCR_AVC_COMMAND idxDVCRCmd;
  1478. AvcCommandType cType = AVC_CTYPE_CONTROL;
  1479. PAGED_CODE();
  1480. ASSERT(pDevExt);
  1481. ASSERT(pSPD);
  1482. ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_EXTXPORT_S));
  1483. pXPrtProperty = (PKSPROPERTY_EXTXPORT_S) pSPD->PropertyInfo; // pointer to the data
  1484. *pulActualBytesTransferred = 0;
  1485. switch (pSPD->Property->Id) {
  1486. case KSPROPERTY_EXTXPORT_STATE:
  1487. switch (pXPrtProperty->u.XPrtState.Mode) {
  1488. // RECORD
  1489. case ED_MODE_RECORD:
  1490. idxDVCRCmd = VCR_RECORD;
  1491. break;
  1492. case ED_MODE_RECORD_FREEZE:
  1493. idxDVCRCmd = VCR_RECORD_PAUSE;
  1494. break;
  1495. // PLAY
  1496. case ED_MODE_STEP_FWD:
  1497. idxDVCRCmd = VCR_PLAY_FORWARD_STEP;
  1498. break;
  1499. case ED_MODE_PLAY_SLOWEST_FWD:
  1500. // DVCPRO does not seem to support the standard play slow fwd so this is an alternate
  1501. if(pDevExt->bDVCPro)
  1502. idxDVCRCmd = VCR_PLAY_FORWARD_SLOWEST2;
  1503. else
  1504. idxDVCRCmd = VCR_PLAY_FORWARD_SLOWEST;
  1505. break;
  1506. case ED_MODE_PLAY_FASTEST_FWD:
  1507. idxDVCRCmd = VCR_PLAY_FORWARD_FASTEST;
  1508. break;
  1509. case ED_MODE_STEP_REV:
  1510. idxDVCRCmd = VCR_PLAY_REVERSE_STEP;
  1511. break;
  1512. case ED_MODE_PLAY_SLOWEST_REV:
  1513. // DVCPRO does not seem to support the standard play slow rev so this is an alternate
  1514. if(pDevExt->bDVCPro)
  1515. idxDVCRCmd = VCR_PLAY_REVERSE_SLOWEST2;
  1516. else
  1517. idxDVCRCmd = VCR_PLAY_REVERSE_SLOWEST;
  1518. break;
  1519. case ED_MODE_PLAY_FASTEST_REV:
  1520. idxDVCRCmd = VCR_PLAY_REVERSE_FASTEST;
  1521. break;
  1522. case ED_MODE_PLAY:
  1523. idxDVCRCmd = VCR_PLAY_FORWARD;
  1524. break;
  1525. case ED_MODE_FREEZE:
  1526. idxDVCRCmd = VCR_PLAY_FORWARD_PAUSE;
  1527. break;
  1528. // WIND
  1529. case ED_MODE_STOP:
  1530. idxDVCRCmd = VCR_WIND_STOP;
  1531. break;
  1532. case ED_MODE_FF:
  1533. idxDVCRCmd = VCR_WIND_FAST_FORWARD;
  1534. break;
  1535. case ED_MODE_REW:
  1536. idxDVCRCmd = VCR_WIND_REWIND;
  1537. break;
  1538. default:
  1539. TRACE(TL_FCP_ERROR,("SetExtTransportProperty: NOT_IMPLEMENTED XPrtState.Mode %d\n", pXPrtProperty->u.XPrtState.Mode));
  1540. return STATUS_NOT_SUPPORTED;
  1541. }
  1542. break;
  1543. case KSPROPERTY_EXTXPORT_STATE_NOTIFY:
  1544. idxDVCRCmd = VCR_TRANSPORT_STATE_NOTIFY;
  1545. cType = AVC_CTYPE_NOTIFY;
  1546. TRACE(TL_FCP_TRACE,("->Notify XPrt State Cmd issued.\n"));
  1547. break;
  1548. case KSPROPERTY_EXTXPORT_LOAD_MEDIUM:
  1549. idxDVCRCmd = VCR_LOAD_MEDIUM_EJECT;
  1550. break;
  1551. case KSPROPERTY_EXTXPORT_TIMECODE_SEARCH:
  1552. idxDVCRCmd = VCR_TIMECODE_SEARCH;
  1553. TRACE(TL_FCP_ERROR,("SetExtTransportProperty: KSPROPERTY_EXTXPORT_TIMECODE_SEARCH NOT_SUPPORTED\n"));
  1554. *pulActualBytesTransferred = 0;
  1555. return STATUS_NOT_SUPPORTED;
  1556. case KSPROPERTY_EXTXPORT_ATN_SEARCH:
  1557. idxDVCRCmd = VCR_ATN_SEARCH;
  1558. TRACE(TL_FCP_ERROR,("SetExtTransportProperty: KSPROPERTY_EXTXPORT_ATN_SEARCH NOT_SUPPORTED\n"));
  1559. *pulActualBytesTransferred = 0;
  1560. return STATUS_NOT_SUPPORTED;
  1561. case KSPROPERTY_EXTXPORT_RTC_SEARCH:
  1562. idxDVCRCmd = VCR_RTC_SEARCH;
  1563. TRACE(TL_FCP_ERROR,("SetExtTransportProperty: KSPROPERTY_EXTXPORT_RTC_SEARCH NOT_SUPPORTED\n"));
  1564. *pulActualBytesTransferred = 0;
  1565. return STATUS_NOT_SUPPORTED;
  1566. case KSPROPERTY_RAW_AVC_CMD:
  1567. idxDVCRCmd = VCR_RAW_AVC;
  1568. if(pXPrtProperty->u.RawAVC.PayloadSize <= MAX_FCP_PAYLOAD_SIZE) {
  1569. DVcrAVCCmdTable[idxDVCRCmd].CType = pXPrtProperty->u.RawAVC.Payload[0];
  1570. DVcrAVCCmdTable[idxDVCRCmd].SubunitAddr = pXPrtProperty->u.RawAVC.Payload[1];
  1571. DVcrAVCCmdTable[idxDVCRCmd].Opcode = pXPrtProperty->u.RawAVC.Payload[2];
  1572. DVcrAVCCmdTable[idxDVCRCmd].OperandLength = pXPrtProperty->u.RawAVC.PayloadSize - 3;
  1573. RtlCopyMemory(DVcrAVCCmdTable[idxDVCRCmd].Operands, pXPrtProperty->u.RawAVC.Payload + 3, DVcrAVCCmdTable[idxDVCRCmd].OperandLength);
  1574. // extract command type; for RAW AVC, it can be anything.
  1575. cType = pXPrtProperty->u.RawAVC.Payload[0];
  1576. TRACE(TL_FCP_WARNING,("RawAVC cmd: cType %x, PayLoadSize %d, PayLoad %x %x %x %x\n",
  1577. cType,
  1578. pXPrtProperty->u.RawAVC.PayloadSize,
  1579. pXPrtProperty->u.RawAVC.Payload[0],
  1580. pXPrtProperty->u.RawAVC.Payload[1],
  1581. pXPrtProperty->u.RawAVC.Payload[2],
  1582. pXPrtProperty->u.RawAVC.Payload[3]
  1583. ));
  1584. } else {
  1585. Status = STATUS_INVALID_PARAMETER;
  1586. *pulActualBytesTransferred = 0;
  1587. return Status;
  1588. }
  1589. break;
  1590. default:
  1591. TRACE(TL_FCP_ERROR,("SetExtTransportProperty: NOT_IMPLEMENTED Property->Id %d\n", pSPD->Property->Id));
  1592. return STATUS_NOT_SUPPORTED;
  1593. }
  1594. Status = DVIssueAVCCommand(pDevExt, cType, idxDVCRCmd, (PVOID) pXPrtProperty);
  1595. TRACE(TL_FCP_TRACE,("SetExtTransportProperty: idxDVCRCmd %d, Status %x\n", idxDVCRCmd, Status));
  1596. *pulActualBytesTransferred = (Status == STATUS_SUCCESS ? sizeof (PKSPROPERTY_EXTXPORT_S) : 0);
  1597. return Status;
  1598. }
  1599. NTSTATUS
  1600. DVGetTimecodeReaderProperty(
  1601. IN PDVCR_EXTENSION pDevExt,
  1602. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1603. OUT PULONG pulActualBytesTransferred
  1604. )
  1605. /*++
  1606. Routine Description:
  1607. Arguments:
  1608. Return Value:
  1609. NTSTATUS
  1610. --*/
  1611. {
  1612. NTSTATUS Status = STATUS_SUCCESS;
  1613. PKSPROPERTY_TIMECODE_S pTmCdReaderProperty;
  1614. DVCR_AVC_COMMAND idxDVCRCmd;
  1615. PAGED_CODE();
  1616. ASSERT (pSPD->PropertyOutputSize >= sizeof (KSPROPERTY_TIMECODE_S));
  1617. pTmCdReaderProperty = (PKSPROPERTY_TIMECODE_S) pSPD->PropertyInfo; // pointer to the data
  1618. *pulActualBytesTransferred = 0;
  1619. switch (pSPD->Property->Id) {
  1620. case KSPROPERTY_TIMECODE_READER:
  1621. idxDVCRCmd = VCR_TIMECODE_READ;
  1622. #ifdef MSDV_SUPPORT_EXTRACT_SUBCODE_DATA
  1623. // There can only be one active stream.
  1624. if(pDevExt->cndStrmOpen == 1 &&
  1625. pDevExt->paStrmExt[pDevExt->idxStreamNumber]->StreamState == KSSTATE_RUN) {
  1626. if(pDevExt->paStrmExt[pDevExt->idxStreamNumber]->bTimecodeUpdated) {
  1627. // Once it is read, it is stale.
  1628. pDevExt->paStrmExt[pDevExt->idxStreamNumber]->bTimecodeUpdated = FALSE;
  1629. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames =
  1630. (((DWORD) pDevExt->paStrmExt[pDevExt->idxStreamNumber]->Timecode[0]) << 24) |
  1631. (((DWORD) pDevExt->paStrmExt[pDevExt->idxStreamNumber]->Timecode[1]) << 16) |
  1632. (((DWORD) pDevExt->paStrmExt[pDevExt->idxStreamNumber]->Timecode[2]) << 8) |
  1633. ((DWORD) pDevExt->paStrmExt[pDevExt->idxStreamNumber]->Timecode[3]);
  1634. *pulActualBytesTransferred = (Status == STATUS_SUCCESS ? sizeof (KSPROPERTY_TIMECODE_S) : 0);
  1635. return STATUS_SUCCESS;
  1636. }
  1637. else {
  1638. TRACE(TL_FCP_TRACE,("bTimecode stale, issue AVC command to read it.\n"));
  1639. }
  1640. }
  1641. #endif
  1642. break;
  1643. case KSPROPERTY_ATN_READER:
  1644. idxDVCRCmd = VCR_ATN_READ;
  1645. #ifdef MSDV_SUPPORT_EXTRACT_SUBCODE_DATA
  1646. // There can only be one active stream.
  1647. if(pDevExt->cndStrmOpen == 1 &&
  1648. pDevExt->paStrmExt[pDevExt->idxStreamNumber]->StreamState == KSSTATE_RUN) {
  1649. if(pDevExt->paStrmExt[pDevExt->idxStreamNumber]->bATNUpdated) {
  1650. // Once it is read, it is stale.
  1651. pDevExt->paStrmExt[pDevExt->idxStreamNumber]->bATNUpdated = FALSE;
  1652. pTmCdReaderProperty->TimecodeSamp.timecode.dwFrames =
  1653. pDevExt->paStrmExt[pDevExt->idxStreamNumber]->AbsTrackNumber >> 1;
  1654. pTmCdReaderProperty->TimecodeSamp.dwUser =
  1655. pDevExt->paStrmExt[pDevExt->idxStreamNumber]->AbsTrackNumber & 0x00000001;
  1656. *pulActualBytesTransferred = (Status == STATUS_SUCCESS ? sizeof (KSPROPERTY_TIMECODE_S) : 0);
  1657. return STATUS_SUCCESS;
  1658. }
  1659. else {
  1660. TRACE(TL_FCP_WARNING,("bATN stale, issue AVC command to read it.\n"));
  1661. }
  1662. }
  1663. #endif
  1664. break;
  1665. case KSPROPERTY_RTC_READER:
  1666. idxDVCRCmd = VCR_RTC_READ;
  1667. break;
  1668. default:
  1669. TRACE(TL_FCP_ERROR,("GetTimecodeReaderProperty: NOT_IMPLEMENTED Property->Id %d\n", pSPD->Property->Id));
  1670. return STATUS_NOT_SUPPORTED;
  1671. }
  1672. Status =
  1673. DVIssueAVCCommand(
  1674. pDevExt,
  1675. AVC_CTYPE_STATUS,
  1676. idxDVCRCmd,
  1677. (PVOID) pTmCdReaderProperty
  1678. );
  1679. TRACE(TL_FCP_TRACE,("GetTimecodeReaderProperty: idxDVCRCmd %d, Status %x\n", idxDVCRCmd, Status));
  1680. *pulActualBytesTransferred = (Status == STATUS_SUCCESS ? sizeof (KSPROPERTY_TIMECODE_S) : 0);
  1681. return Status;
  1682. }
  1683. NTSTATUS
  1684. DVMediaSeekingProperty(
  1685. IN PDVCR_EXTENSION pDevExt,
  1686. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1687. OUT PULONG pulActualBytesTransferred
  1688. )
  1689. /*++
  1690. Routine Description:
  1691. Arguments:
  1692. Return Value:
  1693. NTSTATUS
  1694. --*/
  1695. {
  1696. NTSTATUS Status = STATUS_SUCCESS;
  1697. GUID * pTimeFormatGuid;
  1698. KSMULTIPLE_ITEM * pMultipleItem;
  1699. PAGED_CODE();
  1700. *pulActualBytesTransferred = 0;
  1701. switch (pSPD->Property->Id) {
  1702. case KSPROPERTY_MEDIASEEKING_FORMATS:
  1703. // Its is KSMULTIPLE_ITEM so it is a two step process to return the data:
  1704. // (1) return size in pActualBytesTransferred with STATUS_BUFFER_OVERFLOW
  1705. // (2) 2nd time to get its actual data.
  1706. if(pSPD->PropertyOutputSize == 0) {
  1707. *pulActualBytesTransferred = sizeof(KSMULTIPLE_ITEM) + sizeof(GUID);
  1708. Status = STATUS_BUFFER_OVERFLOW;
  1709. } else if(pSPD->PropertyOutputSize >= (sizeof(KSMULTIPLE_ITEM) + sizeof(GUID))) {
  1710. pMultipleItem = (KSMULTIPLE_ITEM *) pSPD->PropertyInfo; // pointer to the data
  1711. pMultipleItem->Count = 1;
  1712. pMultipleItem->Size = sizeof(KSMULTIPLE_ITEM) + sizeof(GUID);
  1713. pTimeFormatGuid = (GUID *) (pMultipleItem + 1); // pointer to the data
  1714. memcpy(pTimeFormatGuid, &KSTIME_FORMAT_MEDIA_TIME, sizeof(GUID));
  1715. *pulActualBytesTransferred = sizeof(KSMULTIPLE_ITEM) + sizeof(GUID);
  1716. Status = STATUS_SUCCESS;
  1717. } else {
  1718. TRACE(TL_FCP_ERROR,("MediaSeekingProperty: KSPROPERTY_MEDIASEEKING_FORMAT; STATUS_INVALID_PARAMETER\n"));
  1719. Status = STATUS_INVALID_PARAMETER;
  1720. }
  1721. break;
  1722. default:
  1723. TRACE(TL_FCP_ERROR,("MediaSeekingProperty:Not supported ID %d\n", pSPD->Property->Id));
  1724. return STATUS_NOT_SUPPORTED;
  1725. }
  1726. return Status;
  1727. }
  1728. NTSTATUS
  1729. AVCTapeGetDeviceProperty(
  1730. IN PDVCR_EXTENSION pDevExt,
  1731. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1732. IN PULONG pulActualBytesTransferred
  1733. )
  1734. /*++
  1735. Routine Description:
  1736. Handles Get operations for all adapter properties.
  1737. Arguments:
  1738. Return Value:
  1739. NTSTATUS
  1740. --*/
  1741. {
  1742. NTSTATUS Status;
  1743. PAGED_CODE();
  1744. if (IsEqualGUID (&PROPSETID_EXT_DEVICE, &pSPD->Property->Set)) {
  1745. Status =
  1746. DVGetExtDeviceProperty(
  1747. pDevExt,
  1748. pSPD,
  1749. pulActualBytesTransferred
  1750. );
  1751. }
  1752. else
  1753. if (IsEqualGUID (&PROPSETID_EXT_TRANSPORT, &pSPD->Property->Set)) {
  1754. Status =
  1755. DVGetExtTransportProperty(
  1756. pDevExt,
  1757. pSPD,
  1758. pulActualBytesTransferred
  1759. );
  1760. }
  1761. else
  1762. if (IsEqualGUID (&PROPSETID_TIMECODE_READER, &pSPD->Property->Set)) {
  1763. Status =
  1764. DVGetTimecodeReaderProperty(
  1765. pDevExt,
  1766. pSPD,
  1767. pulActualBytesTransferred
  1768. );
  1769. }
  1770. else
  1771. if (IsEqualGUID (&KSPROPSETID_MediaSeeking, &pSPD->Property->Set)) {
  1772. Status =
  1773. DVMediaSeekingProperty(
  1774. pDevExt,
  1775. pSPD,
  1776. pulActualBytesTransferred
  1777. );
  1778. } else {
  1779. //
  1780. // We should never get here
  1781. //
  1782. Status = STATUS_NOT_SUPPORTED;
  1783. TRACE(TL_FCP_ERROR,("get unknown property\n"));
  1784. ASSERT(FALSE);
  1785. }
  1786. return Status;
  1787. }
  1788. NTSTATUS
  1789. AVCTapeSetDeviceProperty(
  1790. IN PDVCR_EXTENSION pDevExt,
  1791. IN PSTREAM_PROPERTY_DESCRIPTOR pSPD,
  1792. IN PULONG pulActualBytetransferred
  1793. )
  1794. /*++
  1795. Routine Description:
  1796. Handles Set operations for all adapter properties.
  1797. Arguments:
  1798. Return Value:
  1799. NTSTATUS
  1800. --*/
  1801. {
  1802. NTSTATUS Status;
  1803. PAGED_CODE();
  1804. if (IsEqualGUID (&PROPSETID_EXT_DEVICE, &pSPD->Property->Set)) {
  1805. Status =
  1806. DVSetExtDeviceProperty(
  1807. pDevExt,
  1808. pSPD,
  1809. pulActualBytetransferred
  1810. );
  1811. }
  1812. else
  1813. if (IsEqualGUID (&PROPSETID_EXT_TRANSPORT, &pSPD->Property->Set)) {
  1814. Status =
  1815. DVSetExtTransportProperty(
  1816. pDevExt,
  1817. pSPD,
  1818. pulActualBytetransferred
  1819. );
  1820. }
  1821. else {
  1822. Status = STATUS_NOT_SUPPORTED;
  1823. //
  1824. // We should never get here
  1825. //
  1826. TRACE(TL_FCP_ERROR,("set unknown property\n"));
  1827. ASSERT(FALSE);
  1828. }
  1829. return Status;
  1830. }