Issue description
I used ZMQ_SNDBUF && ZMQ_RCVBUF on ZMQ_PUB&&ZMQ_SUB no effect.
But I executed the following command and it worked.
sudo sysctl -w net.core.wmem_default=5000
Before modifying net.core.wmem_default
The receiving end continues to receive 3757 frames and then refresh.
After modifying net.core.wmem_default
The receiving end continues to receive 22 frames and then refreshes.
Environment
libzmq version (commit hash if unreleased):
4.3.3
OS:
ubuntu18.04
Is that why?
Code
sender
//
// Created by kongshui on 22-8-23.
//
#include <unistd.h>
#include <iostream>
#include <zmq.hpp>
void main()
{
const int first_count = 10000000;
int hwm = 5;
int time = 10;
auto con = zmq_ctx_new();
// Set up bind socket
void *pub_socket = zmq_socket(con, ZMQ_PUB);
zmq_setsockopt(pub_socket, ZMQ_SNDTIMEO, &time, sizeof(time));
zmq_setsockopt(pub_socket, ZMQ_RCVTIMEO, &time, sizeof(time));
zmq_setsockopt(pub_socket, ZMQ_SNDHWM, &hwm, sizeof(hwm));
zmq_setsockopt(pub_socket, ZMQ_RCVHWM, &hwm, sizeof(hwm));
zmq_bind(pub_socket, "ipc:///tmp/qos_out");
int buf_size = 5000;
auto rrr = zmq_setsockopt(pub_socket, ZMQ_SNDBUF, &buf_size, sizeof(buf_size));
printf("rrr: %d", rrr);
hwm = 10;
size_t hwm_size = sizeof(hwm);
rrr = zmq_getsockopt(pub_socket, ZMQ_SNDBUF, &hwm, &hwm_size);
printf("rrr: %d, size: %d\n", rrr, hwm);
sleep(3);
// Send messages
int send_count = 0;
int recv_count = 0;
std::string msg;
while (send_count < first_count)
{
msg = std::to_string(send_count);
int res = zmq_send(pub_socket, msg.c_str(), msg.length(), ZMQ_DONTWAIT);
printf("res:%d, msg:%s", res, msg.c_str());
if (msg.length() == res)
++send_count;
else
break;
usleep(1000);
}
// Clean up
zmq_close(pub_socket);
}
receiver
//
// Created by kongshui on 22-8-23.
//
#include <unistd.h>
#include <iostream>
#include <zmq.hpp>
void main()
{
const int first_count = 15;
int hwm = 5;
int time = 10;
auto con = zmq_ctx_new();
hwm = 10;
// Set up connect socket
void *sub_socket = zmq_socket(con, ZMQ_SUB);
zmq_setsockopt(sub_socket, ZMQ_SNDTIMEO, &time, sizeof(time));
zmq_setsockopt(sub_socket, ZMQ_RCVTIMEO, &time, sizeof(time));
zmq_setsockopt(sub_socket, ZMQ_SNDHWM, &hwm, sizeof(hwm));
zmq_setsockopt(sub_socket, ZMQ_RCVHWM, &hwm, sizeof(hwm));
int buf_size = 5000;
std::string topic = "www";
auto rrr = zmq_setsockopt(sub_socket, ZMQ_RCVBUF, &buf_size, sizeof(buf_size));
printf("rrr: %d", rrr);
hwm = 10;
size_t hwm_size = sizeof(hwm);
rrr = zmq_getsockopt(sub_socket, ZMQ_RCVBUF, &hwm, &hwm_size);
printf("rrr: %d, size: %d\n", rrr, hwm);
zmq_connect(sub_socket, "ipc:///tmp/qos_out");
// zmq_setsockopt(sub_socket, ZMQ_SUBSCRIBE, topic.c_str(), topic.size());
zmq_setsockopt(sub_socket, ZMQ_SUBSCRIBE, nullptr, 0);
sleep(3);
// Send messages
int send_count = 0;
int recv_count = 0;
std::string msg;
char res[1024] = {0};
while (zmq_recv(sub_socket, res, 1021, ZMQ_DONTWAIT) > 0)
{
++recv_count;
printf("res:%s", res);
printf("first_count: %d, recv_count: %d\n", first_count, recv_count);
memset(res, 0, sizeof(res));
}
while (1)
{
if (zmq_recv(sub_socket, res, 1021, ZMQ_DONTWAIT) > 0)
{
++recv_count;
printf("res:%s", res);
memset(res, 0, sizeof(res));
printf("first_count: %d, recv_count: %d\n", first_count, recv_count);
sleep(1);
}
}
// Clean up
zmq_close(sub_socket);
}
Related
I am interfacing A7672S 4G module with ESP32-C3-DevKitC-02 over Uart0
The problem i am facing is for any AT command published,i am getting lot of junk data
I have tried publising AT to the same 4G module using arduino ,i am able to get the correct response only with this ESP module i am seeing such issues
void uart_init(void)
{
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
// We won't use a buffer for sending data.
uart_driver_install(UART_NUM_0, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
uart_param_config(UART_NUM_0, &uart_config);
uart_set_pin(UART_NUM_0, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
#define RX_BUF_SIZE 1024
int sendData( const char *data)
{
static const char *TX_TASK_TAG = "TX_TASK";
esp_log_level_set(TX_TASK_TAG, ESP_LOG_VERBOSE);
const int len = strlen(data);
const int txBytes = uart_write_bytes(UART_NUM_0, data, len);
ESP_LOGI(TX_TASK_TAG, "Wrote %d bytes", txBytes);
return txBytes;
}
static uint8_t receiveData(uint8_t *data,unsigned int delay_ms)
{
uint8_t rxBytes = 0;
static const char *RX_TASK_TAG = "RX_TASK";
esp_log_level_set(RX_TASK_TAG, ESP_LOG_VERBOSE);
rxBytes = uart_read_bytes(UART_NUM_0, data,RX_BUF_SIZE, delay_ms / portTICK_PERIOD_MS);
data[rxBytes]='\0';
ESP_LOGI(RX_TASK_TAG, "Received %d bytes:\nRxData:%s\n", rxBytes,data);
return rxBytes;
}
uint8_t *data = (uint8_t *)malloc(RX_BUF_SIZE + 1);
uint8_t len=0;
static const char *MAIN_TAG = "MAIN_FUNCTION";
esp_log_level_set(MAIN_TAG, ESP_LOG_VERBOSE);
memset(data, 0, RX_BUF_SIZE + 1);
uart_init();
vTaskDelay(20);
uart_flush(UART_NUM_0);
sendData("AT+CGMI\r\n");
len = receiveData(data,2000);
if(OK == check_response(data,(unsigned char*)"OK"))
{
ESP_LOGI(MAIN_TAG,"Incorporated AT Response Received");
}
else
{
ESP_LOGI(MAIN_TAG,"AT Response Not Received");
}
I've been using the following code for quite a while:
#include <fstream>
#include <gdiplus.h>
#include <windows.h>
#include <iostream>
using namespace std;
void CaptureScreen(const char* filename)
{
HDC hScreenDC = GetDC(0);
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int upper_left_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
int upper_left_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
int bitmap_dx = GetSystemMetrics(SM_CXVIRTUALSCREEN ) * 1.25f;
int bitmap_dy = GetSystemMetrics(SM_CYVIRTUALSCREEN ) * 1.25f;
// create file
ofstream file(filename, ios::binary);
if(!file) return;
// save bitmap file headers
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
fileHeader.bfType = 0x4d42;
fileHeader.bfSize = 0;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
infoHeader.biSize = sizeof(infoHeader);
infoHeader.biWidth = bitmap_dx;
infoHeader.biHeight = -bitmap_dy;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 16;
infoHeader.biCompression = BI_RGB;
infoHeader.biSizeImage = 0;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
file.write((char*)&fileHeader, sizeof(fileHeader));
file.write((char*)&infoHeader, sizeof(infoHeader));
// dibsection information
BITMAPINFO info;
info.bmiHeader = infoHeader;
// ------------------
// THE IMPORTANT CODE
// ------------------
// create a dibsection and blit the window contents to the bitmap
BYTE* memory = 0;
HBITMAP bitmap = CreateDIBSection(hScreenDC, &info, DIB_RGB_COLORS, (void**)&memory, 0, 0);
SelectObject(hMemoryDC, bitmap);
BitBlt(hMemoryDC, 0, 0, bitmap_dx, bitmap_dy, hScreenDC, upper_left_x, upper_left_y, SRCCOPY);
DeleteDC(hMemoryDC);
ReleaseDC(NULL, hScreenDC);
// save dibsection data
int bytes = (((16*bitmap_dx + 31) & (~31))/8)*bitmap_dy;
file.write((const char *)memory, bytes);
DeleteObject(bitmap);
}
int main()
{
CaptureScreen("ok.jpg");
return 0;
}
But it seems to generate a too large BMP file because the bitmaps are saved uncompressed.
I'm looking for a way to capture a screen shot and save it to a buffer in PNG format, send it over a TCP connection and save it as a PNG file there.
I believe it has something to do with assigning BI_PNG to infoHeader.biCompression and a different calculation of bytes but I can't figure exactly what.
http://lodev.org/lodepng/
#include <fstream>
#include <gdiplus.h>
#include <windows.h>
#include <iostream>
#include "lodepng.h"
const int bits_per_pixel = 24;
using namespace std;
void CaptureScreen(const char* filename)
{
HDC hScreenDC = GetDC(0);
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int upper_left_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
int upper_left_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
int bitmap_dx = GetSystemMetrics(SM_CXVIRTUALSCREEN ) * 1.25f;
int bitmap_dy = GetSystemMetrics(SM_CYVIRTUALSCREEN ) * 1.25f;
// create file
ofstream file(filename, ios::binary);
if(!file) return;
// save bitmap file headers
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
fileHeader.bfType = 0x4d42;
fileHeader.bfSize = 0;
fileHeader.bfReserved1 = 0;
fileHeader.bfReserved2 = 0;
fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
infoHeader.biSize = sizeof(infoHeader);
infoHeader.biWidth = bitmap_dx;
infoHeader.biHeight = -bitmap_dy;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = bits_per_pixel;
infoHeader.biCompression = BI_RGB;
infoHeader.biSizeImage = 0;
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 0;
infoHeader.biClrImportant = 0;
file.write((char*)&fileHeader, sizeof(fileHeader));
file.write((char*)&infoHeader, sizeof(infoHeader));
// dibsection information
BITMAPINFO info;
info.bmiHeader = infoHeader;
// ------------------
// THE IMPORTANT CODE
// ------------------
// create a dibsection and blit the window contents to the bitmap
BYTE* memory = 0;
HBITMAP bitmap = CreateDIBSection(hScreenDC, &info, DIB_RGB_COLORS, (void**)&memory, 0, 0);
SelectObject(hMemoryDC, bitmap);
BitBlt(hMemoryDC, 0, 0, bitmap_dx, bitmap_dy, hScreenDC, upper_left_x, upper_left_y, SRCCOPY);
DeleteDC(hMemoryDC);
ReleaseDC(NULL, hScreenDC);
// save dibsection data
int bytes = (((bits_per_pixel*bitmap_dx + 31) & (~31))/8)*bitmap_dy;
file.write((const char *)memory, bytes);
unsigned char *out_buffer;
size_t out_buffer_len;
unsigned error;
if ( bits_per_pixel == 24 )
{
// convert memory from bgr format to rgb
for ( unsigned i = 0; i< bytes-2; i+=3)
{
int tmp = memory[i+2];
memory[i+2] = memory[i];
memory[i] = tmp;
}
error = lodepng_encode24(&out_buffer,
&out_buffer_len,
memory,
bitmap_dx,
bitmap_dy);
}
if ( bits_per_pixel == 32 )
{
// convert memory from bgr format to rgb
for ( unsigned i = 0; i< bytes-3; i+=4)
{
int tmp = memory[i+2];
memory[i+2] = memory[i];
memory[i] = tmp;
}
error = lodepng_encode32(&out_buffer,
&out_buffer_len,
memory,
bitmap_dx,
bitmap_dy);
}
if ( error )
{
std::cout << "error: " << error << '\n';
return;
}
lodepng_save_file(out_buffer, out_buffer_len, "stam.png");
// free(out);
DeleteObject(bitmap);
}
int main()
{
CaptureScreen("ok.jpg");
return 0;
}
This is client code by using libwebsocket version 1.5
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <syslog.h>
#include <sys/time.h>
#include <unistd.h>
#include <libwebsockets.h>
static volatile int force_exit = 0;
static int state, command_received = 0, forked = 0;
#define MAX_ECHO_PAYLOAD 1400
#define LOCAL_RESOURCE_PATH "./"
struct per_session_data {
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + MAX_ECHO_PAYLOAD + LWS_SEND_BUFFER_POST_PADDING];
unsigned int len;
};
//for temporary storing data from tcpdump
struct per_session_data data1;
static int callback_echo(struct libwebsocket_context *context, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len)
{
struct per_session_data *pss = (struct per_session_data *)user;
int n;
switch (reason) {
/* when the callback is used for client operations --> */
case LWS_CALLBACK_CLOSED:
case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
printf("Closed\n");
state = 0;
break;
case LWS_CALLBACK_ESTABLISHED:
case LWS_CALLBACK_CLIENT_ESTABLISHED:
printf("Client connected\n");
state = 2;
break;
/* we will receive our packet here*/
case LWS_CALLBACK_RECEIVE:
case LWS_CALLBACK_CLIENT_RECEIVE:
printf("Rx from server: %s\n", (char *)in);
if (!strcmp((char *)in, "tcpdump"))
{
command_received = 1;
}
break;
/* we will send our packet here */
case LWS_CALLBACK_CLIENT_WRITEABLE:
printf("client writing to server\n");
pss->len = sprintf((char *)&pss->buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
n = libwebsocket_write(wsi, &pss->buf[LWS_SEND_BUFFER_PRE_PADDING], pss->len, LWS_WRITE_TEXT);
printf("Data: %s\n\n\n\n\n\n\n", &pss->buf[LWS_SEND_BUFFER_PRE_PADDING]);
//error handling for write fail and partial writes
if (n < 0) {
printf("ERROR %d writing to socket, hanging up\n", n);
return -1;
}
if (n < (int)pss->len) {
printf("Partial write\n");
return -1;
}
break;
default:
printf("default...\n");
break;
}
return 0;
}
/* List of available protocols */
static struct libwebsocket_protocols protocols[] = {
{
"default", /* name */
callback_echo, /* callback */
sizeof(struct per_session_data) /* per_session_data_size */
},
{
NULL, NULL, 0 /* End of list */
}
};
void sighandler(int sig)
{
force_exit = 1;
}
int main(int argc, char **argv)
{
//pipe stuff
int pipe_fd[2];
if (pipe(pipe_fd) < 0)
{
perror("PIPE:");
exit(-1);
}
//for libwebsocket_service
int n = 0;
//test port can be overidden
int port = 9000;
struct libwebsocket_context *context;
int opts = 0;
char interface_name[128] = "";
const char *interface = NULL;
int use_ssl = 0;
char ssl_cert[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem";
char ssl_key[256] = LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem";
int listen_port = 80;
struct lws_context_creation_info info;
char passphrase[256];
char uri[256] = "/";
char address[256], ads_port[256 + 30];
//lws servicing time intervals
int rate_us = 250000;
unsigned int oldus = 0;
struct libwebsocket *wsi;
//should check this
int debug_level = 2;
memset(&info, 0, sizeof info);
lwsl_notice("Built to support client operations\n");
//re-configuring server ip and port here
if (argc == 3)
{
strncpy(address, argv[1], sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = atoi(argv[2]);
}
else if (argc == 1)
{
strncpy(address, "localhost", sizeof(address) - 1);
address[sizeof(address) - 1] = '\0';
port = 9000;
}
else
{
printf("Try: ./client.exec <ip> <port>\n");
exit(-1);
}
/* we will only try to log things according to our debug_level */
setlogmask(LOG_UPTO (LOG_DEBUG));
openlog("lwsts", 0, LOG_DAEMON);
/* tell the library what debug level to emit and to send it to syslog */
lws_set_log_level(debug_level, lwsl_emit_syslog);
lwsl_notice("libwebsockets echo test - "
"(C) Copyright 2010-2015 Andy Green <andy#warmcat.com> - "
"licensed under LGPL2.1\n");
lwsl_notice("Running in client mode\n");
listen_port = CONTEXT_PORT_NO_LISTEN;
lwsl_info("requiring server cert validation againts %s\n", ssl_cert);
info.ssl_ca_filepath = ssl_cert;
info.port = listen_port;
info.iface = interface;
info.protocols = protocols;
#ifndef LWS_NO_EXTENSIONS
info.extensions = libwebsocket_get_internal_extensions();
#endif
info.gid = -1;
info.uid = -1;
info.options = opts;
context = libwebsocket_create_context(&info);
if (context == NULL) {
lwsl_err("libwebsocket init failed\n");
return -1;
}
signal(SIGINT, sighandler);
n = 0;
while (n >= 0 && !force_exit)
{
//do connect only once
if (!state) {
state = 1;
printf("Client connecting to %s:%u....\n", address, port);
address[sizeof(address) - 1] = '\0';
sprintf(ads_port, "%s:%u", address, port & 65535);
wsi = libwebsocket_client_connect(context, address, port, use_ssl, uri, ads_port, ads_port, NULL, -1);
if (!wsi) {
printf("Client failed to connect to %s:%u\n", address, port);
goto bail;
}
}
if (command_received == 1 && !forked)
{
printf("Going to fork\n");
forked = 1;
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("FORK:");
exit(-1);
}
else if (child_pid == 0)
{
close(pipe_fd[0]);
printf("Starting tcpdump\n");
if (dup2(pipe_fd[1], 1) < 0)
{
perror("DUP2:");
exit(-1);
}
//closing the connection to server for child
libwebsocket_context_destroy(context);
closelog();
char *cmd[] = {"tcpdump", "-i", "any", NULL};
if (execv("/usr/sbin/tcpdump", cmd) < 0)
{
perror("EXECV:");
exit(-1);
}
}
}
/* if (forked == 1)
{
close(pipe_fd[1]);
}
*/
if (command_received == 1)
{
//stay here if the pipe is empty else try to read max 1400 bytes of data
while ((data1.len = read(pipe_fd[0], data1.buf + LWS_SEND_BUFFER_PRE_PADDING, 1400)) <= 0);
//check if server wants any service
//printf("%s\n\n\n\n\n\n\n", data1.buf + LWS_SEND_BUFFER_PRE_PADDING);
libwebsocket_callback_on_writable(context, wsi);
}
//This fn times out every 10usec
n = libwebsocket_service(context, 10);
}
//bail: jump from while loop also if connect fails
bail:
libwebsocket_context_destroy(context);
printf("libwebsockets-test-echo exited cleanly\n");
closelog();
return 0;
}
This is my server code by using socket.io
var io = require('socket.io')();
var middleware = require('socketio-wildcard')();
io.use(middleware);
io.on('connection', function(socket) {
console.log('On socket connection')
socket.on('*', function(event, data){
console.log("---- Event ----- : " + JSON.stringify(event));
console.log("---- Data ----- : " + JSON.stringify(data))
});
});
io.listen(9000, 'localhost');
The client is unable to connect with server. when i tested client with strace it infinitely does receive as below
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
recv(8, "", 1, 0) = 0
.
.
.
.
Please point out my mistake. Any help is appreciated.
Thanks
I am writing a driver module for my 128x64 OLED(ssd1306), which will be used on my raspberry pi. And it works in 4-wire SPI mode. Firstly, I read the datasheet of the ssd1306 and wrote some basic functions. Then I connected this OLED with an Arduino board, ran the codes to test its correctness and I found it worked quite well.
Here are my arduino code:
//oled.ino
#define clearPin(a) digitalWrite(a, LOW)
#define setPin(a) digitalWrite(a, HIGH)
char* hello = "Hello World!";
// visible ascii chars
const unsigned char F6x8[][6] =
{
//...
};
const unsigned char F8X16[]=
{
//...
};
// pin assignments
int CS = 53;
int DIN = 51;
int CLK = 52;
int DC = 3;
int RES = 2;
//***********************************
int writeCommand(byte command)
{
int i;
clearPin(CS);
clearPin(DC);
for(i = 0; i < 8; i++)
{
clearPin(CLK);
delay(1);
if((command >> (7-i)) & 0x1)
setPin(DIN);
else
clearPin(DIN);
delay(1);
setPin(CLK);
delay(1);
}
setPin(CS);
}
int writeData(byte data)
{
int i;
clearPin(CS);
setPin(DC);
for(i = 0; i < 8; i++)
{
clearPin(CLK);
delay(1);
if((data >> (7 - i)) & 0x1)
setPin(DIN);
else
clearPin(DIN);
delay(1);
setPin(CLK);
delay(1);
}
setPin(CS);
}
void setPostion(byte x, byte y)
{
writeCommand(0xB0 | y); // go to page y
writeCommand(0x00 | (x & 0x0f)); // setPin lower column address
writeCommand(0x10 | ((x >> 4) & 0x0f)); // setPin higher column address
}
void write6x8Char(byte x, byte y, char ch)
{
setPostion(x, y);
int i, c = ch - 32;
for(i = 0; i < 6; i++)
writeData(F6x8[c][i]);
}
void write6x8String(byte x, byte y, char* str)
{
//...
}
void write8x16Char(byte x, byte y, char ch)
{
setPostion(x, y);
int i, c = ch - 32;
for(i = 0; i < 8; i++)
writeData(F8X16[c * 16 + i]);
setPostion(x, y+1);
for(i = 8; i < 16; i++)
writeData(F8X16[c * 16 + i]);
}
void write8x16String(byte x, byte y, char* str)
{
//...
}
void clearScreen()
{
fill(0);
}
void fill(unsigned char bmp_data)
{
unsigned char y,x;
for(y = 0; y < 8; y++)
{
writeCommand(0xb0 + y);
writeCommand(0x00);
writeCommand(0x10);
for(x = 0; x < 128; x++)
writeData(bmp_data);
}
}
void setDisplayOn(byte on)
{
writeCommand(0xAE | on);
}
//***********************************************
void initialize()
{
setPin(CLK);
clearPin(RES);
delay(50);
setPin(RES);
setDisplayOn(1);
fill(0x00);
}
void setup()
{
pinMode(CS, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(CLK, OUTPUT);
pinMode(DC, OUTPUT);
pinMode(RES, OUTPUT);
initialize();
}
void loop()
{
write8x16String(0, 0, hello);
}
So I moved them directly into my driver module file with few necessary changes. Here are my oled.c file and Makefile:
//oled.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define DRIVER_NAME "OLED"
#define DEVICE_NAME "OLED"
#define clearGPIO(a) gpio_set_value(a, 0)
#define setGPIO(a) gpio_set_value(a, 1)
const int DIN = 5;
const int CLK = 6;
const int CS = 13;
const int DC = 19;
const int RES = 26;
const unsigned char F6x8[][6] =
{
//...
};
const unsigned char F8X16[]=
{
//...
};
//*****************************************
void delay(int ms)
{
int i, j;
for(i = 0; i < ms; i++)
{
j = 100000;
while(j--);
}
}
//...Same functions with the arduino program...
//*****************************************
static dev_t oled_devno;
static struct class *oled_class;
static struct cdev oled_dev;
static int flag = 0;
//open
static int oled_open(struct inode *inode, struct file *filp)
{
int err;
printk(KERN_INFO"Initializing GPIOs...\n");
err = gpio_request_one(CS, GPIOF_OUT_INIT_LOW, "CS");
if(err){
printk(KERN_ERR"[%s %d]:Request led gpio failed\n", __func__, __LINE__);
gpio_free(CS);
}
err = gpio_request_one(DC, GPIOF_OUT_INIT_LOW, "DC");
if(err){
printk(KERN_ERR"[%s %d]:Request led gpio failed\n", __func__, __LINE__);
gpio_free(DC);
}
err = gpio_request_one(RES, GPIOF_OUT_INIT_LOW, "RES");
if(err){
printk(KERN_ERR"[%s %d]:Request led gpio failed\n", __func__, __LINE__);
gpio_free(RES);
}
err = gpio_request_one(DIN, GPIOF_OUT_INIT_LOW, "DIN");
if(err){
printk(KERN_ERR"[%s %d]:Request led gpio failed\n", __func__, __LINE__);
gpio_free(DIN);
}
err = gpio_request_one(CLK, GPIOF_OUT_INIT_LOW, "CLK");
if(err){
printk(KERN_ERR"[%s %d]:Request led gpio failed\n", __func__, __LINE__);
gpio_free(CLK);
}
flag = 1;
printk(KERN_INFO"Initializing OLED...\n");
oled_initialize();
printk(KERN_INFO"OLED open\n");
return 0;
}
//release
static int oled_release(struct inode *inode, struct file *filp)
{
if(flag)
{
gpio_free(CS);
gpio_free(DC);
gpio_free(RES);
gpio_free(DIN);
gpio_free(CLK);
}
printk(KERN_INFO"OLED release\n");
return 0;
}
//write
ssize_t oled_write(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
char* hello = "Hello driver";
printk(KERN_INFO"I am writing data!\n");
write8x16String(0, 0, hello);
return 0;
}
static struct file_operations oled_fops = {
.owner = THIS_MODULE,
.open = oled_open,
.release = oled_release,
.write = oled_write,
};
static int __init oled_init(void)
{
int err;
printk(KERN_INFO"OLED Init \n");
err = alloc_chrdev_region(&oled_devno,0,1,DRIVER_NAME);
if(err < 0){
goto err;
}
cdev_init(&oled_dev,&oled_fops);
err = cdev_add(&oled_dev,oled_devno,1);
if(err < 0)
{
printk(KERN_ERR"[%s,%d]add cdev failed\n",__func__,__LINE__);
goto FREE_DEVNO;
}
//
oled_class = class_create(THIS_MODULE,DEVICE_NAME);
if(IS_ERR(oled_class))
{
printk(KERN_ERR"[%s,%d]class create failed\n",__func__,__LINE__);
goto DEV_FREE;
}
device_create(oled_class,NULL,oled_devno,NULL,DEVICE_NAME);
return 0;
DEV_FREE:
cdev_del(&oled_dev);
FREE_DEVNO:
unregister_chrdev_region(oled_devno, 1);
err:
return err;
}
static void oled_exit(void)
{
if(flag)
{
gpio_free(CS);
gpio_free(DC);
gpio_free(RES);
gpio_free(DIN);
gpio_free(CLK);
}
device_destroy(oled_class,oled_devno);
class_destroy(oled_class);
cdev_del(&oled_dev);
unregister_chrdev_region(oled_devno, 1);
printk(KERN_INFO"OLED exit\n");
}
module_init(oled_init);
module_exit(oled_exit);
MODULE_LICENSE("GPL");
Makefile:
//Makefile
ifneq ($(KERNELRELEASE),)
obj-m := oled.o
else
KERNELDIR:=/home/rpi/linux/
PWD := $(shell pwd)
CROSS_COMPILE := arm-linux-gnueabihf-
default:
$(MAKE) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=arm -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.c *.order *.symvers
endif
However, when I wrote a program to open the device and write characters into it, there was no response from this OLED. And no error was logged into kern.log. What I really don't understand is why they behaved differently with the same control functions? Is there something fatal that I ignored?
Hey there wonderful community!
I'm back with a question regarding a console server application I've made with winsock. It's finally reaching a stage where I would need a to add a GUI, and to do so, I need it to be using the Windows subsystem.
And so I started the migration.
Yet I'm hitting a stack overflow somewhere in my application, and for the life of me I can't figure out where. Perhaps it has to do with WIN being a non-blocking subsystem (hope I used my vocab correctly).
Anyway, I hope to enlist you all as helpers. Many thanks :)
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <conio.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
int minitialize();
int msend(char msendbuf[512]);
char* mrecv(bool show);
int mshutdown();
void GoToXY(int column, int line);
int scroll(void);
int printm(char *inp);
int printm(char *inp, DWORD color);
int mexit();
char *vir = "true";
int clientnumber=0;
int currentclient=0;
int lastclient=0;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "10150"
struct _client
{
bool con;
sockaddr_in addr; //Client info like ip address
SOCKET cs; //Client socket
fd_set set; //used to check if there is data in the socket
std::string ip;
std::string name;
int i; //any piece of additional info
} client[100];
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
DWORD WINAPI recvfunc(LPVOID randparam)
{
while (true) {
ClientSocket=client[currentclient].cs;
if (mrecv(true)=="1") {
client[currentclient].con=false;
ClientSocket=client[lastclient].cs;
break;
}
}
return 0;
}
DWORD WINAPI headerfunc(LPVOID randparam)
{
Sleep(500);
while (true) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,0);
HANDLE hHeaderColor;
hHeaderColor = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hHeaderColor, FOREGROUND_GREEN);
std::cout<<"Server Started. Current Client:"<<currentclient<<" Clients connected: "<<clientnumber<<" ("<<xx<<","<<yy<<") "<<lastclient;
SetConsoleTextAttribute(hHeaderColor, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
GoToXY(xx,yy);
Sleep(2000);
}
return 0;
}
DWORD WINAPI sendfunc(LPVOID randparam)
{
while (true) {
char mmessage[512];
std::cin.getline(mmessage, 512);
if (strlen(mmessage)<2) {
GoToXY(0,23);
sendfunc("1");
}
char msendbuf[512]="Server> ";
strcat(msendbuf,mmessage);
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
if ((strncmp(msendbuf,"Server> /",9)) != 0) {
printm(msendbuf,FOREGROUND_INTENSITY);
}
GoToXY(0,23);
for (int sp=0; sp<72; sp++) {
std::cout<<" ";
}
GoToXY(0,23);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
minitialize();
HANDLE hRecvThread;
HANDLE hSendThread;
HANDLE hHeaderThread;
DWORD dwRecvThreadId;
DWORD dwSendThreadId;
DWORD dwHeaderThreadId;
hHeaderThread = CreateThread(NULL,0,headerfunc,"1",0,&dwHeaderThreadId);
for (int mf=2; mf<25; mf++) {
std::cout<<"\n";
}
hSendThread = CreateThread(NULL,0,sendfunc,"1",0,&dwSendThreadId);
// Accept a client socket
for (int sock=1; sock<100; sock++) {
ClientSocket = accept(ListenSocket, NULL, NULL);
char sockprint[80];
char sockchar[4];
itoa(sock,sockchar,10);
strcpy(sockprint,"Client ");
strcat(sockprint,sockchar);
strcat(sockprint," connected.");
printm(sockprint);
GoToXY(0,23);
if (ClientSocket == INVALID_SOCKET) {
printm("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
client[sock].cs=ClientSocket;
client[sock].con=true;
lastclient=clientnumber;
clientnumber++;
currentclient=clientnumber;
hRecvThread = CreateThread(NULL,0,recvfunc,"1",0,&dwRecvThreadId);
}
// shutdown the connection since we're done
mshutdown();
std::cin.ignore();
return 0;
}
int printm(char *inp, DWORD color) {
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
color);
printm(inp);
SetConsoleTextAttribute(hOut, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
return 0;
}
int printm(char *inp) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,22);
std::cout<<inp<<"\n";
scroll();
GoToXY(xx,yy);
return 1;
}
int msend(char msendbuf[512]) // Send a message
{
if (strncmp(msendbuf,"Server> /exit",(strlen(msendbuf))) == 0) {
mexit();
}
if (strncmp(msendbuf,"Server> /set_client",19) == 0) {
int nm=atoi(&msendbuf[20]);
currentclient=nm;
ClientSocket=client[nm].cs;
char sockchar[4];
itoa(ClientSocket,sockchar,10);
char sockprint[80];
strcpy(sockprint,"New Socket: ");
strcat(sockprint,sockchar);
printm(sockprint);
char clientprint[80];
strcpy(clientprint,"Client: ");
strcat(clientprint,&msendbuf[20]);
printm(clientprint);
}
if (strncmp(msendbuf,"Server> /list_clients",(strlen(msendbuf))) == 0) {
printm("Clients:",FOREGROUND_RED);
for (int cm=1; cm < 100; cm++) {
int cn=client[cm].cs;
if (cn>0) {
char cli[80];
char cmchar[4];
char cnchar[80];
itoa(cn,cnchar,10);
itoa(cm,cmchar,10);
strcpy(cli,cmchar);
strcat(cli," ");
strcat(cli,cnchar);
strcat(cli," ");
strcat(cli,client[cm].ip.c_str());
strcat(cli," ");
strcat(cli,client[cm].name.c_str());
printm(cli,FOREGROUND_RED);
}
else {
break;
}
}
}
if (strncmp(msendbuf,"Server> /test",(strlen(msendbuf))) == 0) {
char ipcon[500];
*ipcon=(system("ipconfig"));
}
if (strncmp(msendbuf,"Server> /help",(strlen(msendbuf))) == 0) {
printm("Type /help for help or:");
printm("/set_client [client number]");
printm("/list_clients");
}
int iResult3 = send( ClientSocket, msendbuf, 512, 0 );
if (iResult3 == SOCKET_ERROR) {
printm("send failed with error: %d\n", WSAGetLastError());
return 1;
}
}
char* mrecv(bool show) //Recieve a message
{
int iResult2 = recv(ClientSocket, recvbuf, 512, 0);
if (iResult2 > 0) {
if ((strncmp(recvbuf,"/",1)) != 0) {
printm(recvbuf);
}
if (strncmp(recvbuf,"/ip",3) == 0) {
client[clientnumber].ip=&recvbuf[4];
char prin[80];
strcpy(prin,"client[clientnumber].ip: ");
strcat(prin,client[clientnumber].ip.c_str());
printm(prin,FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/name",5) == 0) {
client[clientnumber].name=&recvbuf[6];
char prin2[80];
strcpy(prin2,"client[clientnumber].name: ");
strcat(prin2,client[clientnumber].name.c_str());
printm(prin2,FOREGROUND_GREEN | FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/alert",5) == 0) {
char *message=&recvbuf[7];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
if (strncmp(recvbuf,"Client> /alert",14) == 0) {
char *message=&recvbuf[15];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
}
else if (iResult2 == 0) {
printf("Connection closing...\n");
closesocket(ClientSocket);
WSACleanup();
return "1";
}
else {
printm("recv failed with error: %d\n", WSAGetLastError());
printm("Client must have disconnected. Please select a new client.");
return "1";
}
return recvbuf;
}
int minitialize() //initialize the winsock server
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printm("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printm("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printm("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printm("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printm("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
unsigned long b=1;
ioctlsocket(ClientSocket,FIONBIO,&b);
}
int mshutdown() //shutdown the server
{
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printm("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
void GoToXY(int column, int line)
{
// Create a COORD structure and fill in its members.
// This specifies the new position of the cursor that we will set.
COORD coord;
coord.X = column;
coord.Y = line;
// Obtain a handle to the console screen buffer.
// (You're just using the standard console, so you can use STD_OUTPUT_HANDLE
// in conjunction with the GetStdHandle() to retrieve the handle.)
// Note that because it is a standard handle, we don't need to close it.
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Finally, call the SetConsoleCursorPosition function.
if (!SetConsoleCursorPosition(hConsole, coord))
{
// Uh-oh! The function call failed, so you need to handle the error.
// You can call GetLastError() to get a more specific error code.
// ...
return;
}
}
int scroll( void )
{
HANDLE hStdout;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
SMALL_RECT srctScrollRect, srctClipRect;
CHAR_INFO chiFill;
COORD coordDest;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdout == INVALID_HANDLE_VALUE)
{
printf("GetStdHandle failed with %d\n", GetLastError());
return 1;
}
// Get the screen buffer size.
if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
printf("GetConsoleScreenBufferInfo failed %d\n", GetLastError());
return 1;
}
// The scrolling rectangle
srctScrollRect.Top = 1;
srctScrollRect.Bottom = 22;
srctScrollRect.Left = 0;
srctScrollRect.Right = csbiInfo.dwSize.X - 1;
// The destination for the scroll rectangle is one row up.
coordDest.X = 0;
coordDest.Y = 0;
// The clipping rectangle
srctClipRect.Top = 2;
srctClipRect.Bottom = 22;
srctClipRect.Left = 0;
srctClipRect.Right = csbiInfo.dwSize.X - 1;
// Fill the bottom row with blanks.
chiFill.Attributes = FOREGROUND_RED;
chiFill.Char.AsciiChar = (char)' ';
// Scroll up one line.
if(!ScrollConsoleScreenBuffer(
hStdout, // screen buffer handle
&srctScrollRect, // scrolling rectangle
&srctClipRect, // clipping rectangle
coordDest, // top left destination cell
&chiFill)) // fill character and color
{
printf("ScrollConsoleScreenBuffer failed %d\n", GetLastError());
return 1;
}
return 0;
}
int mexit()
{
msend("/server_closed");
mshutdown();
exit(0);
}
Turns out it was the recursive calling in my "sendfunc" thread that tripped me up.
Specifically,
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
Because I continued to call "sendfunc" from itself, it caused the stack overflow.
So, for anyone else having these problems, watch for overkill recursive function calls.
I simply removed my sending function and I was good to go.