Annotation of ntddk/src/mmedia/soundlib/midi.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1992  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     midi.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains code for playing and recording Midi
        !            12:     data.
        !            13: 
        !            14: Author:
        !            15: 
        !            16:     Robin Speed (robinsp) 25-Nov-92
        !            17: 
        !            18: Environment:
        !            19: 
        !            20:     Kernel mode
        !            21: 
        !            22: Revision History:
        !            23: 
        !            24: --*/
        !            25: 
        !            26: #include <soundlib.h>
        !            27: #include <midi.h>
        !            28: 
        !            29: //
        !            30: // Internal routines
        !            31: //
        !            32: 
        !            33: VOID
        !            34: MidiRecord(
        !            35:     IN  OUT PMIDI_INFO pMidi,
        !            36:     IN  OUT PIRP pIrp
        !            37: );
        !            38: 
        !            39: //
        !            40: // Macros to assist in safely using our spin lock (midi input only)
        !            41: //
        !            42: 
        !            43: #if DBG
        !            44: #define MidiEnter(pMidi)                    \
        !            45:     {                                      \
        !            46:        KIRQL OldIrql;                      \
        !            47:        KeAcquireSpinLock(&(pMidi)->DeviceSpinLock, &OldIrql);\
        !            48:        ASSERT((pMidi)->LockHeld == FALSE); \
        !            49:        (pMidi)->LockHeld = TRUE;
        !            50: 
        !            51: #define MidiLeave(pMidi)                    \
        !            52:        ASSERT((pMidi)->LockHeld == TRUE);  \
        !            53:        (pMidi)->LockHeld = FALSE;          \
        !            54:        KeReleaseSpinLock(&(pMidi)->DeviceSpinLock, OldIrql);\
        !            55:     }
        !            56: #else
        !            57: #define MidiEnter(pMidi)                    \
        !            58:     {                                      \
        !            59:        KIRQL OldIrql;                      \
        !            60:        ASSERT((pMidi)->LockHeld == FALSE); \
        !            61:        KeAcquireSpinLock(&(pMidi)->DeviceSpinLock, &OldIrql);
        !            62: 
        !            63: #define MidiLeave(pMidi)                    \
        !            64:        ASSERT((pMidi)->LockHeld == TRUE);  \
        !            65:        KeReleaseSpinLock(&(pMidi)->DeviceSpinLock, OldIrql);\
        !            66:     }
        !            67: #endif
        !            68: 
        !            69: 
        !            70: VOID SoundInitMidiIn(
        !            71:     IN OUT PMIDI_INFO pMidi,
        !            72:     IN     PVOID HwContext
        !            73: )
        !            74: /*++
        !            75: 
        !            76: Routine Description:
        !            77: 
        !            78:     Initialize midi input data structure.  Assumes the structure is
        !            79:     initialized to 0 apart from the hardware routine entries which
        !            80:     should have been initialized.
        !            81: 
        !            82: Arguments:
        !            83: 
        !            84:     pMidi - pointer to MIDI_INFO data structure
        !            85: 
        !            86: Return Value:
        !            87:     None
        !            88: 
        !            89: --*/
        !            90: {
        !            91:     KeInitializeSpinLock(&pMidi->DeviceSpinLock);
        !            92:     InitializeListHead(&pMidi->QueueHead);
        !            93:     pMidi->Key = MIDI_INFO_KEY;
        !            94:     pMidi->HwContext = HwContext;
        !            95: 
        !            96:     ASSERTMSG("Midi hardware routines not initialized",
        !            97:               pMidi->HwStartMidiIn != NULL &&
        !            98:               pMidi->HwStopMidiIn != NULL &&
        !            99:               pMidi->HwMidiRead != NULL &&
        !           100:               pMidi->HwMidiOut != NULL);
        !           101: 
        !           102: }
        !           103: 
        !           104: 
        !           105: NTSTATUS
        !           106: SoundIoctlGetMidiState(
        !           107:     IN OUT PLOCAL_DEVICE_INFO pLDI,
        !           108:     IN    PIRP pIrp,
        !           109:     IN    PIO_STACK_LOCATION IrpStack
        !           110: )
        !           111: /*++
        !           112: 
        !           113: Routine Description:
        !           114: 
        !           115:     Get the current state of the device and return it to the caller.
        !           116:     This code is COMMON for :
        !           117:        Midi in
        !           118:        Midi out
        !           119: 
        !           120: Arguments:
        !           121: 
        !           122:     pLDI - Pointer to our own device data
        !           123:     pIrp - Pointer to the IO Request Packet
        !           124:     IrpStack - Pointer to current stack location
        !           125: 
        !           126: Return Value:
        !           127: 
        !           128:      Status to put into request packet by caller.
        !           129: 
        !           130: --*/
        !           131: {
        !           132:     PULONG pState;
        !           133: 
        !           134:     if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) {
        !           135:         dprintf1(("Supplied buffer to small for requested data"));
        !           136:         return STATUS_BUFFER_TOO_SMALL;
        !           137:     }
        !           138: 
        !           139:     //
        !           140:     // say how much we're sending back
        !           141:     //
        !           142: 
        !           143:     pIrp->IoStatus.Information = sizeof(ULONG);
        !           144: 
        !           145:     //
        !           146:     // cast the buffer address to the pointer type we want
        !           147:     //
        !           148: 
        !           149:     pState = (PULONG)pIrp->AssociatedIrp.SystemBuffer;
        !           150: 
        !           151:     //
        !           152:     // fill in the info -
        !           153:     //
        !           154: 
        !           155:     *pState = pLDI->State;
        !           156: 
        !           157:     return STATUS_SUCCESS;
        !           158: }
        !           159: 
        !           160: 
        !           161: NTSTATUS SoundIoctlMidiPlay(
        !           162:     IN OUT PLOCAL_DEVICE_INFO pLDI,
        !           163:     IN     PIRP pIrp,
        !           164:     IN     PIO_STACK_LOCATION IrpStack
        !           165: )
        !           166: /*++
        !           167: 
        !           168: Routine Description:
        !           169: 
        !           170:     Play Midi output (if this is an output device).
        !           171:     This call is implemented SYNCRHONOUSLY since the device does
        !           172:     not support interrupts.  However, for MP systems we should really
        !           173:     complete the request asynchronously.  We do release the spin lock while
        !           174:     actually outputting data.
        !           175: 
        !           176: Arguments:
        !           177: 
        !           178:     pLDI - our local device data
        !           179:     pIrp - IO request packet
        !           180:     IrpStack - The current stack location
        !           181: 
        !           182: 
        !           183: Return Value:
        !           184: 
        !           185:     STATUS_SUCCESS       - OK
        !           186:     STATUS_DEVICE_BUSY   - Device in use
        !           187:     STATUS_NOT_SUPPORTED - wrong device
        !           188: 
        !           189: --*/
        !           190: 
        !           191: {
        !           192:     PUCHAR pUserBuffer;                 // Pointer to mapped user buffer
        !           193:     ULONG  UserBufferSize;              // Amount of user data
        !           194:     ULONG i;                             // Buffer index
        !           195:     NTSTATUS Status;
        !           196:     PMIDI_INFO pMidi;
        !           197: 
        !           198:     pMidi = pLDI->DeviceSpecificData;
        !           199:     Status = STATUS_SUCCESS;
        !           200: 
        !           201:     //
        !           202:     // Check it's valid
        !           203:     //
        !           204: 
        !           205:     if (pLDI->DeviceType != MIDI_OUT) {
        !           206:         dprintf1(("Attempt play on input device"));
        !           207:         return STATUS_NOT_SUPPORTED;
        !           208:     }
        !           209: 
        !           210: 
        !           211:     //
        !           212:     // Find the length of the data and the buffer
        !           213:     //
        !           214: 
        !           215:     UserBufferSize =
        !           216:         IrpStack->Parameters.DeviceIoControl.InputBufferLength;
        !           217: 
        !           218:     pUserBuffer = IrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
        !           219: 
        !           220: 
        !           221:     //
        !           222:     // Send the data to the device
        !           223:     //
        !           224: 
        !           225:     dprintf4(("Outputting %d Midi bytes", UserBufferSize));
        !           226: 
        !           227:     //
        !           228:     // Our memory is not locked down or checked since we're
        !           229:     // executing the call SYNCHRONOUSLY - so we defend here against
        !           230:     // bad applications.  This is aimed at getting a fast path
        !           231:     // for short messages.
        !           232:     //
        !           233: 
        !           234:     try {
        !           235:         (*pMidi->HwMidiOut)(pMidi, pUserBuffer, UserBufferSize);
        !           236:     } except (EXCEPTION_EXECUTE_HANDLER) {
        !           237:         Status = STATUS_ACCESS_VIOLATION;
        !           238:     }
        !           239: 
        !           240:     return Status;
        !           241: }
        !           242: 
        !           243: 
        !           244: 
        !           245: NTSTATUS
        !           246: SoundIoctlMidiRecord(
        !           247:     IN OUT PLOCAL_DEVICE_INFO pLDI,
        !           248:     IN     PIRP pIrp,
        !           249:     IN     PIO_STACK_LOCATION pIrpStack
        !           250: )
        !           251: /*++
        !           252: 
        !           253: Routine Description:
        !           254: 
        !           255:     Record midi input.
        !           256: 
        !           257:     The input buffer size is checked
        !           258: 
        !           259:     If there is still data to be read from the device then read as
        !           260:     much as possible and complete the buffer.  Otherwise queue
        !           261:     the request.
        !           262: 
        !           263: 
        !           264: Arguments:
        !           265: 
        !           266:     pLDI - our local device data
        !           267:     pIrp - IO request packet
        !           268:     IrpStack - The current stack location
        !           269: 
        !           270: Return Value:
        !           271: 
        !           272:     STATUS_BUFFER_TOO_SMALL - Not enough room to record anything
        !           273:     STATUS_PENDING          - request queued (at least logically).
        !           274:     STATUS_NOT_SUPPORTED    - wrong device
        !           275: 
        !           276: --*/
        !           277: {
        !           278:     NTSTATUS Status;
        !           279:     PMIDI_INFO pMidi;
        !           280: 
        !           281:     pMidi = pLDI->DeviceSpecificData;
        !           282: 
        !           283:     //
        !           284:     // confirm we are doing this on the input device!
        !           285:     //
        !           286: 
        !           287:     ASSERT(pLDI->DeviceType == MIDI_IN);
        !           288: 
        !           289:     //
        !           290:     // Check size of buffer
        !           291:     //
        !           292:     if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
        !           293:         sizeof(MIDI_DD_INPUT_DATA)) {
        !           294:         dprintf1(("Supplied buffer to small for requested data"));
        !           295: 
        !           296:         return STATUS_BUFFER_TOO_SMALL;
        !           297:     }
        !           298: 
        !           299:     //
        !           300:     // Initialize data length.
        !           301:     //
        !           302: 
        !           303:     pIrp->IoStatus.Information = 0;
        !           304: 
        !           305:     //
        !           306:     // See if there's data to complete the request synchronously
        !           307:     //
        !           308: 
        !           309:     MidiEnter(pMidi);
        !           310: 
        !           311:     if (pMidi->InputBytes != 0) {
        !           312:         ASSERT(pMidi->fMidiInStarted);
        !           313: 
        !           314:         //
        !           315:         // If there was data and a free buffer someone else should
        !           316:         // have dispatched it !
        !           317:         //
        !           318: 
        !           319:         ASSERT(IsListEmpty(&pMidi->QueueHead));
        !           320: 
        !           321:         //
        !           322:         // Pull our data
        !           323:         //
        !           324: 
        !           325:         MidiRecord(pMidi, pIrp);
        !           326:         Status = STATUS_SUCCESS;
        !           327: 
        !           328:     } else {
        !           329:         //
        !           330:         // Request not completed - add it to our list and mark it pending
        !           331:         //
        !           332: 
        !           333:         SoundAddIrpToCancellableQ(&pMidi->QueueHead,
        !           334:                                   pIrp,
        !           335:                                   FALSE);   // Means insert at tail
        !           336:         dprintf3(("irp added"));
        !           337: 
        !           338:         //
        !           339:         // Mark request pending
        !           340:         //
        !           341:         pIrp->IoStatus.Status = STATUS_PENDING;
        !           342:         Status = STATUS_PENDING;
        !           343:         IoMarkIrpPending(pIrp);
        !           344:     }
        !           345: 
        !           346:     MidiLeave(pMidi);
        !           347: 
        !           348:     return Status;
        !           349: }
        !           350: 
        !           351: 
        !           352: 
        !           353: VOID
        !           354: SoundMidiInDeferred(
        !           355:     IN     PKDPC pDpc,
        !           356:     IN     PDEVICE_OBJECT pDeviceObject,
        !           357:     IN OUT PIRP pIrpDeferred,
        !           358:     IN OUT PVOID Context
        !           359: )
        !           360: /*++
        !           361: 
        !           362: Routine Description:
        !           363: 
        !           364:     Process data after a midi input interrupt.
        !           365:     If we have started a new batch of data try to grab the first
        !           366:     byte.
        !           367:     While there is data record it using MidiRecord for each buffer
        !           368:     in the queue.
        !           369:     The last buffer which has data in it is always completed since
        !           370:     we must get data to the application in real time.
        !           371: 
        !           372: 
        !           373: Arguments:
        !           374: 
        !           375:     pDpc - Dpc object
        !           376:     pDeviceObject - Our device (points to our device extension)
        !           377:     pIrpDeferred - Not meaningful here
        !           378:     Context - NULL for our Dpcs
        !           379: 
        !           380: Return Value:
        !           381: 
        !           382:     None
        !           383: 
        !           384: --*/
        !           385: {
        !           386:     //
        !           387:     // The job here is just to read the Midi data in until
        !           388:     // the top bit is set.  The data is sent to the buffers
        !           389:     // supplied by the application.
        !           390:     //
        !           391: 
        !           392:     PLOCAL_DEVICE_INFO pLDI;
        !           393:     PMIDI_INFO pMidi;
        !           394: 
        !           395:     pLDI = (PLOCAL_DEVICE_INFO)pDeviceObject->DeviceExtension;
        !           396:     pMidi = pLDI->DeviceSpecificData;
        !           397: 
        !           398:     dprintf4(("("));
        !           399: 
        !           400:     MidiEnter(pMidi);
        !           401: 
        !           402:     //
        !           403:     // If input is not running something has gone wrong.
        !           404:     // (copied from windows 3.1 driver so I assume that
        !           405:     // resetting the SB will also cancel any pending interrupt if
        !           406:     // we stop midi input)
        !           407:     //
        !           408: 
        !           409:     ASSERT(pMidi->fMidiInStarted);
        !           410: 
        !           411:     //
        !           412:     // Try to grab as many bytes as possible
        !           413:     //
        !           414: 
        !           415: 
        !           416:     while (pMidi->InputBytes < sizeof(pMidi->MidiInputByte)) {
        !           417:         if ((*pMidi->HwMidiRead)(
        !           418:             pMidi,
        !           419:             pMidi->MidiInputByte +
        !           420:                 (pMidi->InputPosition + pMidi->InputBytes) %
        !           421:                      sizeof(pMidi->MidiInputByte))) {
        !           422:             pMidi->InputBytes++;
        !           423:         } else {
        !           424:             break;
        !           425:         }
        !           426:     }
        !           427: 
        !           428:     //
        !           429:     // If there is a LOT of data coming in then we expect that
        !           430:     // the application will only supply a fairly small number of
        !           431:     // buffers at a time.  We then pass the buffers back and if
        !           432:     // there's still more the buffers are passed in again.  This way
        !           433:     // other threads get in for long messages.  On the other hand
        !           434:     // short messages need passing back quickly so 2 buffers should
        !           435:     // kept in motion.
        !           436:     //
        !           437: 
        !           438:     //
        !           439:     // Loop while there's still data and still somewhere to put it
        !           440:     //
        !           441: 
        !           442:     while (pMidi->InputBytes) {
        !           443: 
        !           444:         PIRP pIrp;
        !           445: 
        !           446:         //
        !           447:         // Get our next buffer if there is one
        !           448:         //
        !           449: 
        !           450:         pIrp = SoundRemoveFromCancellableQ(&pMidi->QueueHead);
        !           451: 
        !           452:         if (pIrp == NULL) {
        !           453:             break;
        !           454:         }
        !           455: 
        !           456: 
        !           457:         //
        !           458:         // Try filling it with data. MidiRecord will turn off the
        !           459:         // InputAvailable flag if it runs out of data.
        !           460:         //
        !           461: 
        !           462:         MidiRecord(pMidi, pIrp);
        !           463: 
        !           464:         //
        !           465:         // Complete the request
        !           466:         //
        !           467: 
        !           468:         pIrp->IoStatus.Status = STATUS_SUCCESS;
        !           469:         IoCompleteRequest(pIrp, IO_SOUND_INCREMENT);
        !           470:     }
        !           471: 
        !           472:     //
        !           473:     // Release the spin lock
        !           474:     //
        !           475: 
        !           476:     MidiLeave(pMidi);
        !           477: 
        !           478:     dprintf4((")"));
        !           479: }
        !           480: 
        !           481: 
        !           482: NTSTATUS
        !           483: SoundSetMidiInputState(
        !           484:     IN OUT PLOCAL_DEVICE_INFO pLDI,
        !           485:     IN     ULONG State
        !           486: )
        !           487: /*++
        !           488: 
        !           489: Routine Description:
        !           490: 
        !           491:     Perform the state changes for midi input :
        !           492:         MIDI_DD_RECORD - Start recording
        !           493:         MIDI_DD_TOP    - suspend recording
        !           494:         MIDI_DD_RESET  - suspend recording and cancel buffers
        !           495: 
        !           496: Arguments:
        !           497: 
        !           498:     pLDI - Pointer to local device data
        !           499:     State - the new state to set
        !           500: 
        !           501: Return Value:
        !           502: 
        !           503:     Return status for caller
        !           504: 
        !           505: --*/
        !           506: {
        !           507:     NTSTATUS Status;
        !           508:     PMIDI_INFO pMidi;
        !           509: 
        !           510:     pMidi = pLDI->DeviceSpecificData;
        !           511: 
        !           512:     switch (State) {
        !           513:     case MIDI_DD_RECORD:
        !           514: 
        !           515:         pMidi->RefTime = SoundGetTime();
        !           516: 
        !           517:         pMidi->InputBytes = 0;           // Clear buffer
        !           518:         pMidi->InputPosition = 0;
        !           519: 
        !           520:         (*pMidi->HwStartMidiIn)(pLDI->DeviceSpecificData);
        !           521:         pLDI->State = MIDI_DD_RECORDING;
        !           522:         pMidi->fMidiInStarted = TRUE;
        !           523:         Status = STATUS_SUCCESS;
        !           524:         dprintf3(("Midi Input started"));
        !           525:         break;
        !           526: 
        !           527:     case MIDI_DD_STOP:
        !           528: 
        !           529:         (*pMidi->HwStopMidiIn)(pLDI->DeviceSpecificData);
        !           530:         pLDI->State = MIDI_DD_STOPPED;
        !           531:         pMidi->fMidiInStarted = FALSE;
        !           532:         pMidi->InputBytes = 0;
        !           533:         Status = STATUS_SUCCESS;
        !           534:         dprintf3(("Midi Input stopped"));
        !           535:         break;
        !           536: 
        !           537:     case MIDI_DD_RESET:
        !           538: 
        !           539:         (*pMidi->HwStopMidiIn)(pLDI->DeviceSpecificData);
        !           540:         pLDI->State = MIDI_DD_STOPPED;
        !           541:         pMidi->fMidiInStarted = FALSE;
        !           542:         pMidi->InputBytes = 0;
        !           543: 
        !           544:         //
        !           545:         // Free any pending Irps.
        !           546:         //
        !           547: 
        !           548:         SoundFreeQ(&pMidi->QueueHead, STATUS_CANCELLED);
        !           549: 
        !           550:         Status = STATUS_SUCCESS;
        !           551:         dprintf3(("Midi Input reset"));
        !           552:         break;
        !           553: 
        !           554:     default:
        !           555: 
        !           556:         dprintf1(("Bogus set midi input state request: %08lXH", State));
        !           557:         Status = STATUS_INVALID_PARAMETER;
        !           558:         break;
        !           559:     }
        !           560: 
        !           561:     return Status;
        !           562: }
        !           563: 
        !           564: 
        !           565: 
        !           566: VOID
        !           567: MidiRecord(
        !           568:     IN  OUT PMIDI_INFO pMidi,
        !           569:     IN  OUT PIRP pIrp
        !           570: )
        !           571: /*++
        !           572: 
        !           573: Routine Description:
        !           574: 
        !           575:     Read midi input data into user's buffer.  The time stamp field
        !           576:     in the user's buffer is also filled in.  See ntddmidi.h.
        !           577: 
        !           578: Arguments:
        !           579: 
        !           580:     pMidi - Pointer to global device data
        !           581: 
        !           582: Return Value:
        !           583: 
        !           584:     None
        !           585: 
        !           586: --*/
        !           587: {
        !           588:     int i;
        !           589:     int BufferLength;
        !           590: 
        !           591:     PMIDI_DD_INPUT_DATA pData;
        !           592: 
        !           593: 
        !           594:     pData = (PMIDI_DD_INPUT_DATA)
        !           595:             MmGetSystemAddressForMdl(pIrp->MdlAddress);
        !           596: 
        !           597:     //
        !           598:     // Find out how much room we've got for our data
        !           599:     //
        !           600:     {
        !           601:         PIO_STACK_LOCATION pIrpStack;
        !           602: 
        !           603:         pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
        !           604:         BufferLength =
        !           605:             pIrpStack->Parameters.Read.Length -
        !           606:                 FIELD_OFFSET(MIDI_DD_INPUT_DATA, Data[0]);
        !           607: 
        !           608:         ASSERT(BufferLength > 0);
        !           609:     }
        !           610: 
        !           611: 
        !           612:     //
        !           613:     // Try filling it with data. MidiRecord will turn off the
        !           614:     // InputActive flag if it runs out of data.  There must be
        !           615:     // at least one byte of data available because callers are
        !           616:     // expecting to complete the Irp on return with data
        !           617:     //
        !           618: 
        !           619:     ASSERT(pMidi->InputBytes != 0);
        !           620: 
        !           621:     //
        !           622:     // Remember the time
        !           623:     //
        !           624: 
        !           625:     pData->Time = RtlLargeIntegerSubtract(SoundGetTime(), pMidi->RefTime);
        !           626: 
        !           627:     //
        !           628:     // Read bytes until exhaused or buffer full
        !           629:     //
        !           630: 
        !           631:     for (i = 0; pMidi->InputBytes != 0 && i < BufferLength; i++) {
        !           632:         //
        !           633:         // Record the byte
        !           634:         //
        !           635: 
        !           636:         pData->Data[i] = pMidi->MidiInputByte[pMidi->InputPosition];
        !           637:         pMidi->InputPosition =
        !           638:             (pMidi->InputPosition + 1) % sizeof(pMidi->MidiInputByte);
        !           639: 
        !           640:         pMidi->InputBytes--;
        !           641: 
        !           642:         dprintf4(("%2X", (ULONG)pData->Data[i]));
        !           643: 
        !           644:         //
        !           645:         // Try to read our next byte
        !           646:         //
        !           647: 
        !           648:         if (pMidi->InputBytes == 0) {
        !           649:             pMidi->InputPosition = 0;
        !           650: 
        !           651:             //
        !           652:             // Read as many bytes as we can
        !           653:             //
        !           654: 
        !           655:             while (pMidi->InputBytes < sizeof(pMidi->MidiInputByte)) {
        !           656: 
        !           657:                 if ((*pMidi->HwMidiRead)(
        !           658:                                    pMidi,
        !           659:                                    pMidi->MidiInputByte + pMidi->InputBytes)) {
        !           660:                     pMidi->InputBytes++;
        !           661:                 } else {
        !           662:                     break;
        !           663:                 }
        !           664:             }
        !           665:         }
        !           666:     }
        !           667: 
        !           668:     //
        !           669:     // Record the amount of data returned in the Irp
        !           670:     // The caller will complete the request.
        !           671: 
        !           672:     pIrp->IoStatus.Information = i + sizeof(LARGE_INTEGER);
        !           673: }
        !           674: 
        !           675: 
        !           676: 
        !           677: VOID
        !           678: SoundMidiReset(
        !           679:     IN  OUT PMIDI_INFO pMidi
        !           680: )
        !           681: /*++
        !           682: 
        !           683: Routine Description:
        !           684: 
        !           685:     Reset midi output state
        !           686: 
        !           687: Arguments:
        !           688: 
        !           689:     pMidi - Pointer to Midi device data
        !           690: 
        !           691: Return Value:
        !           692: 
        !           693:     None
        !           694: 
        !           695: --*/
        !           696: {
        !           697:     int i, j;
        !           698:     //
        !           699:     // Send a note off to each key on each channel
        !           700:     // !!! this is not recommended by the midi spec !!!
        !           701:     //
        !           702:     for (i = 0; i < 16; i++) {
        !           703: 
        !           704:         UCHAR Data[4 + 256];
        !           705: 
        !           706:         // Turn the damper pedal off (sustain)
        !           707: 
        !           708:         Data[0] = (UCHAR)(0xB0 + i);   // Control change status byte
        !           709:         Data[1] = 0x40;                   // Control number for sustain
        !           710:         Data[2] = 0x00;                   // value (0 = off)
        !           711: 
        !           712:         // Send note off for each key
        !           713: 
        !           714:         Data[3] = (UCHAR)(0x80 + i);   // Note off status byte
        !           715: 
        !           716:         for (j = 0; j < 128; j++) {
        !           717:             Data[4 + j * 2] = (UCHAR)j;     // Key number
        !           718:             Data[4 + j * 2 + 1] = 0x40;     // Velocity (64 recommended)
        !           719:         }
        !           720: 
        !           721:         (*pMidi->HwMidiOut)(pMidi, Data, sizeof(Data));
        !           722:     }
        !           723: }
        !           724: 
        !           725: 
        !           726: 
        !           727: NTSTATUS
        !           728: SoundMidiDispatch(
        !           729:     IN OUT PLOCAL_DEVICE_INFO pLDI,
        !           730:     IN    PIRP pIrp,
        !           731:     IN    PIO_STACK_LOCATION IrpStack
        !           732: )
        !           733: /*++
        !           734: 
        !           735: Routine Description:
        !           736: 
        !           737:     Midi Irp call dispatcher
        !           738: 
        !           739: Arguments:
        !           740: 
        !           741:     pLDI - Pointer to local device data
        !           742:     pIrp - Pointer to IO request packet
        !           743:     IrpStack - Pointer to current stack location
        !           744: 
        !           745: Return Value:
        !           746: 
        !           747:     Return status from dispatched routine
        !           748: 
        !           749: --*/
        !           750: {
        !           751:     NTSTATUS Status;
        !           752: 
        !           753:     Status = STATUS_SUCCESS;
        !           754: 
        !           755:     switch (IrpStack->MajorFunction) {
        !           756:     case IRP_MJ_CREATE:
        !           757:         Status = SoundSetShareAccess(pLDI, IrpStack);
        !           758:         if (NT_SUCCESS(Status) && IrpStack->FileObject->WriteAccess) {
        !           759: 
        !           760:             if (pLDI->DeviceType == MIDI_OUT) {
        !           761:                 //
        !           762:                 // We can open Midi output
        !           763:                 //
        !           764:                 pLDI->State = MIDI_DD_IDLE;
        !           765:                 dprintf3(("Opened for midi output"));
        !           766:                 Status = STATUS_SUCCESS;
        !           767:             } else {
        !           768:                 //
        !           769:                 // Open midi input
        !           770:                 // Only midi input has state data
        !           771:                 //
        !           772: 
        !           773:                 PMIDI_INFO pMidi;
        !           774:                 pMidi = pLDI->DeviceSpecificData;
        !           775: 
        !           776:                 ASSERT(IsListEmpty(&pMidi->QueueHead));
        !           777: 
        !           778:                 pLDI->State = MIDI_DD_STOPPED;
        !           779:                 ASSERT(!pMidi->fMidiInStarted);
        !           780:                 dprintf3(("Opened for midi input"));
        !           781:                 Status = STATUS_SUCCESS;
        !           782:             }
        !           783:         }
        !           784:         break;
        !           785: 
        !           786:     case IRP_MJ_CLOSE:
        !           787: 
        !           788:         Status = STATUS_SUCCESS;
        !           789: 
        !           790:         break;
        !           791: 
        !           792:     case IRP_MJ_READ:
        !           793: 
        !           794:         if (pLDI->DeviceType != MIDI_IN) {
        !           795:             Status = STATUS_INVALID_DEVICE_REQUEST;
        !           796:         } else {
        !           797:             if (IrpStack->FileObject->WriteAccess) {
        !           798:                 Status = SoundIoctlMidiRecord(pLDI, pIrp, IrpStack);
        !           799:             } else {
        !           800:                 Status = STATUS_ACCESS_DENIED;
        !           801:             }
        !           802:         }
        !           803:         break;
        !           804: 
        !           805: 
        !           806:     case IRP_MJ_DEVICE_CONTROL:
        !           807: 
        !           808:         //
        !           809:         // Check that if someone has the device open for 'write' it's
        !           810:         // marked as in use
        !           811:         //
        !           812: 
        !           813:         ASSERT(!IrpStack->FileObject->WriteAccess ||
        !           814:                (*pLDI->DeviceInit->ExclusionRoutine)(pLDI, SoundExcludeQueryOpen));
        !           815: 
        !           816:         //
        !           817:         // Dispatch the IOCTL function
        !           818:         // Note that some IOCTLs only make sense for input or output
        !           819:         // devices and not both.
        !           820:         // Note that APIs which are possibly asynchronous do not
        !           821:         // go through the Irp cleanup at the end here because they
        !           822:         // may get completed before returning here or they are made
        !           823:         // accessible to other requests by being queued.
        !           824:         //
        !           825: 
        !           826:         switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
        !           827: 
        !           828:         case IOCTL_MIDI_GET_CAPABILITIES:
        !           829:             Status = (*pLDI->DeviceInit->DevCapsRoutine)(pLDI, pIrp, IrpStack);
        !           830:             break;
        !           831: 
        !           832:         case IOCTL_MIDI_PLAY:
        !           833:             Status = SoundIoctlMidiPlay(pLDI, pIrp, IrpStack);
        !           834:             break;
        !           835: 
        !           836:         case IOCTL_MIDI_SET_STATE:
        !           837:             if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) {
        !           838:                 dprintf1(("Supplied buffer too small for expected data"));
        !           839:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           840:             } else {
        !           841:                 PULONG pState;
        !           842: 
        !           843:                 //
        !           844:                 // cast the buffer address to the pointer type we want
        !           845:                 //
        !           846: 
        !           847:                 pState = (PULONG)pIrp->AssociatedIrp.SystemBuffer;
        !           848: 
        !           849:                 if (pLDI->DeviceType == MIDI_IN) {
        !           850:                     Status = SoundSetMidiInputState(pLDI, *pState);
        !           851:                 } else {
        !           852: 
        !           853:                     switch (*pState) {
        !           854:                     case MIDI_DD_RESET:
        !           855:                         //
        !           856:                         // Sent note-off to all notes
        !           857:                         //
        !           858:                         SoundMidiReset(
        !           859:                             (PMIDI_INFO)pLDI->DeviceSpecificData);
        !           860: 
        !           861:                         break;
        !           862: 
        !           863:                     default:
        !           864:                         Status = STATUS_INVALID_PARAMETER;
        !           865:                     }
        !           866:                 }
        !           867:             }
        !           868:         break;
        !           869: 
        !           870:         case IOCTL_MIDI_GET_STATE:
        !           871:             Status = SoundIoctlGetMidiState(pLDI, pIrp, IrpStack);
        !           872:             break;
        !           873: 
        !           874: 
        !           875:         default:
        !           876:             dprintf2(("Unimplemented IOCTL (%08lXH) requested", IrpStack->Parameters.DeviceIoControl.IoControlCode));
        !           877:             Status = STATUS_INVALID_DEVICE_REQUEST;
        !           878:             break;
        !           879:         }
        !           880:         break;
        !           881: 
        !           882: 
        !           883:     case IRP_MJ_CLEANUP:
        !           884:         if (IrpStack->FileObject->WriteAccess) {
        !           885: 
        !           886:             PMIDI_INFO pMidi;
        !           887: 
        !           888:             pMidi = pLDI->DeviceSpecificData;
        !           889: 
        !           890:             switch (pLDI->DeviceType) {
        !           891:             case MIDI_OUT:
        !           892:                 SoundMidiReset(pMidi);
        !           893:                 break;
        !           894: 
        !           895:             case MIDI_IN:
        !           896:                 (*pMidi->HwStopMidiIn)(pLDI->DeviceSpecificData);
        !           897:                 pMidi->fMidiInStarted = FALSE;
        !           898:                 pMidi->InputBytes = 0;
        !           899:                 SoundFreeQ(&pMidi->QueueHead, STATUS_CANCELLED);
        !           900:                 break;
        !           901:             }
        !           902:             pLDI->PreventVolumeSetting = FALSE;
        !           903: 
        !           904:             (*pLDI->DeviceInit->ExclusionRoutine)(pLDI, SoundExcludeClose);
        !           905: 
        !           906:         } else {
        !           907:             Status = STATUS_SUCCESS;
        !           908:         }
        !           909:         break;
        !           910: 
        !           911: 
        !           912:     default:
        !           913:         dprintf1(("Unimplemented major function requested: %08lXH", IrpStack->MajorFunction));
        !           914:         Status = STATUS_INVALID_DEVICE_REQUEST;
        !           915:         break;
        !           916:     }
        !           917: 
        !           918:     return Status;
        !           919: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.