void RemoveListener( LPARDUINOLISTENER listener )
	{
	LOG(MAINFUNC,"Arduino::RemoveListener");
	listener_lock.Lock();
	int i=0;
	while ( (i<listeners_count) && (listeners[i].callback!=listener) )
		i++;
	if (listeners[i].callback==listener)
		{
		// remove entry so that entries after this are simply moved 1 entry lower
		while (i<listeners_count-1)
			{
			listeners[i].callback = listeners[i+1].callback;
			listeners[i].data = listeners[i+1].data;
			i++;
			}
		listeners_count--;
		listener_lock.Unlock();
		LOG(MAINFUNC,"Arduino::RemoveListener - removed successfully");
		}
	else
		{
		listener_lock.Unlock();
		LOG(ERR,"Arduino::RemoveListener - no such listener found!");
		}
	}
Beispiel #2
0
static status_t
device_open(const char* name, uint32 /*flags*/, void** cookie)
{
	status_t status = B_OK;

	TRACE("device_open() - name: %s\n", name);

	// Find the device name in the list of devices.

	int32 i = 0;
	while (gDeviceNames[i] != NULL && (strcmp(name, gDeviceNames[i]) != 0))
		i++;

	if (gDeviceNames[i] == NULL)
		return B_BAD_VALUE;		// device name not found in list of devices

	DeviceInfo& di = gDeviceInfo[i];

	gLock.Acquire();	// make sure no one else has write access to common data

	if (di.openCount == 0)
		status = InitDevice(di);

	gLock.Release();

	if (status == B_OK) {
		di.openCount++;		// mark device open
		*cookie = &di;		// send cookie to opener
	}

	TRACE("device_open() returning 0x%lx,  open count: %ld\n", status,
		di.openCount);
	return status;
}
bool IsConnected()
{
	init_lock.Lock();
	LOG(HELPERFUNC,"Arduino::IsConnected %d",isConnected);
	bool isconnected = isConnected;
	init_lock.Unlock();
	return isconnected;
}
int CloseDevice()
{
	LOG(MAINFUNC,"Arduino::CloseDevice");
	init_lock.Lock();
	CloseHandle(hCommPort);
	hCommPort=INVALID_HANDLE_VALUE;
	isConnected=0;
	CloseHandle(ghWriteCompleteEvent);
	init_lock.Unlock();
	return 0;
}
int Send(const char * cmd)
	{
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - msg [%s]",cmd);
	write_lock.Lock();

	DWORD dwwritten = 0; 
	int len = strlen(cmd);

	char buf[256];
	if(len>256)
	{
		write_lock.Unlock();
		LOG(ERR,"Arduino::Send: Msg too long!");
		return -1;
	}

#ifndef USBCAN_PROTOCOL
	// surround message with {}
	sprintf_s(buf,256,"{%s}\r",cmd);
	len += 3;	// {}\r
#else
	sprintf_s(buf,256,"%s\r",cmd);
	len += 1;	// \r
#endif

	if  ( (dwwritten=blockingWrite(buf, len )) == -1)
		{
		LOG(ERR,"Arduino::SendMsg - Blocking write failed ! \n");
		write_lock.Unlock();
		return -1;
		}

	if (dwwritten != len)
		{
		write_lock.Unlock();
		LOG(ERR,"Arduino::SendMsg - Write didn't finish (%d out of %d bytes sent)\n", dwwritten,len);
		DWORD   dwErrors;
		COMSTAT comStat;
		ClearCommError(hCommPort, &dwErrors, &comStat);
		LOG(ERR,"Arduino::SendMsg - ClearCommError: Error flags: 0x%x, bytes in output queue: %d\n", dwErrors, comStat.cbOutQue);		
		return -1;
		}
	write_lock.Unlock();

#ifndef USBCAN_PROTOCOL
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - completed succefully: %d written (%d bytes original)",dwwritten,dwwritten-3);
	return dwwritten-3;
#else
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - completed succefully: %d written (%d bytes original)",dwwritten,dwwritten-1);
	return dwwritten-1;
#endif
}
Beispiel #6
0
void
uninit_driver(void)
{
	// Free the driver data.

	gLock.Delete();
	put_module(B_PCI_MODULE_NAME);	// put the pci module away
}
Beispiel #7
0
static status_t
device_free(void* dev)
{
	DeviceInfo& di = *((DeviceInfo*)dev);
	SharedInfo& si = *(di.sharedInfo);
	pci_info& pciInfo = di.pciInfo;

	TRACE("enter device_free()\n");

	gLock.Acquire();		// lock driver

	// If opened multiple times, merely decrement the open count and exit.

	if (di.openCount <= 1) {
		DisableVBI();		// disable & clear any pending interrupts

		if (si.bInterruptAssigned) {
			remove_io_interrupt_handler(pciInfo.u.h0.interrupt_line,
				InterruptHandler, &di);
		}

		// Delete the semaphores, ignoring any errors because the owning team
		// may have died.
		if (si.vertBlankSem >= 0)
			delete_sem(si.vertBlankSem);
		si.vertBlankSem = -1;

		UnmapDevice(di);	// free regs and frame buffer areas

		delete_area(di.sharedArea);
		di.sharedArea = -1;
		di.sharedInfo = NULL;
	}

	if (di.openCount > 0)
		di.openCount--;		// mark device available

	gLock.Release();	// unlock driver

	TRACE("exit device_free() openCount: %ld\n", di.openCount);
	return B_OK;
}
int RegisterListener( LPARDUINOLISTENER listener, void *data )
	{
	LOG(MAINFUNC,"Arduino::RegisterListener");
	listener_lock.Lock();
	if (listeners_count<MAX_LISTENERS)
		{
		listeners[listeners_count].callback = listener;
		listeners[listeners_count].data = data;
		listeners_count++;
		listener_lock.Unlock();
		LOG(MAINFUNC,"Arduino::RegisterListener - added succesfully");
		}
	else
		{
		listener_lock.Unlock();
		LOG(ERR,"Arduino::RegisterListener - too many listeners!");
		return -1;
		}
	return 0;
	}
Beispiel #9
0
status_t device_free(void *dev)
{
    LogFlowFunc(("device_free\n"));

    DeviceInfo& di = *(DeviceInfo *)dev;
    gLock.Acquire();

    if (di.openCount <= 1)
    {
        // TODO deinit device!
        delete_area(di.sharedArea);
        di.sharedArea = -1;
        di.sharedInfo = NULL;
    }

    if (di.openCount > 0)
        di.openCount--;

    gLock.Release();

    return B_OK;
}
Beispiel #10
0
status_t
init_driver(void)
{
	// Get handle for the pci bus.

	if (get_module(B_PCI_MODULE_NAME, (module_info**)&gPCI) != B_OK)
		return B_ERROR;

	status_t status = gLock.Init("ATI driver lock");
	if (status < B_OK)
		return status;

	// Get info about all the devices supported by this driver.

	uint32 pciIndex = 0;
	uint32 count = 0;

	while (count < MAX_DEVICES) {
		DeviceInfo& di = gDeviceInfo[count];

		const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, di.pciInfo);
		if (pDevice == NULL)
			break;			// all supported devices have been obtained

		// Compose device name.
		sprintf(di.name, "graphics/" DEVICE_FORMAT,
				  di.pciInfo.vendor_id, di.pciInfo.device_id,
				  di.pciInfo.bus, di.pciInfo.device, di.pciInfo.function);
		TRACE("init_driver() match found; name: %s\n", di.name);

		gDeviceNames[count] = di.name;
		di.openCount = 0;		// mark driver as available for R/W open
		di.sharedArea = -1;		// indicate shared area not yet created
		di.sharedInfo = NULL;
		di.pChipInfo = pDevice;
		count++;
		pciIndex++;
	}

	gDeviceNames[count] = NULL;	// terminate list with null pointer

	TRACE("init_driver() %ld supported devices\n", count);

	return B_OK;
}
Beispiel #11
0
void uninit_driver()
{
    LogFlowFunc(("uninit_driver\n"));
    gLock.Delete();
    put_module(VBOXGUEST_MODULE_NAME);
}
Beispiel #12
0
status_t init_driver()
{
    LogFlowFunc(("init_driver\n"));

    gLock.Init("VBoxVideo driver lock");

    uint32 pciIndex = 0;

    while (gPCI->get_nth_pci_info(pciIndex, &gDeviceInfo.pciInfo) == B_OK)
    {
        if (gDeviceInfo.pciInfo.vendor_id == VENDOR_ID && gDeviceInfo.pciInfo.device_id == DEVICE_ID)
        {
            sprintf(gDeviceInfo.name, "graphics/" DEVICE_FORMAT,
                    gDeviceInfo.pciInfo.vendor_id, gDeviceInfo.pciInfo.device_id,
                    gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function);
            TRACE("found device %s\n", gDeviceInfo.name);

            gCanHasDevice = true;
            gDeviceInfo.openCount = 0;

            size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7;
            gDeviceInfo.sharedArea = create_area("vboxvideo shared info",
                                                 (void **)&gDeviceInfo.sharedInfo, B_ANY_KERNEL_ADDRESS,
                                                 ROUND_TO_PAGE_SIZE(sharedSize), B_FULL_LOCK,
                                                 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);

            uint16_t width, height, vwidth, bpp, flags;
            VBoxVideoGetModeRegisters(&width, &height, &vwidth, &bpp, &flags);

            gDeviceInfo.sharedInfo->currentMode.space = get_color_space_for_depth(bpp);
            gDeviceInfo.sharedInfo->currentMode.virtual_width = width;
            gDeviceInfo.sharedInfo->currentMode.virtual_height = height;
            gDeviceInfo.sharedInfo->currentMode.h_display_start = 0;
            gDeviceInfo.sharedInfo->currentMode.v_display_start = 0;
            gDeviceInfo.sharedInfo->currentMode.flags = 0;
            gDeviceInfo.sharedInfo->currentMode.timing.h_display = width;
            gDeviceInfo.sharedInfo->currentMode.timing.v_display = height;
            /* Not used, but this makes a reasonable-sounding refresh rate show in screen prefs: */
            gDeviceInfo.sharedInfo->currentMode.timing.h_total = 1000;
            gDeviceInfo.sharedInfo->currentMode.timing.v_total = 1;
            gDeviceInfo.sharedInfo->currentMode.timing.pixel_clock = 850;

            /* Map the PCI memory space */
            uint32 command_reg = gPCI->read_pci_config(gDeviceInfo.pciInfo.bus,
                                                       gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function,  PCI_command, 2);
            command_reg |= PCI_command_io | PCI_command_memory | PCI_command_master;
            gPCI->write_pci_config(gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device,
                                   gDeviceInfo.pciInfo.function, PCI_command, 2, command_reg);

            gDeviceInfo.sharedInfo->framebufferArea = map_physical_memory("vboxvideo framebuffer",
                                                      (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0],
                                                      gDeviceInfo.pciInfo.u.h0.base_register_sizes[0], B_ANY_KERNEL_BLOCK_ADDRESS,
                                                      B_READ_AREA | B_WRITE_AREA, &(gDeviceInfo.sharedInfo->framebuffer));
            vm_set_area_memory_type(gDeviceInfo.sharedInfo->framebufferArea,
                                    (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0], B_MTR_WC);
            break;
        }

        pciIndex++;
    }

    return B_OK;
}
namespace Arduino {


	Benaphore init_wait_lock;

	Benaphore init_lock;
	Benaphore listener_lock;

	Benaphore write_lock;

	bool isConnected=0;

	HANDLE hCommPort = INVALID_HANDLE_VALUE;

	OVERLAPPED read_overlap;
	OVERLAPPED write_overlap;
	OVERLAPPED comm_event_overlap;

	HANDLE ghWriteCompleteEvent;

	DWORD dwCommEventMask;	

	typedef struct {
		LPARDUINOLISTENER callback;
		void * data;		
	} listener_struct;

	listener_struct listeners[MAX_LISTENERS];
	int listeners_count=0;

	char collectionbuf[MAX_COLLECTION_BUF_SIZE+1];
	char buffer[MAX_READ_BUF_SIZE];
	int cbufi=0;


int RegisterListener( LPARDUINOLISTENER listener, void *data )
	{
	LOG(MAINFUNC,"Arduino::RegisterListener");
	listener_lock.Lock();
	if (listeners_count<MAX_LISTENERS)
		{
		listeners[listeners_count].callback = listener;
		listeners[listeners_count].data = data;
		listeners_count++;
		listener_lock.Unlock();
		LOG(MAINFUNC,"Arduino::RegisterListener - added succesfully");
		}
	else
		{
		listener_lock.Unlock();
		LOG(ERR,"Arduino::RegisterListener - too many listeners!");
		return -1;
		}
	return 0;
	}

void RemoveListener( LPARDUINOLISTENER listener )
	{
	LOG(MAINFUNC,"Arduino::RemoveListener");
	listener_lock.Lock();
	int i=0;
	while ( (i<listeners_count) && (listeners[i].callback!=listener) )
		i++;
	if (listeners[i].callback==listener)
		{
		// remove entry so that entries after this are simply moved 1 entry lower
		while (i<listeners_count-1)
			{
			listeners[i].callback = listeners[i+1].callback;
			listeners[i].data = listeners[i+1].data;
			i++;
			}
		listeners_count--;
		listener_lock.Unlock();
		LOG(MAINFUNC,"Arduino::RemoveListener - removed successfully");
		}
	else
		{
		listener_lock.Unlock();
		LOG(ERR,"Arduino::RemoveListener - no such listener found!");
		}
	}


bool IsConnected()
{
	init_lock.Lock();
	LOG(HELPERFUNC,"Arduino::IsConnected %d",isConnected);
	bool isconnected = isConnected;
	init_lock.Unlock();
	return isconnected;
}


int blockingWrite( char * buf, unsigned int len )
{
	DWORD dwwritten = 0, dwErr;
	memset(&write_overlap, 0, sizeof(write_overlap));
	write_overlap.hEvent = ghWriteCompleteEvent; // CreateEvent(NULL, FALSE, FALSE, NULL); // TRUE, NULL); // for some reason event 
	unsigned int fSuccess = WriteFile(hCommPort, buf, len, &dwwritten, &write_overlap);
	if (!fSuccess) 
	{
		dwErr = GetLastError();
		if (dwErr != ERROR_IO_PENDING)
			{
			LOG(ERR,"Arduino::SendMsg - Write failed (%d)\n", GetLastError());
			return -1;
			}

		// Pending IO -> Wait for the result
	if (!GetOverlappedResult(hCommPort, &write_overlap, &dwwritten, TRUE))
		{
		LOG(ERR,"Arduino::SendMsg - Error waiting for write to finish (%d)\n", GetLastError());
		return -1;
		}

	} 
	
	return dwwritten;
}


int OpenDevice( int com_port, int baud_rate, int disable_DTR )
{
	LOG(MAINFUNC,"Arduino::OpenDevice - com port %d, baud_rate %d, disable DTR %d",com_port,baud_rate,disable_DTR);
	init_lock.Lock();
	if (isConnected)
		{
		init_lock.Unlock();
		LOG(ERR,"Arduino::OpenDevice - already connected!");
		return ARDUINO_ALREADY_CONNECTED;
		}

	if (com_port==-1)
		{
		com_port = ARDUINO_DEFAULT_COM_PORT;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to comport %d",com_port);
		}
	if (baud_rate==-1)
		{
		baud_rate = ARDUINO_DEFAULT_BAUD_RATE;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to baud rate %d",baud_rate);
		}
	if (disable_DTR==-1)
		{
		disable_DTR = ARDUINO_DEFAULT_DTR_DISABLED;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to dtr disabled=%d",disable_DTR);
		}
	

	TCHAR COMx[32];
	int n = _stprintf_s(COMx, 32, _T("\\\\.\\COM%d"),com_port);
	long int err;
	BOOL fSuccess;	
	DCB dcb;

	LOG(MAINFUNC,"Arduino::OpenDevice - creating file handle for com port");
	hCommPort = CreateFile(
	COMx,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_WRITE, // 0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL
    );

	if (hCommPort == INVALID_HANDLE_VALUE) 
	{
		err=GetLastError();
		if (err==ERROR_ALREADY_EXISTS)
			{
			LOG(ERR,"Arduino::OpenDevice - Already opened by other process!");
			init_lock.Unlock();
			return ARDUINO_IN_USE;
			} 
		else
			{
			LOG(ERR,"Arduino::OpenDevice - CreateFileA failed %d!",err);
			init_lock.Unlock();
			return ARDUINO_OPEN_FAILED;
			}
	}

	LOG(MAINFUNC,"Arduino::OpenDevice - getting comm state");
	fSuccess = GetCommState(hCommPort, &dcb);

	if (!fSuccess) 
	{
		LOG(ERR,"Arduino::OpenDevice - GetCommStateFailed %d", err=GetLastError());
		PrintError(err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		init_lock.Unlock();
		return ARDUINO_GET_COMMSTATE_FAILED;
	}

	LOG(MAINFUNC,"Arduino::OpenDevice - setting comm state");
	dcb.BaudRate = baud_rate;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.fDtrControl = (disable_DTR==1 ? DTR_CONTROL_DISABLE : DTR_CONTROL_ENABLE);	// to prevent Arduino from reseting when first sending something
		
	fSuccess = SetCommState(hCommPort, &dcb);
	if (!fSuccess) 
	{
		err=GetLastError();
		LOG(ERR,"Arduino::OpenDevice - SetCommStateFailed %d", err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		PrintError(err);
		init_lock.Unlock();
		return ARDUINO_SET_COMMSTATE_FAILED;
	}


	LOG(MAINFUNC,"Arduino::OpenDevice - enable listening to comm events");
	DWORD      dwStoredFlags;
	// listen only for events regarding errors and receive buffer
	dwStoredFlags = /*EV_BREAK | EV_CTS |*/ EV_DSR | /* EV_ERR | EV_RING | EV_RLSD | */ EV_RXCHAR /* | EV_RXFLAG | EV_TXEMPTY*/ ;
	if (!SetCommMask(hCommPort, dwStoredFlags))
	{
		err=GetLastError();
		LOG(ERR,"Arduino::OpenDevice - Error setting communications mask (err %d); abort!", err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		PrintError(err);
		init_lock.Unlock();
		return ARDUINO_SET_COMMMASK_FAILED;
	}

	// create event for write completed
	if ((ghWriteCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
	{
		LOG(ERR,"Arduino::OpenDevice - Create 'Write Complete Event' failed (err %d); abort!", GetLastError());
		return ARDUINO_CREATE_EVENT_FAILED;
	}


	blockingWrite("\r\r\r",3);

	isConnected=true;

#ifdef USBCAN_PROTOCOL
	Send("Z0");	// we are not interested in time stamps, we generate our own
#else
	Send(":ping");
#endif

	init_lock.Unlock();
	LOG(MAINFUNC,"Arduino::OpenDevice - port configured");
	return ARDUINO_INIT_OK;
}


int CloseDevice()
{
	LOG(MAINFUNC,"Arduino::CloseDevice");
	init_lock.Lock();
	CloseHandle(hCommPort);
	hCommPort=INVALID_HANDLE_VALUE;
	isConnected=0;
	CloseHandle(ghWriteCompleteEvent);
	init_lock.Unlock();
	return 0;
}


int Send(const char * cmd)
	{
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - msg [%s]",cmd);
	write_lock.Lock();

	DWORD dwwritten = 0; 
	int len = strlen(cmd);

	char buf[256];
	if(len>256)
	{
		write_lock.Unlock();
		LOG(ERR,"Arduino::Send: Msg too long!");
		return -1;
	}

#ifndef USBCAN_PROTOCOL
	// surround message with {}
	sprintf_s(buf,256,"{%s}\r",cmd);
	len += 3;	// {}\r
#else
	sprintf_s(buf,256,"%s\r",cmd);
	len += 1;	// \r
#endif

	if  ( (dwwritten=blockingWrite(buf, len )) == -1)
		{
		LOG(ERR,"Arduino::SendMsg - Blocking write failed ! \n");
		write_lock.Unlock();
		return -1;
		}

	if (dwwritten != len)
		{
		write_lock.Unlock();
		LOG(ERR,"Arduino::SendMsg - Write didn't finish (%d out of %d bytes sent)\n", dwwritten,len);
		DWORD   dwErrors;
		COMSTAT comStat;
		ClearCommError(hCommPort, &dwErrors, &comStat);
		LOG(ERR,"Arduino::SendMsg - ClearCommError: Error flags: 0x%x, bytes in output queue: %d\n", dwErrors, comStat.cbOutQue);		
		return -1;
		}
	write_lock.Unlock();

#ifndef USBCAN_PROTOCOL
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - completed succefully: %d written (%d bytes original)",dwwritten,dwwritten-3);
	return dwwritten-3;
#else
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::SendMsg - completed succefully: %d written (%d bytes original)",dwwritten,dwwritten-1);
	return dwwritten-1;
#endif
}




int Listen( HANDLE CommEventHandle )
{
	memset(&comm_event_overlap, 0, sizeof(comm_event_overlap));
	comm_event_overlap.hEvent = CommEventHandle; // comm event handle
	int ret;
//	if (!ReadFileEx(hCommPort, buffer,1, &read_overlap, (LPOVERLAPPED_COMPLETION_ROUTINE)&ReadRequestCompleted))
	ret=WaitCommEvent(hCommPort,&dwCommEventMask,&comm_event_overlap);
	if (!ret)
	{
		ret = GetLastError();
		if (ret != ERROR_IO_PENDING) 
		{
		LOG(ERR,"Arduino::WaitCommEvent error: %d",ret);
		return ret;
		}
	}
	return 0;
}


void MsgReceived( char * msg_buf, int len )
{
	LOG(ARDUINO_MSG,"Arduino::MsgReceived: read: %d bytes: [%s]",len,msg_buf);
//	LOG(ARDUINO_MSG_VERBOSE,"  Msg: [%s]",msg_buf);

#ifndef USBCAN_PROTOCOL
	if ( (msg_buf[0]=='{') && (msg_buf[len-1]=='}') )
	{
		// get rid of wavy brackets
		msg_buf++;
		len--;
		msg_buf[len-1]=0;
#endif

		// Callback for each listener
		int accepted=0;
		for (int i=0;i<listeners_count;i++)
		{
			if (listeners[i].callback(msg_buf,len,listeners[i].data))
				accepted++;
		}
		if (!accepted)
			{
			LOG(ERR,"Arduino::MsgReceived: Warning! None of the listeners accepted the message!");
			}
#ifndef USBCAN_PROTOCOL
	}
	else
	{
		LOG(ERR,"Arduino::MsgReceived: Msg not inside {} ! -- ignoring [%s]",msg_buf);
	}
#endif
}


// Parses received message, each separated by newline: Appends collectionbuf until newline is reached, then calls MsgReceived to let each listener handle message according
// to each protocol needs. Collectionbuf is then cleared and parsing can continue until there's no more bytes to read. If newline is not reached in the end, the chars received
// after previous newline will stay on collectionbuf to wait for next ReadRequestCompleted.
VOID CALLBACK ReadRequestCompleted( DWORD errorCode, DWORD bytesRead, LPVOID overlapped )
{
	buffer[bytesRead]=0;
	LOG(ARDUINO_MSG_VERBOSE,"Arduino::ReadRequestCompleted: errorCode %d, read: %d bytes: [%s]\n",errorCode,bytesRead,buffer);
	if (bytesRead>0)
	{
		unsigned int i=0;

		while (i<bytesRead) 
		{
			// handle one message  (messages separated by newline)
			while ((cbufi<MAX_COLLECTION_BUF_SIZE) && (i<bytesRead) && (buffer[i]!='\r') )
			{
				// line feeds are ignored
				if (buffer[i]!='\n')
					collectionbuf[cbufi++] = buffer[i++];
				else
					i++;
			}
			// If we have reached end of line, handle the message. However if collectionbuf has reached is maximum size, handle it as a whole message (shouldn't happen, but just in case). 
			// Collectionbuf is cleared in the end to make space for new messages
			if ( (buffer[i]=='\r') || (cbufi==MAX_COLLECTION_BUF_SIZE) )
				{
				collectionbuf[cbufi]=0;
				if (cbufi>0)
					MsgReceived(collectionbuf,cbufi);
				cbufi=0;
				}
			// ignore empty lines
			if ( (buffer[i]=='\n') || (buffer[i]=='\r') )
				i++;
		}
	 }
	// restart the read
//	ReadOperation();
}


int BlockingRead( int bytes )
{
	LOG(HELPERFUNC,"Arduino::BlockingRead: read %d bytes",bytes);
	//	if (!ReadFileEx(hCommPort, buffer,1, &read_overlap, (LPOVERLAPPED_COMPLETION_ROUTINE)&ReadRequestCompleted))
	DWORD err=0;
	DWORD bytesRead;
	DWORD bytesLeft = bytes;
	while ( (bytesLeft>0) && (!err) )
	{
		DWORD bytesToRead = ( bytesLeft>MAX_READ_BUF_SIZE ? MAX_READ_BUF_SIZE : bytesLeft );

		memset(&read_overlap, 0, sizeof(read_overlap));
		err=ReadFileEx(hCommPort, buffer,bytesToRead, &read_overlap,NULL);
		if (!err) 
		{
			err = GetLastError();
			if (err!=ERROR_IO_PENDING)
			{
				LOG(ERR,"Arduino::BlockingRead: ReadFileEx error! %d",err);
				return err;
			} else
				err=NULL; // omit ERROR_IO_PENDING since we want to continue reading
		}		
		if (!GetOverlappedResult(hCommPort, &read_overlap, &bytesRead, TRUE))
		{
			LOG(ERR,"Arduino::BlockingRead: GetOverlappedResult error! %d",err=GetLastError());
			return err;
		}
		if (bytesRead != bytes)
		{
			LOG(ERR,"Arduino::BlockingRead: bytes read (%d) != bytes requested (%d)! Still handling the bytes we got..",bytesRead,bytes);
		}
		ReadRequestCompleted(0,bytesRead,&read_overlap);
		bytesLeft -= bytesRead;
	}
	return STATUS_NOERROR;
}


int HandleCommEvent()
{
	// Get and clear current errors on the port.
	DWORD   dwErrors;
	COMSTAT comStat;
	DWORD ret;
	if (!ClearCommError(hCommPort, &dwErrors, &comStat))
	{
		LOG(ERR,"Arduino::HandleCommEvent - error calling ClearCommError: %d",ret=GetLastError());
		return ret;
	}
	if (dwErrors & CE_FRAME)
	{
		LOG(ERR,"Arduino::HandleCommEvent - hardware detected a framing error!");
	} 
	if (dwErrors & CE_OVERRUN)
	{
		LOG(ERR,"Arduino::HandleCommEvent - A character-buffer overrun has occurred. The next character is lost!");
	}
	if (dwErrors & CE_RXOVER)
	{
		LOG(ERR,"Arduino::HandleCommEvent - An input buffer overflow has occurred!");
	}
	if (dwErrors & CE_RXPARITY)
	{
		LOG(ERR,"Arduino::HandleCommEvent - hardware detected a parity error!");
	} 

	if (comStat.cbInQue>0)
	{
		LOG(HELPERFUNC,"Arduino::HandleCommEvent - %d bytes in receiving buffer!",comStat.cbInQue);
		return BlockingRead(comStat.cbInQue);
	}
	return 0;
} 

}
int OpenDevice( int com_port, int baud_rate, int disable_DTR )
{
	LOG(MAINFUNC,"Arduino::OpenDevice - com port %d, baud_rate %d, disable DTR %d",com_port,baud_rate,disable_DTR);
	init_lock.Lock();
	if (isConnected)
		{
		init_lock.Unlock();
		LOG(ERR,"Arduino::OpenDevice - already connected!");
		return ARDUINO_ALREADY_CONNECTED;
		}

	if (com_port==-1)
		{
		com_port = ARDUINO_DEFAULT_COM_PORT;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to comport %d",com_port);
		}
	if (baud_rate==-1)
		{
		baud_rate = ARDUINO_DEFAULT_BAUD_RATE;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to baud rate %d",baud_rate);
		}
	if (disable_DTR==-1)
		{
		disable_DTR = ARDUINO_DEFAULT_DTR_DISABLED;
		LOG(MAINFUNC,"Arduino::OpenDevice - defaulting to dtr disabled=%d",disable_DTR);
		}
	

	TCHAR COMx[32];
	int n = _stprintf_s(COMx, 32, _T("\\\\.\\COM%d"),com_port);
	long int err;
	BOOL fSuccess;	
	DCB dcb;

	LOG(MAINFUNC,"Arduino::OpenDevice - creating file handle for com port");
	hCommPort = CreateFile(
	COMx,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_WRITE, // 0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL
    );

	if (hCommPort == INVALID_HANDLE_VALUE) 
	{
		err=GetLastError();
		if (err==ERROR_ALREADY_EXISTS)
			{
			LOG(ERR,"Arduino::OpenDevice - Already opened by other process!");
			init_lock.Unlock();
			return ARDUINO_IN_USE;
			} 
		else
			{
			LOG(ERR,"Arduino::OpenDevice - CreateFileA failed %d!",err);
			init_lock.Unlock();
			return ARDUINO_OPEN_FAILED;
			}
	}

	LOG(MAINFUNC,"Arduino::OpenDevice - getting comm state");
	fSuccess = GetCommState(hCommPort, &dcb);

	if (!fSuccess) 
	{
		LOG(ERR,"Arduino::OpenDevice - GetCommStateFailed %d", err=GetLastError());
		PrintError(err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		init_lock.Unlock();
		return ARDUINO_GET_COMMSTATE_FAILED;
	}

	LOG(MAINFUNC,"Arduino::OpenDevice - setting comm state");
	dcb.BaudRate = baud_rate;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.fDtrControl = (disable_DTR==1 ? DTR_CONTROL_DISABLE : DTR_CONTROL_ENABLE);	// to prevent Arduino from reseting when first sending something
		
	fSuccess = SetCommState(hCommPort, &dcb);
	if (!fSuccess) 
	{
		err=GetLastError();
		LOG(ERR,"Arduino::OpenDevice - SetCommStateFailed %d", err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		PrintError(err);
		init_lock.Unlock();
		return ARDUINO_SET_COMMSTATE_FAILED;
	}


	LOG(MAINFUNC,"Arduino::OpenDevice - enable listening to comm events");
	DWORD      dwStoredFlags;
	// listen only for events regarding errors and receive buffer
	dwStoredFlags = /*EV_BREAK | EV_CTS |*/ EV_DSR | /* EV_ERR | EV_RING | EV_RLSD | */ EV_RXCHAR /* | EV_RXFLAG | EV_TXEMPTY*/ ;
	if (!SetCommMask(hCommPort, dwStoredFlags))
	{
		err=GetLastError();
		LOG(ERR,"Arduino::OpenDevice - Error setting communications mask (err %d); abort!", err);
		CloseHandle(hCommPort);
		hCommPort=INVALID_HANDLE_VALUE;
		PrintError(err);
		init_lock.Unlock();
		return ARDUINO_SET_COMMMASK_FAILED;
	}

	// create event for write completed
	if ((ghWriteCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
	{
		LOG(ERR,"Arduino::OpenDevice - Create 'Write Complete Event' failed (err %d); abort!", GetLastError());
		return ARDUINO_CREATE_EVENT_FAILED;
	}


	blockingWrite("\r\r\r",3);

	isConnected=true;

#ifdef USBCAN_PROTOCOL
	Send("Z0");	// we are not interested in time stamps, we generate our own
#else
	Send(":ping");
#endif

	init_lock.Unlock();
	LOG(MAINFUNC,"Arduino::OpenDevice - port configured");
	return ARDUINO_INIT_OK;
}
Beispiel #15
0
void uninit_driver()
{
	TRACE("uninit_driver\n");
	gLock.Delete();
	put_module(VBOXGUEST_MODULE_NAME);
}