LINUX.ORG.RU

Сообщения Vitaliy69

 

Ручная сборка драйвера WiFi под чипсет Ке5370

Попытался собрать свежий драйвер для чипсета RT5370 версии 2.5.0.3 из файла 2011_0719_RT3070_RT3370_RT5370_RT5372_Linux_STA_V2.5.0.3_DPO.bz2 под платформу SH4.

На Ubuntu 10.04.4 x32 поставил STLinux 2.4, собирал под ядро linux-sh4-2.5.32.59_stm24_0211. В путях к ядру указывал /opt/STM/STLinux-2.2/devkit/sources/kernel/linux-sh4-2.5.32.59_stm24_0211 вместо STLinux-2.4, так как Makefile написан «в лоб», что вызывает ошибку компиляции уже на начальном этапе из-за:

install:
ifeq ($(TARGET), LINUX)
ifneq (,$(findstring 2.4,$(LINUX_SRC)))
	$(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.4 install
else
	$(MAKE) -C $(RT28xx_DIR)/os/linux -f Makefile.6 install
endif
endif

То есть любые упоминания в пути цифр 2.4 заставляет собираться как под Kernel 2.4, что в данном случае не так.

Проставил в Makefile:

PLATFORM = ST
...
LINUX_SRC = /opt/STM/STLinux-2.2/devkit/sources/kernel/linux-sh4-2.5.32.59_stm24_0211
CROSS_COMPILE = /opt/STM/STLinux-2.2/devkit/sh4/bin/sh4-linux-

В ./os/linux/config.mk прописал:

HAS_WPA_SUPPLICANT=y
HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y
CC := sh4-linux-gcc
LD := sh4-linux-ld

Собираю по make. Получаю ошибку:

script/Makefile.build:49: *** CFLAGS was changed in «/home/vitaliy/drv_src/os/linux/Makefile». Fix it to use EXTRA_CFLAGS.

Нахожу строки в ./os/linux/config.mk:

ifeq ($(PLATFORM),ST)
CFLAGS := -D__KERNEL__ -I$(LINUX_SRC)/include -I$(RT28xx_DIR)/include -Wall -O2 -Wundef -Wstrict-prototypes -Wno-trigraphs -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-aliasing -fno-common -fomit-frame-pointer -ffreestanding -m4-nofpu -o $(WFLAGS) 
export CFLAGS
endif

Меняю в них CFLAGS на EXTRA_CFLAGS.

Получаю ошибку:

sh4-linux-gcc: error: -pg and -fomit-frame-pointer are incompatible.

Хорошо, убираю флаг -fomit-frame-pointer.

Получаю ошибку:

error: cpu/cache.h: No such file or directory.

Хорошо, в строке:

WFLAGS := -DAGGREGATION_SUPPORT -DPIGGYBACK_SUPPORT -DWMM_SUPPORT  -DLINUX -Wall -Wstrict-prototypes -Wno-trigraphs

Убираю флаг -DLINUX.

Теперь ругается на незнакомые типы (вроде ./os/linux/../../common/crypt_md5.c:638:1: error: unknown type name 'VOID' и много пододобных ошибок по типам 'UCHAR', 'ULONG' и так далее).

Если не делать изменений в файлах исходников, а попытаться собрать

KBUILD_NOPEDANTIC=1 make

то получаю ошибку:

./os/linux/../../common/crypt_md5.c:28:23: fatal error: rt_config.h: No such file or directory.

make ARCH=sh CROSS_COMPILE=sh4-linux- тоже набирал, но дело не в этом - конечная платформа и кросс-компилятор прописаны в Makefile, кроме того в .bashrc прописал export PATH=$PATH:/opt/STM/STLinux-2.2/devkit/sh4/bin.

Вопрос. Что делаю не так и как всё же стоит попытаться собрать драйвер RT5370 под SH4-платформу? Может, кто собирал сам и сталкивался с таким.

Vitaliy69
()

Проблема с сокетами

Друзья, имеется проблема при работе с сокетами под Linux'ами.

Создаю сокет:

bool CTcpClient::createSocket()
{
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);

if(sock == INVALID_SOCKET)
{
LOG_SOCKET_ERROR("create socket failed");
return false;
}

int opt;
int optlen = sizeof(opt);
int iRet;

opt = 64*1024;
iRet = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&opt, optlen);
if (iRet != 0)
{
LOG_SOCKET_ERROR("setsockopt SO_SNDBUF failed");
return false;
}

iRet = setsockopt( sock, SOL_SOCKET, SO_RCVBUF, (char*)&opt, optlen );
if (iRet != 0)
{
LOG_SOCKET_ERROR("setsockopt SO_RCVBUF failed");
return false;
}

setSock(sock); /// возвращаю созданный сокет в класс CTcpClient

return true;
}

Задаём опции и подключаемся к удалённой машине по локальной сети:

void CConnection::connect_to_service()
{
COptionsSP options_w; /// класс для чтения конфигурационного файла, в котором задаются номера портов и т. д.
TMultiConfigWraper multi_options;
if (INodeSP parent = m_wpParent.lock())
options_w = multi_options->getOptions(parent->GetCfgFile());
else
options_w = multi_options->getOptions("");

m_conn_state = connecting;
/*
enum EConnState { connecting, worked, aborted };
EConnState m_conn_state;
*/
fd_set set;
struct timeval timeout;
int numsocks = 0;

timeout.tv_sec = 0;
timeout.tv_usec = 100000;

// к кому подключаемся
unsigned short usPort = options_w->getListenPort();

SOCKADDR_IN ServAddr;
ServAddr.sin_family = AF_INET;
ServAddr.sin_port = htons(usPort);
ServAddr.sin_addr.s_addr = GetAddress();

for (unsigned long i = 0; i < m_conn_try; ++i)
{
if (connect(m_apClient->getSock(), (SOCKADDR *)&ServAddr, sizeof(SOCKADDR_IN)) != SOCKET_ERROR) /// boost::shared_ptr<CTcpClient> m_apClient;
{
FD_ZERO(&set);
FD_SET(m_apClient->getSock(), &set);

numsocks = select(m_apClient->getSock(), 0, &set, 0, &timeout );

if (numsocks == SOCKET_ERROR)
{
LOG_SOCKET_ERROR("select failed");
work_tools::sleep(100);
/*
inline void sleep(int ms)
{
boost::xtime delay;
to_time(ms, delay);
boost::thread().sleep(delay);
}
*/
continue;
}

SOCKADDR_IN local_addr;
int len = sizeof(SOCKADDR_IN);

if (getsockname( m_apClient->getSock(), (SOCKADDR *)&local_addr, (socklen_t*)&len) == SOCKET_ERROR)
{
LOG_SOCKET_ERROR("getsockname failed");
}

///делаем неблокирующим
unsigned long ulNonBlockingMode = 1;
if (ioctlsocket(m_apClient->getSock(), FIONBIO, &ulNonBlockingMode) < 0)
{
LOG_SOCKET_ERROR("ioctlsocket failed");
}

m_apClient->setPort(ntohs(local_addr.sin_port)); // можно отправлять
m_connect_event.set(connected);
m_conn_state = worked;

return;
}
else
{
LOG_SOCKET_ERROR("connect failed");
}

work_tools::sleep(100);
}
m_conn_state = aborted;
}

Ну, и, собственно, функции отсылки:

bool CConnection::send_packet_impl(const char *pHead, unsigned long ulHeadLen, const char *pData, unsigned long ulLen)
{
if( !m_apClient )
return false;

#ifdef WIN32
DWORD sended = 0;
WSABUF wbuf[2];

wbuf[0].buf = const_cast<char*>(pHead);
wbuf[0].len = ulHeadLen;

wbuf[1].buf = const_cast<char*>(pData);
wbuf[1].len = ulLen;

while (true)
{
if(WSASend(m_apClient->getSock(), wbuf, 2, &sended, 0, NULL, NULL  ) < 0)
{
LOG_SOCKET_ERROR("send failed");
if(WSAGetLastError() == WSAECONNRESET)
{
m_conn_state = connecting;
return false;
}

work_tools::sleep(5);
continue;
}
if(sended < ulHeadLen + ulLen)
LOG( "data loss");

return true;
}

#else
send_to_service( pHead, ulHeadLen );
send_to_service( pData, ulLen );
#endif
}

#ifndef WIN32
bool CConnection::send_to_service(const char *pData, unsigned long ulLen)
{
if( !m_apClient )
return false;

unsigned long total = 0;
int n;

while(total < ulLen)
{
struct timeval tv;
int retval;
tv.tv_sec = 1;
tv.tv_usec = 0;
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(m_apClient->getSock(), &rfds);

retval = select(m_apClient->getSock() + 1, NULL, &rfds, NULL, &tv);

if (retval > 0) /// есть дескрипторы, готовые принять данные
{
if (FD_ISSET(m_apClient->getSock(), &rfds)
{
n = send(m_apClient->getSock(), pData + total, ulLen - total, MSG_CONFIRM);
}
if (n == SOCKET_ERROR)
{
if (total > 0)
LOG_ERROR("send failed on pos" << total);

LOG_SOCKET_ERROR("send failed");

if (errno == EWOULDBLOCK)
{
work_tools::sleep(100); /// почему-то всё время заходит сюда
}
if(errno == ECONNRESET)
{
m_conn_state = connecting;
return false;
}
}
else
{
total += n;
}
}
if (retval == 0) /// вернули управление по таймауту, дескрипторов нет
{
work_tools::sleep(100);
}
if (retval < 0)
{
if ( errno == EWOULDBLOCK )
{
work_tools::sleep(100);
}
if(errno == ECONNRESET)
{
m_conn_state = connecting;
return false;
}
}
}
}

А теперь суть проблемы. Если код под Windows работает без проблем, то реализация для Linux страдает. Хотя функция select в send_to_service возвращает управление со значением больше 0, при попытке сразу же вызвать send валится исключение EAGAIN. Если данных послать очень много (например, 500 Мбайт для локального хоста и всего 100 Кбайт для локальной сети), то в течение минуты сокет дохнет, а ядро шлёт connection timed out, от чего клиент напрочь отваливается. Что делаю не так?

Vitaliy69
()

RSS подписка на новые темы