Annotation of ntddk/src/mmedia/soundlib/midi.c, revision 1.1.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.