int MsgQueueConnection::send(uint num_bytes, const char *src, bool immediate_send_hint) { if (!is_connected()) { LOG("SKYPE ERROR - LocalServerConnection::send(), not connected"); return -1; } // message is copied because STTester modifies the buffer and needs a non-const //SEString msg = message; //STTester_ON_OUTGOING_EVENT(msg); message_buf msg_buf; //loop through msg // int tot = num_bytes; int offset = 0; do { //send msg to queue in chunks msg_buf.len = min(tot, KMaxQueueSlotSize); Mem::Copy(msg_buf.buf, (const char*)src+offset, msg_buf.len); TInt err = GetOutQueue().Send( msg_buf ); LOG("TRANSPORT: MsgQueueConnection::send - Buffer sent, err: " + SEString::from(err)); // If we hit exactly the maximum slot size, skypekit expects more data and will "hang". // To prevent this we send a terminating message with length 0. (AAAXL-115). if ( tot == KMaxQueueSlotSize ) { message_buf emptyBuf; emptyBuf.len = 0; TInt err = GetOutQueue().Send( emptyBuf ); LOG("TRANSPORT: MsgQueueConnection::send - Empty buffer sent, err: " + SEString::from(err)); } tot -= msg_buf.len; offset += msg_buf.len; } while (tot>0); #if 0 if (debug) LOG("TRANSPORT: Wrote message \"" + msg + "\""); #endif return offset; }
VOID VIOSerialReclaimConsumedBuffers(IN PVIOSERIAL_PORT Port) { WDFREQUEST request; PSINGLE_LIST_ENTRY iter; PVOID buffer; UINT len; struct virtqueue *vq = GetOutQueue(Port); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_QUEUEING, "--> %s\n", __FUNCTION__); if (vq) { while ((buffer = virtqueue_get_buf(vq, &len)) != NULL) { if (Port->PendingWriteRequest != NULL) { request = Port->PendingWriteRequest; Port->PendingWriteRequest = NULL; if (WdfRequestUnmarkCancelable(request) != STATUS_CANCELLED) { WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, (size_t)WdfRequestGetInformation(request)); } else { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_QUEUEING, "Request %p was cancelled.\n", request); } } iter = &Port->WriteBuffersList; while (iter->Next != NULL) { PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter->Next, WRITE_BUFFER_ENTRY, ListEntry); if (buffer == entry->Buffer) { iter->Next = entry->ListEntry.Next; ExFreePoolWithTag(buffer, VIOSERIAL_DRIVER_MEMORY_TAG); ExFreePoolWithTag(entry, VIOSERIAL_DRIVER_MEMORY_TAG); } else { iter = iter->Next; } }; Port->OutVqFull = FALSE; } } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_QUEUEING, "<-- %s Full: %d\n", __FUNCTION__, Port->OutVqFull); }
////////////////////////////////////////////////////////////////////////// // Worker thread polls QAudioOutput device to see if there is room // to put more data into it and then calls GetOutQueue(..) to get more data. // This thread was needed because the normal "pull" mechanism of Qt does // not work very well since it depends on the main process signal-slot event // queue and you get dropouts if the GUI gets busy. ////////////////////////////////////////////////////////////////////////// void CSoundOut::run() { while(!m_ThreadQuit ) //execute loop until quit flag set { if( (QAudio::IdleState == m_pAudioOutput->state() ) || (QAudio::ActiveState == m_pAudioOutput->state() ) ) { //Process sound data while soundcard is active and no errors unsigned int len = m_pAudioOutput->bytesFree(); //in bytes if( len>0 ) { //limit size to SOUND_WRITEBUFSIZE if(len > SOUND_WRITEBUFSIZE) len = SOUND_WRITEBUFSIZE; if(m_StereoOut) { len &= ~(0x03); //keep on 4 byte chunks GetOutQueue( len/4, (TYPESTEREO16*)m_pData ); } else { len &= ~(0x01); //keep on 2 byte chunks GetOutQueue( len/2, (TYPEMONO16*)m_pData ); } m_pOutput->write((char*)m_pData,len); } else //no room in sound card output buffer so wait { //not good but no other wait or blocking mechanism available msleep(m_BlockTime); } } else { //bail out if error occurs qDebug()<<"SoundOut Error"; #if 0 //RRK if(m_pParent) ((CSdrInterface*)m_pParent)->SendIOStatus(CSdrInterface::ERROR); #endif m_ThreadQuit = true; } } qDebug()<<"sound thread exit"; }
size_t VIOSerialSendBuffers(IN PVIOSERIAL_PORT Port, IN PVOID Buffer, IN size_t Length) { struct virtqueue *vq = GetOutQueue(Port); struct VirtIOBufferDescriptor sg[QUEUE_DESCRIPTORS]; PVOID buffer = Buffer; size_t length = Length; int out = 0; int ret; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Buffer: %p Length: %d\n", __FUNCTION__, Buffer, Length); if (BYTES_TO_PAGES(Length) > QUEUE_DESCRIPTORS) { return 0; } while (length > 0) { sg[out].physAddr = MmGetPhysicalAddress(buffer); sg[out].length = min(length, PAGE_SIZE); buffer = (PVOID)((LONG_PTR)buffer + sg[out].length); length -= sg[out].length; out += 1; } WdfSpinLockAcquire(Port->OutVqLock); ret = virtqueue_add_buf(vq, sg, out, 0, Buffer, NULL, 0); virtqueue_kick(vq); if (ret >= 0) { Port->OutVqFull = (ret == 0); } else { Length = 0; TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "Error adding buffer to queue (ret = %d)\n", ret); } WdfSpinLockRelease(Port->OutVqLock); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); return Length; }