/*************************************************************** * Name: BarCode.cpp * Purpose: Code for Application Frame * Author: Igor I (info@tiptopcity.com) * Created: 2010-12-01 * Copyright: Igor I (www.tiptopcity.com) * License: Commercial **************************************************************/ //#include "stdafx.h" #include "BarCode.h" //#include /* #include extern "C" { #include } /**/ //#include "hidsdi.h" //Это если считыватель штрих кодов как HID устройство windows в папке C:\WinDDK\7600.16385.1\inc\ //------------------------------------------------------------------------------ //TSimpleList* g_BarCode=NULL; BarCode* g_BarCode=NULL; //------------------------------------------------------------------------------ BarCode::BarCode() { m_id=0; bString = true; m_crit = new wxCriticalSection(); //Для синхронизации m_ListD = new TSimpleList(5,false); m_critW = new wxCriticalSection(); //Для синхронизации записи в поток m_ListW = new TSimpleList(5,false); //Список пакетов которых надо записать в поток m_ListL = new TSimpleList(5,false); cPort=new ComPort(); if(g_BarCode!=NULL) g_BarCode->Disconnect(); g_BarCode=this; } //------------------------------------------------------------------------------ BarCode::~BarCode() { //Следим за глобальным объектом. if(g_BarCode==this) g_BarCode=NULL; /*if(g_BarCode!=NULL && g_BarCode->count()==0) { delete g_BarCode; g_BarCode=NULL; }*/ //Чистим и удаляем список для записи с поток for(unsigned int i=0;icount();i++) { delete m_ListW->get(i)->data; delete m_ListW->get(i); } delete m_ListW; for(unsigned int i=0;icount();i++) delete m_ListD->get(i); //Не востребованные удаляем если есть delete m_ListD; m_ListD=NULL; delete m_ListL; m_ListL=NULL; delete cPort; cPort=NULL; delete m_crit; m_crit=NULL; delete m_ListW; m_ListW=NULL; } //------------------------------------------------------------------------------ //Добавить слушателя выбора void BarCode::AddListener(CharStringListener* listener) { //m_crit->Enter(); if(m_ListL!=NULL && listener!=NULL) m_ListL->add(listener); //m_crit->Leave(); }; //------------------------------------------------------------------------------ //Удалить слкшателя выбора void BarCode::RemListener(CharStringListener* listener) { //m_crit->Enter(); if(m_ListL!=NULL && listener!=NULL) m_ListL->del(listener); //m_crit->Leave(); }; //------------------------------------------------------------------------------ bool BarCode::Connect(int port,int speed) { cPort->BaudRate=speed; if (cPort->Open(port)) { if(cPort->Setup(0)) { if(Create()==wxTHREAD_NO_ERROR) { Run(); return true; } } } return false; } //------------------------------------------------------------------------------ ///<Отсоедениться от порта и удалить поток bool BarCode::Disconnect() { return cPort->Close(); } //------------------------------------------------------------------------------ //Функция - поток служит для приёма и отправкм данных void* BarCode::Entry() { unsigned char* ch=new unsigned char[255]; //Буфер unsigned int pos=0; //Позиция в буфере while(cPort->bOpen) { if(bString) { //Читаем побайтно до заданного признака if(cPort->Read(&ch[pos],1)>0) { if(ch[pos]==13 || ch[pos]==10 || pos==254) { if(pos>0) { ch[pos]=0; //Ставим признак конца строки m_ListD->add(ch); ch=new unsigned char[255]; pos=0; } }else pos++; } }else { //Как прочитали 1 байт так с разу и добавляем в список событий if(cPort->Read(ch,1)>0) { ch[1]=0; //Ставим признак конца строки m_ListD->add(ch); ch=new unsigned char[255]; pos=0; } } //Если есть данные для отправки отправляем их в поток m_critW->Enter(); for(unsigned int i=0;icount();i++) { if(m_ListW->get(i)->state==0) //Те которые ждут отправки { m_ListW->get(i)->sizeW = cPort->Write(m_ListW->get(i)->data,m_ListW->get(i)->size); m_ListW->get(i)->state = m_ListW->get(i)->sizeW == m_ListW->get(i)->size ? 2 : 3; // 2 - ok, 3 - error (Нет состоояния 1 так как отправляем блоком) } } m_critW->Leave(); //wxThread::Sleep(100); //Расскоментировать если полностью в асинхронном режиме ком порт } delete ch; return NULL; } //------------------------------------------------------------------------------ //Работает в основном потоке для проверки прихода данных (сам не вызвается надо из внешней проги проверять) bool BarCode::OnTimer() { if(m_ListD==NULL || m_ListL==NULL) return false; unsigned char *ch; unsigned char **p; //Указатель на указатель чтоб слушатели могли забрать себе. p=&ch; do { ch=NULL; m_crit->Enter(); if(m_ListD->count()>0) { ch=m_ListD->get(0); m_ListD->del((unsigned int)0); //Удаляем из списка } m_crit->Leave(); //Информируем слушателей о новой таблице if(ch!=NULL) { m_crit->Enter(); for(unsigned int i=0;icount();i++) { m_ListL->get(i)->OnDataIncoming(p); if(ch!=NULL) break; //Кто-то воспользовался... } m_crit->Leave(); //Если никому не понадобилась удаляем таблицу if(ch!=NULL) {delete ch; ch=NULL;} } } while(ch!=NULL); return true; } //------------------------------------------------------------------------------ //Синхронно записать данные в поток unsigned long BarCode::WriteS(const void* lpBuffer,unsigned long nNumberOfBytesToWrite) { int id=GetNextId(); SData* d=new SData; d->id=id; d->sizeW=0; d->state=0; d->data=new char[nNumberOfBytesToWrite]; memcpy(d->data,lpBuffer,nNumberOfBytesToWrite); //Копируем данные (TODO можно и не копировать так как здесь эмуляция синхронности) d->size=nNumberOfBytesToWrite; m_critW->Enter(); m_ListW->add(d); m_critW->Leave(); //Ждём ответ то что все данные записанны в порт тоесть в пакете поменялся статус unsigned long size=0; for(int i=0;i<600;i++) //Макс минуту ждём статус... { SData* rez=NULL; m_critW->Enter(); for(unsigned int j=0;jcount();j++) { if(m_ListW->get(j)->id==id && (m_ListW->get(j)->state==2 || m_ListW->get(j)->state==3)) { rez=m_ListW->get(j); m_ListW->del(j); break; } } m_critW->Leave(); if(rez!=NULL) { size=rez->sizeW; delete rez->data; delete rez; break; } wxThread::Sleep(100); } return size; } //------------------------------------------------------------------------------