後來才知道DevC++已經沒有在更新了
所以…
codeblocks + MSVCRT runtime (UCRT runtime這兩個不知道有什麼分別)
CodeBlock安裝好後,
把MinGW-w64解壓縮後,放到某個路徑下
CodeBlock, Setting->Compiler
有Toolchain executables,
這裡指定MinGW-w64的路徑,ex: C:\mingw64\
如果有另外的library(可以在 mingw64 資料夾下找尋)
就在Linker settings那加入
2023年8月28日 星期一
Search for a specific COM port on Win10
#include <windows.h>
#include <setupapi.h>
#include <stdio.h>
#include <devguid.h>
#include <wchar.h>
#define SEARCH_STRINT "Cinterion PLSx3 USB Com Port1 "
int main() {
// Get a handle to a device information set for COM ports
HDEVINFO hdevinfo;
//GUID ClassGuid = {0x4d36e978,0xe325,0x11ce,{0xbf,0xc1,0x08,0x00,0x2b,0xe1,0x03,0x18}};
GUID guid = {0x4d36e978,0xe325,0x11ce,{0xbf,0xc1,0x08,0x00,0x2b,0xe1,0x03,0x18}}; //GUID_DEVCLASS_PORTS
//查到資料大多這樣寫,devguid.h也宣告了
//但mingw64編譯卻一直說找不到GUID_DEVCLASS_USB @@
//所以改用查guid碼方式來避開
//hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_USB, 0, 0, DIGCF_PRESENT);
hdevinfo = SetupDiGetClassDevs((LPGUID)&guid, NULL, NULL, DIGCF_PRESENT );
if (hdevinfo == INVALID_HANDLE_VALUE) {
printf("SetupDiGetClassDevs failed with error code %d\n", GetLastError());
return 1;
}
// Enumerate through the COM ports
SP_DEVINFO_DATA devinfoData;
devinfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SP_DEVICE_INTERFACE_DATA interfaceData;
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
DWORD index = 0;
for(index=0; SetupDiEnumDeviceInfo(hdevinfo, index, &devinfoData); index++)
{
wchar_t friendlyName[128];
if (SetupDiGetDeviceRegistryProperty(hdevinfo, &devinfoData, SPDRP_HARDWAREID, NULL, (BYTE*)friendlyName, sizeof(friendlyName), NULL))
{
// Check if the COM port information matches the USB modem's VID and PID
//printf("friendlyName=%s\n", friendlyName);
char cpy[128];
char comport[COMPORT_SIZE];
strcpy(cpy, (char *)friendlyName);
//printf("%d. cpy=%s\n", (int)index, cpy);
if (strcmp(cpy, SEARCH_STR0))
continue;
if (SetupDiGetDeviceRegistryProperty(hdevinfo, &devinfoData, SPDRP_FRIENDLYNAME, NULL, (BYTE*)friendlyName, sizeof(friendlyName), NULL))
{
strcpy(cpy, (char *)friendlyName);
//printf("%d. cpy=%s\n", (int)index, cpy);
char *p;
p = strtok(cpy, SEARCH_STR2);
for (; p != NULL; )
{
//printf( "pp=%s\n", p );
p = strtok(NULL, "M");
if(p)
strncpy(comport, p, COMPORT_SIZE);
}
}
//printf("p=%s, len=%zu\n", comport, strlen(comport));
comport[strlen(comport)-1]='\0';
//printf("comport=%s\n", comport);
strcpy(com, comport);
//printf("com=%s\n", com);
}
}
// Clean up
SetupDiDestroyDeviceInfoList(hdevinfo);
return 0;
}
Ref: ChatGPT
2023年8月25日 星期五
List all serial com port on Win10
Copied the code from Here
Output:
ref:
Here
#define WIN32_LEAN_AND_MEAN // excludes stuff frokm windows.h that we won't need here.
#include <Windows.h>
#include <string.h>
#include <tchar.h>
#include <malloc.h>
#include <stdio.h>
void ShowErrorFromLStatus(LSTATUS lResult)
{
LPTSTR psz;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
lResult,
0,
(LPTSTR)&psz,
1024,
NULL);
_tprintf(_T("Windows reports error: (0x%08X): %s\n"), lResult, (psz) ? psz : _T("(null)"));
if (psz)
{
LocalFree(psz);
}
}
int main()
{
DWORD nValues, nMaxValueNameLen, nMaxValueLen;
HKEY hKey = NULL;
LPTSTR szDeviceName = NULL;
LPTSTR szFriendlyName = NULL;
DWORD dwType = 0;
DWORD nValueNameLen = 0;
DWORD nValueLen = 0;
DWORD dwIndex = 0;
LSTATUS lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_READ, &hKey);
if (ERROR_SUCCESS != lResult)
{
printf("Failed to open key \'HARDWARE\\DEVICEMAP\\SERIALCOMM\' \n");
ShowErrorFromLStatus(lResult);
return 1;
}
lResult = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
&nValues, &nMaxValueNameLen, &nMaxValueLen, NULL, NULL);
if (ERROR_SUCCESS != lResult)
{
_tprintf(_T("Failed to RegQueryInfoKey()\n"));
ShowErrorFromLStatus(lResult);
RegCloseKey(hKey);
return 2;
}
szDeviceName = (LPTSTR)malloc(nMaxValueNameLen + sizeof(TCHAR));
if (!szDeviceName)
{
_tprintf(_T("malloc() fail\n"));
RegCloseKey(hKey);
return 3;
}
szFriendlyName = (LPTSTR)malloc(nMaxValueLen + sizeof(TCHAR));
if (!szFriendlyName)
{
free(szDeviceName);
_tprintf(_T("malloc() fail\n"));
RegCloseKey(hKey);
return 3;
}
_tprintf(_T("Found %d serial device(s) registered with PnP and active or available at the moment.\n"), nValues);
for (DWORD dwIndex = 0; dwIndex < nValues; ++dwIndex)
{
dwType = 0;
nValueNameLen = nMaxValueNameLen + sizeof(TCHAR);
nValueLen = nMaxValueLen + sizeof(TCHAR);
lResult = RegEnumValueW(hKey, dwIndex,
(LPWSTR)szDeviceName, &nValueNameLen,
NULL, &dwType,
(LPBYTE)szFriendlyName, &nValueLen);
if (ERROR_SUCCESS != lResult || REG_SZ != dwType)
{
_tprintf(_T("SerialPortEnumerator::Init() : can't process registry value, index: %d\n"), dwIndex);
ShowErrorFromLStatus(lResult);
continue;
}
_tprintf(_T("Found port \'%ls\': Device name for CreateFile(): \'\\.%ls\'\n"), szFriendlyName, szDeviceName);
}
free(szDeviceName);
free(szFriendlyName);
RegCloseKey(hKey);
return 0;
}
Output:
C:\Test>auto_com_port.exe
Found 8 serial device(s) registered with PnP and active or available at the moment.
Found port 'COM1': Device name for CreateFile(): '\.\Device\Serial0'
Found port 'COM24': Device name for CreateFile(): '\.\Device\USBSER00COM24'
Found port 'COM25': Device name for CreateFile(): '\.\Device\USBSER00COM25'
Found port 'COM22': Device name for CreateFile(): '\.\Device\USBSER00COM22'
Found port 'COM23': Device name for CreateFile(): '\.\Device\USBSER00COM23'
Found port 'COM15': Device name for CreateFile(): '\.\Device\QCUSB_COCOM15'
Found port 'COM16': Device name for CreateFile(): '\.\Device\QCUSB_COCOM16'
Found port 'COM17': Device name for CreateFile(): '\.\Device\QCUSB_COCOM17'
ref:
Here
2022年9月30日 星期五
xdo on linux (按鍵精靈)
xdo, 按鍵精靈, works on XUbuntu 20.04
Install:
Exsample:
get current mouse coordinates:
ref:
1. How would I get the current mouse coordinates in bash?
2. C language - trigger key events in Linux with xdo
Install:
$ sudo apt-get install libxdo-dev libxdo3 xdotool
Exsample:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xdo.h>
#include <unistd.h>
void mouse_left_click(const xdo_t *xdo, int x, int y)
{
xdo_click_window(xdo, CURRENTWINDOW, Button1); //left mouse key
return;
}
void keyboard_enter_string(const xdo_t *xdo, const char *str, size_t slen)
{
int i=0;
char character[2]={'\0'};
for(i=0; i<slen; i++)
{
character[0]=*(str+i);
xdo_send_keysequence_window(xdo, CURRENTWINDOW, character, 0);
}
return;
}
int main(void)
{
//xdo_t *x = xdo_new(":0.0");
xdo_t * x = xdo_new(NULL);
xdo_send_keysequence_window(x, CURRENTWINDOW, "Alt_L+Tab", 0);
sleep(3);
xdo_move_mouse(x, 628, 435, CURRENTWINDOW);
sleep(2);
mouse_left_click(x, 0, 0);
//xdo_send_keysequence_window(x, CURRENTWINDOW, "Alt_L+Tab", 0);
//sleep(1);
////keyboard_enter_string(x, "Hello", strlen("Hello"));
xdo_enter_text_window(x, CURRENTWINDOW, "hello world", 1000);
//xdo_send_keysequence_window(x, CURRENTWINDOW, "KP_Enter", 0); //ok
//xdo_send_keysequence_window(x, CURRENTWINDOW, "Alt_L+F4", 0); //ok
//xdo_send_keysequence_window(x, CURRENTWINDOW, "Shift_L+Super_L+s", 0); //ok
xdo_free(x);
return 0;
}
$ gcc example.c -o ex -lxdo
get current mouse coordinates:
$ xdotool getmouselocation --shell
ref:
1. How would I get the current mouse coordinates in bash?
2. C language - trigger key events in Linux with xdo
2022年9月18日 星期日
Parse CCLK with strptime
example:
ref:
strptime
PLS83, RIL(libril-cwm-lte) network.c
Other keywords in Android:
ref:
1. android 手機的網絡時間同步
2. https://www.itdaan.com/tw/7a3b63850d9d
ctime="+CCLK: "22/09/19,03:21:12+32""
void parsetime (const char *ctime)
{
char ptime[32]; //parse time
char *buf=(char *)malloc(sizeof(char) * 32);
struct tm tt;
time_t putime, \
nutime;
int time_zone=0;
sscanf(ctime, "%s %s", buf, ptime);
free(buf);
buf=strstr(ptime, "+");
if (buf == NULL)
buf=strstr(ptime, "-");
if (buf == NULL)
{
printf("err: can't find the time zone\n");
exit(1);
}
ptime[strlen(ptime)-strlen(buf)]='\0'; //remove time zone and late character
buf++; //get time zone
time_zone=atoi(buf);
buf=ptime+1; //remove first character
strncpy(ptime, buf, 32);
printf("time_zone=%d, buf=%s, ptime=%s\n", time_zone, buf, ptime);
strptime(ptime, "%y/%m/%d,%H:%M:%S", &tt);
tt.tm_hour+=(time_zone/4);
printf("tm_sec: %d\n",tt.tm_sec);
printf("tm_min: %d\n",tt.tm_min);
printf("tm_hour: %d\n",tt.tm_hour);
printf("tm_mday: %d\n",tt.tm_mday);
printf("tm_mon: %d\n",tt.tm_mon+1);
printf("tm_year: %d\n",tt.tm_year-100);
putime = mktime(&tt);
nutime=(long int)time(NULL);
printf("nutime-putime=%ld\n", nutime-putime);
return;
}
ref:
strptime
PLS83, RIL(libril-cwm-lte) network.c
void parseNITZresponse(char *szNITZrepsonse)
{
...
...
// All parameters available: generate NITZ notifications.
generateNITZnotification(nitzUtUCS2, nitzTZ, nitzDST);
}
other keywords:
RIL_UNSOL_NITZ_TIME_RECEIVED
Other keywords in Android:
frameworks/opt/telephony/src/java/com/android/internal/telephony/ServiceStateTracker.java
setTimeFromNITZString(nitzString, nitzReceiveTime)
ref:
1. android 手機的網絡時間同步
2. https://www.itdaan.com/tw/7a3b63850d9d
2022年7月24日 星期日
AT command and PLS83
read: cat /dev/ttyACM0
write: echo "ACT" > /dev/ttyACM0
read line: get_next_line.git
main.c
utool.c
utool.h
write: echo "ACT" > /dev/ttyACM0
read line: get_next_line.git
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <limits.h>
#include "get_next_line.h"
#include "utool.h"
#define TEST_THERMAL 1
#if TEST_THERMAL
const char *Thermal_atc[] =
{
"at\r",
"ati1\r",
"at+csq\r",
"at^sctm=1,1\r",
"at^sctm?\r"
};
#else //connect to Internet
const char *QMI_atc[] =
{
"at\r",
"at+cpin?\r",
"at+cops?\r",
};
const char *ECM_atc[] =
{
"at\r",
"at+cpin?\r",
"at+cops?\r",
"AT+CGPADDR=?\r,"
"AT+CGPADDR\r",
"AT+CGPADDR=1,1\r",
"AT^SWWAN=?\r",
"AT^SWWAN?\r",
"AT^SWWAN=1,1,1\r",
};
//QMI, PID=006F
const char *QMIMODE[] =
{
"at^ssrvset=\"actSrvset\",11\r",
"at+cfun=1,1"
};
//ECM, PID=0069
const char *ECMMODE[] =
{
"at^ssrvset=\"actSrvset\",1\r",
"at+cfun=1,1"
};
#endif
int STOP_PROCESS=0;
void *test_cat(void *fd_)
{
#ifdef TEST_THERMAL
#else
char *err="";
#endif
int fd= *((int *)fd_);
int ret=0;
char *line;
while ((ret = get_next_line(fd, &line)) == STATUS_LINE)
{
printf("output=%s\n", line);
#ifdef TEST_THERMAL
#else
err=strstr(line, "ERR");
if ( err != NULL)
{
STOP_PROCESS=1;
printf(cRED "err=%s\n" cRESET, err);
pthread_exit(NULL);
}
err=strstr(line, "SHUTDOWN");
if ( err != NULL)
{
STOP_PROCESS=1;
printf(cRED "err=%s\n" cRESET, err);
pthread_exit(NULL);
}
#endif
free(line);
}
if (ret == -1)
printf("error\n");
else if (ret == 0)
{
printf("at EOF: [%s]\n", line);
free(line);
printf("EOF\n");
}
printf("thread done\n");
return NULL;
}
int todoECM(void)
{
ssize_t size=128;
char *file_path=(char *)malloc(sizeof(char)*size);
char *wwan_path=(char *)malloc(sizeof(char)*size);
char *wwan;
char *cmd=(char *)malloc(sizeof(char)*size);
int fd;
DIR *d;
struct dirent *dir;
char *line;
int ret=0;
char *sret;
ssize_t slen=0;
d = opendir("/sys/class/net");
if (d)
{
while ((dir = readdir(d)) != NULL)
{
printf("%s\n", dir->d_name);
if (strlen (dir->d_name) <= 2)
continue;
sprintf(file_path, "/sys/class/net/%s/uevent", dir->d_name);
printf("file_path=%s\n", file_path);
fd=open(file_path, O_RDONLY);
while ((ret = get_next_line(fd, &line)) == STATUS_LINE)
{
printf("line=%s\n", line);
sret=strstr(line, "wwan");
slen =( sret == NULL ? 0 : strlen(sret));
if (slen > 0)
break;
}
if (slen > 0)
if (get_next_line(fd, &line) == STATUS_LINE)
{
printf("line2=%s\n", line);
break;
}
}
closedir(d);
}
wwan=strtok(line, "=");
wwan=strtok(NULL, "=");
printf("wwan=%s\n", wwan);
sprintf(cmd, "sudo ifconfig %s up", wwan);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
sprintf(cmd, "sudo dhclient %s", wwan);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
free(cmd);
free(wwan_path);
return 0;
}
int todoQMI(void)
{
int i=0;
ssize_t size=128;
char *cdcwdm_path =(char *)malloc(sizeof(char)*size);
char *wwan_path=(char *)malloc(sizeof(char)*size);
char wwan[8];
char *cmd=(char *)malloc(sizeof(char)*size);
for (i=0; i<9; i++) // Suppose cdc-wdm ranges from 0 to 9
{
memset(cdcwdm_path, '\0', sizeof(char)*size);
sprintf(cdcwdm_path, "/dev/cdc-wdm%d", i);
if ( access(cdcwdm_path, F_OK) == 0 ) //file exists
break;
}
sprintf(cmd, "sudo qmicli -d %s -p --dms-get-operating-mode", cdcwdm_path);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char)*size);
sprintf(cmd, "sudo qmicli -d %s -p --get-wwan-iface", cdcwdm_path);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
for (i=0; i<9; i++) // Suppose cdc-wdm ranges from 0 to 9
{
memset(wwan_path, '\0', sizeof(char)*size);
sprintf(wwan_path, "/sys/class/net/wwan%d", i);
if ( access(wwan_path, F_OK) == 0 ) //file exists
{
sprintf(wwan, "wwan%d", i);
break;
}
}
sprintf(cmd, "sudo ip link set %s down", wwan);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
sprintf(cmd, "echo \'Y\' | sudo tee /sys/class/net/%s/qmi/raw_ip", wwan);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
sprintf(cmd, "udo ip link set %s up", wwan);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
sprintf(cmd, "sudo qmicli -p -d %s -p --wds-start-network=\"apn='Internet',ip-type=4\" --client-no-release-cid", cdcwdm_path);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
sprintf(cmd, "sudo udhcpc -i %s", wwan);
printf("cmd=%s\n", cmd);
system(cmd);
memset(cmd, '\0', sizeof(char));
free(cmd);
free(wwan_path);
free(cdcwdm_path);
return 0;
}
int main (void)
{
pthread_t thread1;
char *getMode=(char *)malloc(sizeof(char)*32);
void *ret;
int fd=-1;
int i=0;
ssize_t count=0;
int sleep_time=0;
const char **MODE_atc;
int (*todoMode)(void)=NULL;
fd=open("/dev/ttyACM0", O_RDWR);
if (fd < 0)
{
printf("cant' find the ACM0\n");
}
isPID69or6f(&getMode);
printf("get_mode=%s\n", getMode);
pthread_create(&thread1, NULL, test_cat, (void *)&fd);
#if TEST_THERMAL
//count=sizeof(Thermal_atc)/sizeof(Thermal_atc[0]);
count=NUM_ELEMS(Thermal_atc);
printf("count=%ld\n", count);
sleep_time = 500*2;
for (i=0 ; STOP_PROCESS == 0; i++)
{
if (i == count)
i=0;
//printf(cGREEN "start the process...atc=%s\n" cRESET, Thermal_atc[i]);
//write(fd, Thermal_atc[i], strlen(Thermal_atc[i]));
MODE_atc=Thermal_atc;
#else
if (!strcmp("QMI", getMode))
{
//QMI to do
//count=sizeof(QMI_atc)/sizeof(QMI_atc[0]);
count=NUM_ELEMS(QMI_atc[0]);
printf("count=%ld\n", count);
MODE_atc=QMI_atc;
todoMode=todoQMI;
}
else
{
//ECM to do
//count=sizeof(ECM_atc)/sizeof(ECM_atc[0]);
count=NUM_ELEMS(ECM_atc);
printf("count=%ld\n", count);
MODE_atc=ECM_atc;
todoMode=todoECM;
}
sleep_time = 500;
for (i=0; i < count && STOP_PROCESS == 0; i++)
{
#endif
printf(cGREEN "start the process...%s, atc=%s\n" cRESET, getMode, MODE_atc[i]);
write(fd, MODE_atc[i], strlen(MODE_atc[i]));
msleep(sleep_time);
}
todoMode();
if (i == count)
{
printf("iiii=%d, count=%ld\n", i, count);
pthread_cancel(thread1);
close(fd);
}
pthread_join( thread1, (void *)(&ret));
printf("main done\n");
free(getMode);
return 0;
}
utool.c
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include "utool.h"
void msleep(unsigned long msec) {
struct timespec ts;
int err;
ts.tv_sec = (msec / 1000);
ts.tv_nsec = (msec % 1000) * 1000 * 1000;
do {
err = nanosleep (&ts, &ts);
} while (err < 0 && errno == EINTR);
}
//缺點:USB沒有拔掉的話,路徑好像不會被移除
int isPID69or6f(char **mode)
{
const char *QMIpath="/sys/bus/usb/drivers/qmi_wwan";
const char *ECMpath="/sys/bus/usb/drivers/cdc_acm"; //or cdc_ether
if ( access(QMIpath, F_OK) == 0 ) //file exists
{
strcpy( *mode, "QMI");
printf(cRED "QMI mode\n" cRESET);
}
else if ( access(ECMpath, F_OK) == 0 )
{
strcpy( *mode, "ECM");
printf(cRED "ECM mode\n" cRESET);
}
return 0;
}
utool.h
#include <pthread.h>
#define cRED "\x1b[;31;1m"
#define cGREEN "\x1b[;32;1m"
#define cRESET "\x1b[0;m"
#define NUM_ELEMS(a) (sizeof(a) / sizeof(a[0]))
int isPID69or6f(char **mode);
void msleep(unsigned long msec);
int executeSystemCmd(const char *cmd, char **response, int timeout);
2021年8月11日 星期三
basic CMakeLists.txt for hello_world
$ tree
CMakeLists.txt (下面還有一個,比較好用, Cross compile for Android)
不要在ndk中使用系统预编译好的C++库
main.cpp
test.cpp
test.h
compile
ref:
1. cmake
2. How to cross-compile for embedded with CMake like a champ
3. 不要在ndk中使用系统预编译好的C++库
4. CMake 入門/運算子
5. 关于安卓的交叉编译
CMakeLists.txt
linux-android.toolchain.cmake
compile
cmake-hello-world/
├── CMakeLists.txt
├── linux-android.toolchain.cmake
└── src
├── main.cpp
└── TestHello
├── test.cpp
└── test.h
CMakeLists.txt (下面還有一個,比較好用, Cross compile for Android)
APP_STL := c++_shared or c++_staticcmake_minimum_required (VERSION 3.10) project (CMakeHelloWorld) #version number set (CMakeHelloWorld_VERSION_MAJOR 1) set (CMakeHelloWorld_VERSION_MINOR 0) message (STATUS "CXX is $ENV{CXX}") set(argument_list) option(USE_ANDROID "" OFF) #OFF by default if (USE_ANDROID) set (CMAKE_ANDROID_ARCH_ABI arm64-v8a) set (ANDROID_STL "c++_static") set (CMAKE_CXX_COMPILER $ENV{CXX}) set (CMAKE_AR $ENV{AR}) set (CMAKE_RANLIB $ENV{RANLIB}) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") endif() include_directories(src/TestHello) # 指定 include header path set(HELLO_SOURCES src/TestHello/test.cpp) # 設定變數, 將第二個所給予的內容指定到第一個變數名稱當中 #set(HELLO_SOURCES src/HelloWorld.cpp) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) # PROJECT....是CMAKE寫好的變數 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) #add_library(test_hello SHARED src/main.cpp src/TestHello/test.cpp src/TestHello/test.h) add_library(hello ${HELLO_SOURCES}) #add_library(hello2 ${HELLO_SOURCES2}) add_executable(main src/main.cpp ${HELLO_SOURCES}) # 產生可執行檔 if (USE_ANDROID) #target_link_libraries需寫在add_executable的下方 target_link_libraries(main hello-latomic -lc++_static -lc++abi) else()target_link_libraries(main hello) endif()
不要在ndk中使用系统预编译好的C++库
main.cpp
#include <test.h>
using namespace std;
int main(void)
{
Test t;
t.Hello();
}
test.cpp
#include "test.h"
using namespace std;
void Test::Hello(void)
{
cout << "Hello, world!\n" << endl;
}
test.h
#include <stdio.h>
#include <iostream>
using namespace std;
class Test{
public:
void Hello (void);
};
compile
$ mkdir build; cd build
$ cmake ..
or
$ cmake -D USE_ANDROID=ON ..
沒有問題後
$ cd build
$ make
ref:
1. cmake
2. How to cross-compile for embedded with CMake like a champ
3. 不要在ndk中使用系统预编译好的C++库
4. CMake 入門/運算子
5. 关于安卓的交叉编译
CMakeLists.txt
cmake_minimum_required (VERSION 3.10) project (CMakeHelloWorld) #version number set (CMakeHelloWorld_VERSION_MAJOR 1) set (CMakeHelloWorld_VERSION_MINOR 0) message (STATUS "CXX is $ENV{CXX}") set(argument_list) option(USE_ANDROID "" OFF) #OFF by default if (USE_ANDROID) set (CMAKE_ANDROID_ARCH_ABI arm64-v8a) set (ANDROID_STL "c++_static") set (CMAKE_CXX_COMPILER $ENV{CXX}) set (CMAKE_AR $ENV{AR}) set (CMAKE_RANLIB $ENV{RANLIB}) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif() include(CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) if(COMPILER_SUPPORTS_CXX11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") elseif(COMPILER_SUPPORTS_CXX0X) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") else() message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif() include_directories(src/TestHello) # 指定 include header path #set(HELLO_SOURCES src/TestHello/test.cpp) # 設定變數, 將第二個所給予的內容指定到第一個變數名稱當中 file(GLOB SOURCES src/TestHello/*.cpp src/TestHello/*.h) #set(HELLO_SOURCES src/HelloWorld.cpp) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) # PROJECT....是CMAKE寫好的變數 set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) #add_library(test_hello SHARED src/main.cpp src/TestHello/test.cpp src/TestHello/test.h) #add_library(hello ${HELLO_SOURCES}) #add_library(hello2 ${HELLO_SOURCES2}) add_executable(main src/main.cpp ${SOURCES}) # 產生可執行檔 if (USE_ANDROID) target_link_libraries(main-latomic -lc++_static -lc++abi) else()target_link_libraries(main)endif()
linux-android.toolchain.cmake
if (USE_ANDROID)
if (NOT NDKDIR)
message(FATAL_ERROR "Set NDK_DIR, Recommended version 22.1.7171670")
endif()
#set (NDK "/opt/android_studio/sdk/ndk/22.1.7171670")
set (TOOLCHAIN "${NDKDIR}/toolchains/llvm/prebuilt/linux-x86_64")
#set (CMAKE_ANDROID_API 29)
set (ANDROID_STL "c++_static")
if (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "arm64-v8a")
set (TARGET "aarch64-linux-android")
elseif (${CMAKE_ANDROID_ARCH_ABI} STREQUAL "armeabi-v7a")
set (TARGET "armv7a-linux-androideabi")
else()
set (TARGET "x86_64-linux-android")
endif()
set (CMAKE_C_COMPILER ${TOOLCHAIN}/bin/${TARGET}${CMAKE_ANDROID_API}-clang)
message (STATUS "1111111111 is ${CMAKE_C_COMPILER}")
set (CMAKE_CXX_COMPILER ${TOOLCHAIN}/bin/${TARGET}${CMAKE_ANDROID_API}-clang++)
set (CMAKE_AR ${TOOLCHAIN}/bin/${TARGET}$-ar)
set (CMAKE_RANLIB ${TOOLCHAIN}/bin/${TARGET}$-ranlib)
# set searching rules for cross-compiler
SET (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
compile
$ mkdir build; cd build
$ cmake -D USE_ANDROID=ON -D CMAKE_TOOLCHAIN_FILE=../linux-android.toolchain.cmake -D NDKDIR=/opt/android_studio/sdk/ndk/22.1.7171670 -D CMAKE_ANDROID_ARCH_ABI=arm64-v8a -D CMAKE_ANDROID_API=29 ..
沒有問題後
$ make
標籤:
Android apk,
C
2021年3月12日 星期五
Get EDID
1. EDID 1.4 Spec
2. EDID解析
3. EDID簡介
cp /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-HDMI-A-1/edid ~/edid.txt
可以再把輸出放到此網站分析, Here
2. EDID解析
3. EDID簡介
$ sudo find /sys/ | grep -i edid /sys/kernel/debug/dri/0/HDMI-A-1/edid_override /sys/kernel/debug/dri/0/VGA-1/edid_override /sys/kernel/debug/dri/0/eDP-1/edid_override /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-HDMI-A-1/edid /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-VGA-1/edid /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-eDP-1/edid /sys/module/drm_kms_helper/parameters/edid_firmware /sys/module/drm/parameters/edid_firmware /sys/module/drm/parameters/edid_fixup
#include <stdio.h>
#include <string.h>
#include <stdint.h>
int main()
{
FILE *fp;
char ch[1];
int i=0, j=0;
fp = fopen("eee.txt", "r");
for (i=0; i<16; i++)
printf(" %2X", i);
printf("\n");
i=0, j=0;
for(;fread(ch, sizeof(ch), 1, fp);)
{
if (j==0)
printf("0");
if (j%16==0)
printf("%1x ", j);
printf("0x%2.2x ", (uint8_t)ch[0]);
i++; j++;
if(i==16)
{
printf("\n");
i=0;
}
}
fclose(fp);
return 0;
}
輸出:
0 1 2 3 4 5 6 7 8 9 A B C D E F 00 0x00 0xff 0xff 0xff 0xff 0xff 0xff 0x00 0x10 0xac 0x79 0xa0 0x4c 0x31 0x37 0x32 10 0x24 0x16 0x01 0x03 0x80 0x34 0x20 0x78 0xea 0xee 0x95 0xa3 0x54 0x4c 0x99 0x26 20 0x0f 0x50 0x54 0xa1 0x08 0x00 0x81 0x40 0x81 0x80 0xa9 0x40 0xb3 0x00 0xd1 0xc0 30 0x01 0x01 0x01 0x01 0x01 0x01 0x28 0x3c 0x80 0xa0 0x70 0xb0 0x23 0x40 0x30 0x20 40 0x36 0x00 0x06 0x44 0x21 0x00 0x00 0x1a 0x00 0x00 0x00 0xff 0x00 0x59 0x52 0x34 50 0x38 0x56 0x32 0x39 0x38 0x32 0x37 0x31 0x4c 0x0a 0x00 0x00 0x00 0xfc 0x00 0x44 60 0x45 0x4c 0x4c 0x20 0x55 0x32 0x34 0x31 0x32 0x4d 0x0a 0x20 0x00 0x00 0x00 0xfd 70 0x00 0x32 0x3d 0x1e 0x53 0x11 0x00 0x0a 0x20 0x20 0x20 0x20 0x20 0x20 0x01 0x65 80 0x02 0x03 0x1b 0x61 0x23 0x09 0x07 0x07 0x83 0x01 0x00 0x00 0x67 0x03 0x0c 0x00 90 0x20 0x00 0x80 0x2d 0x43 0x90 0x84 0x02 0xe2 0x00 0x0f 0x8c 0x0a 0xd0 0x8a 0x20 a0 0xe0 0x2d 0x10 0x10 0x3e 0x96 0x00 0xa0 0x5a 0x00 0x00 0x00 0x00 0x00 0x00 0x00 b0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 c0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 d0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 e0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 f0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x29
可以再把輸出放到此網站分析, Here
GStreamer(Gst) - play wav file
環境: apq8009
gst-launch-1.0
copy if from gst_HelloWorld and modify it
Compile:
gcc -Wall helloworld.c -o helloworld $(pkg-config --cflags --libs gstreamer-1.0)
Makefile
ref:
1. gst_HelloWorld(basic-tutorial-1.c)
2. gst_Seeking_example(basic-tutorial-4.c)
3. gst_plugin
gst-launch-1.0
gst-launch-1.0 filesrc location=a.wav ! wavparse ! audioconvert ! autoaudiosink
copy if from gst_HelloWorld and modify it
#include <gst/gst.h> #include <glib.h> static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) { GMainLoop *loop = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_print ("End of stream\n"); g_main_loop_quit (loop); break; case GST_MESSAGE_ERROR: { gchar *debug; GError *error; gst_message_parse_error (msg, &error, &debug); g_free (debug); g_printerr ("Error: %s\n", error->message); g_error_free (error); g_main_loop_quit (loop); break; } default: break; } return TRUE; } static void on_pad_added (GstElement *element, GstPad *pad, gpointer data) { GstPad *sinkpad; GstElement *decoder = (GstElement *) data; /* We can now link this pad with the vorbis-decoder sink pad */ g_print ("Dynamic pad created, linking demuxer/decoder\n"); sinkpad = gst_element_get_static_pad (decoder, "sink"); gst_pad_link (pad, sinkpad); gst_object_unref (sinkpad); } int main (int argc, char *argv[]) { GMainLoop *loop; GstElement *pipeline, *source, *decoder, *conv, *sink; GstBus *bus; guint bus_watch_id; /* Initialisation */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* Check input arguments */ if (argc != 2) { g_printerr ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]); return -1; } /* Create gstreamer elements */ pipeline = gst_pipeline_new ("audio-player"); source = gst_element_factory_make ("filesrc", "file-source"); decoder = gst_element_factory_make ("wavparse", "wav-decoder"); conv = gst_element_factory_make ("audioconvert", "converter"); sink = gst_element_factory_make ("autoaudiosink", "audio-output"); if (!pipeline || !source || !decoder || !conv || !sink) { g_printerr ("One element could not be created. Exiting.\n"); return -1; } g_object_set (G_OBJECT (source), "location", argv[1], NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); bus_watch_id = gst_bus_add_watch (bus, bus_call, loop); gst_object_unref (bus); gst_bin_add_many (GST_BIN (pipeline), source, decoder, conv, sink, NULL); gst_element_link_many (source, decoder, conv, sink, NULL); g_signal_connect (source, "pad-added", G_CALLBACK (on_pad_added), decoder); g_print ("Now playing: %s\n", argv[1]); gst_element_set_state (pipeline, GST_STATE_PLAYING); g_print ("Running...\n"); g_main_loop_run (loop); g_print ("Returned, stopping playback\n"); gst_element_set_state (pipeline, GST_STATE_NULL); g_print ("Deleting pipeline\n"); gst_object_unref (GST_OBJECT (pipeline)); g_source_remove (bus_watch_id); g_main_loop_unref (loop); return 0; }
Compile:
gcc -Wall helloworld.c -o helloworld $(pkg-config --cflags --libs gstreamer-1.0)
Makefile
CC=gcc CFLAGS = -MMD CFLAGS += `pkg-config --cflags --libs gstreamer-1.0` CFLAGS += -lrt -lpthread SRCS=$(shell ls *.c) OBJS = $(patsubst %.c, %.o, $(SRCS)) #Output OUT_DIR = build OUT_OBJS = $(addprefix $(OUT_DIR)/, $(OBJS)) DEPS = $(patsubst %.o, %.d, $(OUT_OBJS)) TARGET = y_gst_server $(OUT_DIR)/$(TARGET): $(OUT_OBJS) $(CC) -o $@ $^ $(CFLAGS) $(OUT_DIR)/%.o:%.c mkdir -p $(OUT_DIR) $(CC) -c $< -o $@ $(CFLAGS) clean: -rm -rf $(OUT_DIR) $(TARGET) $(OBJS)
1. gst_HelloWorld(basic-tutorial-1.c)
2. gst_Seeking_example(basic-tutorial-4.c)
3. gst_plugin
2021年2月22日 星期一
bluethoothctl with C
Server Mode (Playback from external BT source)
無法啟動 power on
查找原因
解決
ref:
1. Cannot unblock soft-blocked bluetooth
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
int pfds[2];
int status;
pid_t pid;
if ( pipe(pfds) == -1 )
{
perror("pipe error\n");
exit(1);
}
pid = fork();
if ( pid == 0 ) //child, run the bluetoothctl command
{
close(STDIN_FILENO);
dup2( pfds[0], STDIN_FILENO );
close( pfds[1] );
execl("/usr/bin/bluetoothctl", "bluetoothctl", (char*) NULL);
exit(0);
}
else //father, send the command to bluetoothctl
{
close(STDOUT_FILENO);
dup2( pfds[1], STDOUT_FILENO );
write(STDOUT_FILENO, "power on\n", strlen("power off\n"));
sleep(1);
write(STDOUT_FILENO, "agent on\n", strlen("agent on\n"));
write(STDOUT_FILENO, "default-agent\n", strlen("default-agent\n"));
write(STDOUT_FILENO, "pairable on\n", strlen("pairable on\n"));
write(STDOUT_FILENO, "pair A8:87:B3:1E:D9:66\n", strlen("pair A8:87:B3:1E:D9:66\n"));
write(STDOUT_FILENO, "trust A8:87:B3:1E:D9:66\n", strlen("trust A8:87:B3:1E:D9:66\n"));
write(STDOUT_FILENO, "connect A8:87:B3:1E:D9:66\n", strlen("connect A8:87:B3:1E:D9:66\n"));
sleep(2);
write(STDOUT_FILENO, "exit\n", strlen("exit\n"));
write(STDOUT_FILENO, "connect A8:87:B3:1E:D9:66\n", strlen("connect A8:87:B3:1E:D9:66\n"));
close( pfds[0] );
waitpid((pid_t)pid, &status, 0);
exit(0);
}
}
ref:Bluetooth A2DP
無法啟動 power on
[bluetooth]# power on
Failed to set power on: org.bluez.Error.Blocked
查找原因
$ sudo systemctl status bluetooth.service
● bluetooth.service - Bluetooth service
Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2021-02-22 17:08:08 CST; 1min 55s ago
Docs: man:bluetoothd(8)
Main PID: 4723 (bluetoothd)
Status: "Running"
Tasks: 1 (limit: 4915)
CGroup: /system.slice/bluetooth.service
└─4723 /usr/lib/bluetooth/bluetoothd
二 22 17:08:08 hello-W230ST systemd[1]: Starting Bluetooth service...
二 22 17:08:08 hello-W230ST bluetoothd[4723]: Bluetooth daemon 5.48
二 22 17:08:08 hello-W230ST systemd[1]: Started Bluetooth service.
二 22 17:08:08 hello-W230ST bluetoothd[4723]: Starting SDP server
二 22 17:08:08 hello-W230ST bluetoothd[4723]: Bluetooth management interface 1.14 initialized
二 22 17:08:08 hello-W230ST bluetoothd[4723]: Failed to set mode: Blocked through rfkill (0x12)
二 22 17:08:08 hello-W230ST bluetoothd[4723]: Endpoint registered: sender=:1.91 path=/MediaEndpoint/A2DPSource
二 22 17:08:08 hello-W230ST bluetoothd[4723]: Endpoint registered: sender=:1.91 path=/MediaEndpoint/A2DPSink
二 22 17:09:55 hello-W230ST bluetoothd[4723]: Failed to set mode: Blocked through rfkill (0x12)
$ sudo systemctl restart bluetooth.service <-沒用
$ sudo rfkill list
0: hci0: Bluetooth
Soft blocked: yes <- 被block住了@@?
Hard blocked: no
1: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
解決
$ sudo rfkill unblock bluetooth
$ sudo rfkill list
0: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
1: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
ref:
1. Cannot unblock soft-blocked bluetooth
2020年8月20日 星期四
字串搜尋比較
run.sh
run.py
run.c
#!/bin/bash
str="Aug 20 10:34:45 cs2=home_ubuntu cs2_1234 Aug 20 10:34:45 cs2_1234 cs2=home_ubuntu12345"
ii=0
while true
do
fstr=$(echo $str | awk -F" " '{print $argv0}' argv0=$ii)
if [ -z "$fstr" ];
then
break
fi
if [ ${fstr:0:4} = "cs2=" ];
then
echo $fstr
fi
ii=$((ii+1))
#echo "ii="$ii
done
$ time ./run.sh cs2=home_ubuntu cs2=home_ubuntu12345 real 0m0.033s user 0m0.031s sys 0m0.011sref: how-do-i-use-shell-variables-in-an-awk-script
run.py
#!/bin/python3
import os
def test():
str="Aug 20 10:34:45 cs2=home_ubuntu cs2_1234 Aug 20 10:34:45 cs2_1234 cs2=home_ubuntu12345"
fstr = str.split(" ")
for i in fstr:
if "cs2=" in i:
print(i)
if __name__=='__main__':
test()
$ time python3 ./run.py cs2=home_ubuntu cs2=home_ubuntu12345 real 0m0.027s user 0m0.023s sys 0m0.004s
run.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buf[128]="Aug 20 10:34:45 cs2=home_ubuntu cs2_1234 Aug 20 10:34:45 cs2_1234 cs2=home_ubuntu12345";
char *target="cs2=";
char *tmp;
char *pch, *delim=" ";
pch = strtok(buf,delim);
for(; pch != NULL; )
{
tmp=strstr(pch, target);
if(tmp != NULL)
{
printf("%s\n", tmp);
}
pch = strtok (NULL, delim);
}
return 0;
}
$ time ./run cs2=home_ubuntu cs2=home_ubuntu12345 real 0m0.001s user 0m0.001s sys 0m0.000s
標籤:
C,
Linux Script,
Python
2020年7月8日 星期三
ADC-read battery
kernel有留ioctl來讀資料
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include <signal.h>
//#define DEBUG_ENV
#ifdef DEBUG_ENV
#define fprintfs(fmt,args...) fprintf(stdout, fmt ,##args)
#define fprintfe(fmt,args...) fprintf(stderr, fmt ,##args)
#define DEBUGMSG __FILE__, __LINE__, __FUNCTION__
#else
#define fprintfs(fmt,args...)
#define fprintfe(fmt,args...)
#endif
#define SARADC_IOC_MAGIC 'a'
#define MS_SAR_INIT _IO(SARADC_IOC_MAGIC, 0)
#define MS_SAR_SET_CHANNEL_READ_VALUE _IO(SARADC_IOC_MAGIC, 1)
int STOP_FLAG=0;
typedef struct
{
int channel_value;
int adc_value;
}READ_ADC_t;
int read_saradc (char *argv[], int fd, int *val)
{
READ_ADC_t radc;
//sscanf(argv[1], "%d", &radc.channel_value);
sscanf("3", "%d", &radc.channel_value); //PAD_SAR_GPIO
if (fd < 0)
{
fprintf(stderr, "/dev/saradc");
return 0;
}
if (ioctl(fd, MS_SAR_SET_CHANNEL_READ_VALUE, &radc)< 0)
{
fprintf(stderr, "ioctl failed\n");
return 0;
}
fprintfs("radc_channel=%d\n", radc.channel_value);
fprintfs("radc_adc_value=%d\n", radc.adc_value);
*val=radc.adc_value;
return 1;
}
void sigroutine(int dunno)
{
switch(dunno){
case SIGINT:
fprintfs("ctrl-c signal\n");
STOP_FLAG=1;
break;
case SIGTERM:
fprintfs("terminal signal\n");
STOP_FLAG=1;
break;
case SIGQUIT:
fprintfs("quit signal\n");
STOP_FLAG=1;
break;
default:
fprintfs("Unknow signal\n");
}
}
unsigned char bat_percent(int val)
{
int i=0, j=0;
int bat[16]={644, 628, 616,
600, 583, 570, 552,
530, 522, 500, 492,
476, 461, 0};
for(j=0; j<(int)(sizeof(bat)/sizeof(bat[0])); j++)
{
if (bat[j] == 0)
break;
}
for (i=0; i<j; i++)
{
if (val >= bat[i])
{
break;
}
}
if ( 10-i == -1)
return 5;
if ( 10-i == -2 || 10-i == -3)
return 0;
return (10-i)*10;
}
void min_max(int *val, int *minval)
{
static int min=0;
static int max=0;
if (min == 0 && max == 0)
{
min=*val;
*minval=*val;
max=*val;
}
if (*val < min)
{
min=*val;
*minval=min;
}
if (*val > max)
max=*val;
fprintfs("min=%d, minval=%d, max=%d\n", min, *minval, max);
return;
}
int main(int argc, char *argv[])
{
int adc_val=0, get_min_val=0;
int fd=0;
int i=0, j=0;
unsigned char ret=0;
if(!(fd = open("/dev/saradc", O_RDONLY|O_NONBLOCK)))
return 0;
signal(SIGINT , sigroutine);
signal(SIGQUIT, sigroutine);
for(i=0;i<10 && !STOP_FLAG;i++)
{
read_saradc(argv, fd, &adc_val);
min_max(&adc_val, &get_min_val);
for(j=0; j<10; j++)
usleep(1000*5); //5ms
}
ret=bat_percent(get_min_val);
printf("bat=%d%%\n", ret);
close(fd);
return 1;
}
2020年3月28日 星期六
aplay -L
Copy it form alsa.c
Linux Sound Programming
#include <alsa/asoundlib.h>
static void pcm_list(snd_pcm_stream_t stream)
{
void **hints, **n;
char *name, *descr, *descr1, *io;
const char *filter;
if (snd_device_name_hint(-1, "pcm", &hints) < 0)
return;
n = hints;
filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";
while (*n != NULL) {
name = snd_device_name_get_hint(*n, "NAME");
descr = snd_device_name_get_hint(*n, "DESC");
io = snd_device_name_get_hint(*n, "IOID");
if (io != NULL && strcmp(io, filter) != 0)
goto __end;
printf("%s\n", name);
if ((descr1 = descr) != NULL) {
printf(" ");
while (*descr1) {
if (*descr1 == '\n')
printf("\n ");
else
putchar(*descr1);
descr1++;
}
putchar('\n');
}
__end:
if (name != NULL)
free(name);
if (descr != NULL)
free(descr);
if (io != NULL)
free(io);
n++;
}
snd_device_name_free_hint(hints);
}
void main (void)
{
printf("-------capture-------\n");
pcm_list(SND_PCM_STREAM_CAPTURE);
printf("\n");
printf("\n");
printf("-------playback-------\n");
pcm_list(SND_PCM_STREAM_PLAYBACK);
return;
}
Copy it form alsa.c
ref: Linux Sound Programming
2020年2月15日 星期六
Alsa Audio Capture - RMS
ref : Introduction to Sound Programming with ALSA
Simple Sound Recording
Compile: gcc rec.c -o rec -lasound -lm
ref:
1.通过pcm音频数据计算分贝
2.Some typical Sound Pressure and Sound Pressure Levels
3.db-rms
4.Alsa Audio Capture by c language
Simple Sound Recording
/* This example reads from the default PCM device and writes to standard output for 5 seconds of data. */ /* Use the newer ALSA API */ #define ALSA_PCM_NEW_HW_PARAMS_API #include <alsa/asoundlib.h> #include <math.h> #include <unistd.h> //#define DEVICE "hw:1,0" #define DEVICE "default" / #define CH_2 1 //#define CH_4 1 float rmsValue(signed char arr[], int n) { float square = 0.0; float mean = 0.0, root = 0.0, db= 0.0; int i; // Calculate square. for (i = 0; i < n; i++) { //printf("arr[%d]=%d, pow=%f\n", i, arr[i], pow(arr[i], 2)); square += pow(arr[i], 2); } //printf("n=%d, square=%f\n", n, square); // Calculate Mean. mean = (square / (float)(n)); // Calculate Root. root = sqrt(mean); return root; } //for ARMv7 signed char complement (signed char *a) { if((*a>>7)) { *a=*a&0xEF; *a = ~(*a) + 1; *a = *a * (-1); //for ARMv7 } else { *a=*a & 0xEF; } return *a; } int main() { long loops; int rc; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int val; int dir; snd_pcm_uframes_t frames; signed char *buffer; signed char *channelbuf; int i=0, j=0, k=0, m=0, n=0; #if CH_2 int channels=2; float root[2]={0}, aroot[2]={0}; #endif #if CH_4 int channels=4; float root[4]={0}, aroot[4]={0}; #endif int rate = 16000; signed char tmp=0; /* Open PCM device for recording (capture). */ rc = snd_pcm_open(&handle, DEVICE, SND_PCM_STREAM_CAPTURE, 0); //can use "dsnoop_test", "pulghw", or others to replace "default" if (rc < 0) { fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc)); exit(1); } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle, params); /* Set the desired hardware parameters. */ /* Interleaved mode */ snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* Signed 16-bit little-endian format */ snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(handle, params, channels); val = rate; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); /* Set period size to 32 frames. */ #if CH_2 frames = 32; #endif #if CH_4 frames = 32 * 2; #endif snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); #if 1 /* Write the parameters to the driver */ rc = snd_pcm_hw_params(handle, params); if (rc < 0) { fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc)); exit(1); } /* Use a buffer large enough to hold one period */ snd_pcm_hw_params_get_period_size(params, &frames, &dir); #if CH_2 size = frames * 4; /* 2 bytes/sample, 2 channels */ #endif #if CH_4 size = frames * 4 * 2; /* 2 bytes/sample, 2 channels */ #endif buffer = (signed char *) malloc(sizeof(signed char)*size); /* We want to loop for 5 seconds */ snd_pcm_hw_params_get_period_time(params, &val, &dir); loops = 5000000 / val; printf("loops=%ld, val=%d, frames=%ld, size=%d\n", loops, val, frames, size); channelbuf = (signed char *) malloc(sizeof(signed char)*size); while (loops > 0) { loops--; //memset(buffer, '0', sizeof(signed char)*size); for(m=0; m<size; m++) buffer[m]=0; rc = snd_pcm_readi(handle, buffer, frames); if (rc == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(handle); break; } else if (rc < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(rc)); } else if (rc != (int)frames) { fprintf(stderr, "short read, read %d frames\n", rc); } #if 0 //for recording rc = write(1, buffer, size); if (rc != size) fprintf(stderr, "short write: wrote %d bytes\n", rc); } //while #else for(j=0; j<channels; ++j) { for (i=j, k=0; i <rc ; i += channels, ++k) { memset(channelbuf, '0', sizeof(signed char)*size); for(m=0; m<size; m++) channelbuf[m]=0; tmp=complement(buffer+(i+j)); //for ARMv7 #if 0 printf("k=%3d,tmp=%4d; ",k , tmp); if ( k%channels==0) printf("\n"); #else channelbuf[k]=tmp; //printf("ch=%d, chbuf[%d]=%3d; ", j, k, channelbuf[k]); //if ( k%channels==0) // printf("\n"); #endif } root[j]=rmsValue(channelbuf, k+1); #if 0 printf("root[%d]=%f ",j, root[j]); if ( j%channels==1) printf("\n"); #endif aroot[j] += root[j]; //printf("aroot[%i]=%f\n", j, aroot[j]); } } //while #if 1 for(j=0; j<channels; j++) fprintf(stderr, "aroot[%i]=%f\n", j, aroot[j]); for(j=0; j<channels; j++) { root[j] = 10 * log10(aroot[j]); fprintf(stderr, "root[%i]=%f\n", j, root[j]); } #endif #endif snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); free(channelbuf); #endif return 0; }
Compile: gcc rec.c -o rec -lasound -lm
ref:
1.通过pcm音频数据计算分贝
2.Some typical Sound Pressure and Sound Pressure Levels
3.db-rms
4.Alsa Audio Capture by c language
2019年9月14日 星期六
操作gpio - mmap and gpiohandle_request, gpiochip
gpio.h
gpio.c
main.c
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <sched.h> #include <sys/mman.h> #include <errno.h> #include <linux/ioctl.h> #include <linux/types.h> #define MMIO_SUCCESS 0 #define MMIO_ERROR_DEVMEM -1 #define MMIO_ERROR_MMAP -2 #define PAD_TOP_BK_ADDR (0x00000B00) #define TOP_GPIO_OUT_OFFSET (0x0000006A) #define TOP_GPIO_IN_OFFSET (0x00000019) #define PAD_TOP_BK_ADDR (0x00000B00) #define TOP_GPIO_OUT_OFFSET (0x0000006A) #define TOP_GPIO_IN_OFFSET (0x00000019) #define GPIO_OUT_REG_ADDR (0x1F000000+(PAD_TOP_BK_ADDR<<1)+(TOP_GPIO_OUT_OFFSET<<2)) #define GPIO_IN_REG_ADDR (0x1F000000+(PAD_TOP_BK_ADDR<<1)+(TOP_GPIO_IN_OFFSET <<2)) #define BASE 0x1F001000 #define GPIO_NUM_RANGE_MIN 84 /* Linerequest flags */ #define GPIOHANDLE_REQUEST_INPUT (1UL << 0) #define GPIOHANDLE_REQUEST_OUTPUT (1UL << 1) #define GPIOHANDLE_REQUEST_ACTIVE_LOW (1UL << 2) #define GPIOHANDLE_REQUEST_OPEN_DRAIN (1UL << 3) #define GPIOHANDLE_REQUEST_OPEN_SOURCE (1UL << 4) #define GPIO_GET_CHIPINFO_IOCTL _IOR(0xB4, 0x01, struct gpiochip_info) #define GPIO_GET_LINEINFO_IOCTL _IOWR(0xB4, 0x02, struct gpioline_info) #define GPIO_GET_LINEHANDLE_IOCTL _IOWR(0xB4, 0x03, struct gpiohandle_request) #define GPIO_GET_LINEEVENT_IOCTL _IOWR(0xB4, 0x04, struct gpioevent_request) #define GPIOHANDLES_MAX 64 struct gpiohandle_request { __u32 lineoffsets[GPIOHANDLES_MAX]; __u32 flags; __u8 default_values[GPIOHANDLES_MAX]; char consumer_label[32]; __u32 lines; int fd; }; #ifdef DEBUG_ENV #define fprintff(fmt,args...) fprintf(fmt ,##args) #define DEBINFO __FILE__, __LINE__, __FUNCTION__ #else #define fprintff(fmt,args...) #endif int s500_mmio_init(void); int s500_mmio_set_output(int gpio_number, char *device_name); int s500_mmio_set_input(int gpio_number, char *device_name); void s500_mmio_set_high(int gpio_number); void s500_mmio_set_low(int gpio_number); int s500_mmio_read_input(int gpio_number); void set_max_priority(void); void set_default_priority(void);
gpio.c
#include "gpio.h"
volatile unsigned char *s500_mmio_gpio_out = NULL;
volatile unsigned char *s500_mmio_gpio_in = NULL;
off_t page_base;
off_t page_offset_in, page_offset_out;
int s500_mmio_init(void) {
if (s500_mmio_gpio_in == NULL && s500_mmio_gpio_out == NULL)
{
size_t pagesize = sysconf(_SC_PAGE_SIZE);
int fd = open("/dev/mem", O_RDWR | O_SYNC);
if (fd == -1) {
// Error opening /dev/mem. Probably not running as root.
return MMIO_ERROR_DEVMEM;
}
// Map GPIO memory to location in process space.
page_base = (GPIO_IN_REG_ADDR / pagesize) * pagesize;
page_offset_in = GPIO_IN_REG_ADDR - page_base;
fprintff(stdout, "page_offset_in=0x%X, page_offset_out=0x%x\n", page_offset_in, page_offset_out);
s500_mmio_gpio_in = mmap(NULL, page_offset_in+1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_base);
page_base = (GPIO_OUT_REG_ADDR / pagesize) * pagesize;
page_offset_out = GPIO_OUT_REG_ADDR - page_base;
s500_mmio_gpio_out = mmap(NULL, page_offset_out+1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, page_base);
close(fd);
if (s500_mmio_gpio_in == MAP_FAILED || s500_mmio_gpio_out == MAP_FAILED)
{
// Don't save the result if the memory mapping failed.
s500_mmio_gpio_in = NULL;
s500_mmio_gpio_out = NULL;
return MMIO_ERROR_MMAP;
}
}
return MMIO_SUCCESS;
}
int s500_mmio_set_input(int gpio_number, char *device_name)
{
int fd=0;
int ret=0;
char *chrdev_name;
struct gpiohandle_request req;
ret = asprintf(&chrdev_name, "/dev/%s", device_name);
if (ret < 0)
{
fprintf(stderr, "can't open /dev/%s", device_name);
return -ENOMEM;
}
fd = open(chrdev_name, 0);
if (fd == -1)
{
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
goto exit_close_error;
}
req.lineoffsets[0] = gpio_number;
req.flags = GPIOHANDLE_REQUEST_INPUT;
req.lines = 1;
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1)
{
ret = -errno;
fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",ret);
goto exit_close_error;
}
exit_close_error:
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
free(chrdev_name);
return ret;
}
int s500_mmio_set_output(int gpio_number, char *device_name)
{
int fd=0;
int ret=0;
char *chrdev_name;
struct gpiohandle_request req;
ret = asprintf(&chrdev_name, "/dev/%s", device_name);
if (ret < 0)
{
fprintf(stderr, "can't open /dev/%s", device_name);
return -ENOMEM;
}
fd = open(chrdev_name, 0);
if (fd == -1)
{
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
goto exit_close_error;
}
req.lineoffsets[0] = gpio_number;
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
req.lines = 1;
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret == -1)
{
ret = -errno;
fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",ret);
goto exit_close_error;
}
exit_close_error:
if (close(fd) == -1)
perror("Failed to close GPIO character device file");
free(chrdev_name);
return ret;
}
int s500_mmio_read_input(int gpio_number) {
return (*(s500_mmio_gpio_in+page_offset_in) & (1 << (gpio_number - GPIO_NUM_RANGE_MIN )) ? 1 : 0);
}
void s500_mmio_set_high(int gpio_number)
{
*(s500_mmio_gpio_out+page_offset_out) |= (1 << (gpio_number-GPIO_NUM_RANGE_MIN));
}
void s500_mmio_set_low(int gpio_number)
{
*(s500_mmio_gpio_out+page_offset_out) &= (1 << (gpio_number-GPIO_NUM_RANGE_MIN));
}
void set_max_priority(void) {
struct sched_param sched;
memset(&sched, 0, sizeof(sched));
// Use FIFO scheduler with highest priority for the lowest chance of the kernel context switching.
sched.sched_priority = sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &sched);
}
void set_default_priority(void) {
struct sched_param sched;
memset(&sched, 0, sizeof(sched));
// Go back to default scheduler with default 0 priority.
sched.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &sched);
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "gpio.h"
int main (int argc, char **argv)
{
if (argc < 2)
{
printf("ex: ./main 88");
return;
}
int gpio_num=atoi(argv[1]);
int ret=0;
printf("num=%d\n", gpio_num);
if (s500_mmio_init() < 0)
printf("error open mem!n");
set_max_priority();
ret=s500_mmio_set_input(gpio_num, "gpiochip0");
for(;;)
{
ret=s500_mmio_read_input(gpio_num);
usleep(500*1000);
fprintf(stdout, "\rret=%d", ret);
fflush(stdout);
}
set_default_priority();
}
2018年12月28日 星期五
tinyalsa
- Tiny library
Source code and Download
or
(沒裝過)sudo apt-add-repository ppa:taylorcholberton/tinyalsa sudo apt-get update sudo apt-get install tinyalsa sudo apt-get install libtinyalsa-dev - Sample code - ics-mr1
tinyplay.c
tinycap.c
2018年9月10日 星期一
top 指定 program, cpu loading
script
copy form Here
ref:
1. stackoverflow
top -p `pgrep -d, -f program1`, `pgrep -d, -f program2`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#define DEBUG 0
#define CPU_CORE 2
#define STR_ROW 16
#define STR_LEN 64
#define CSV_FORMAT
typedef struct target
{
char **cpu;
char **name;
}target_t;
int STOP_FLAG;
void sigroutine(int dunno)
{
switch(dunno){
case SIGINT:
printf("ctrl-c signal\n");
STOP_FLAG=1;
break;
case SIGTERM:
printf("terminal signal\n");
STOP_FLAG=1;
break;
case SIGQUIT:
printf("quit signal\n");
STOP_FLAG=1;
break;
default:
printf("Unknow signal\n");
}
}
char **getMem()
{
int i=0, j=0;
char **ptr = (char **)malloc(sizeof(char*) * STR_ROW);
for (i = 0; i <STR_ROW; i++)
ptr[i] = (char *)malloc(sizeof(char *) * STR_LEN);
for (i = 0; i <STR_ROW; i++)
for(j=0; j< STR_LEN; j++)
ptr[i][j]=0;
return ptr;
}
int get_count(const char *cmd)
{
FILE *pp=NULL;
char buf[32];
int count=0;
pp=popen(cmd, "r");
while (fgets(buf, 255, pp) != NULL)
{
//printf("buf=%s", buf);
}
sscanf(buf, "%d", &count);
printf("cound=%d\n", count-1);
pclose(pp);
return count-1;
}
int ttop (const char *cmd, char **val)
{
int i=0,j=0;
FILE *pp=NULL;
char buf[32];
for (i=0; i<STR_ROW; i++)
{
for(j=0; j<STR_LEN; j++)
{
val[i][j]=0;
}
}
i=0;j=0;
pp=popen(cmd, "r");
while (fgets(buf, 255, pp) != NULL)
{
#if DEBUG
printf("buf=%s", buf);
#endif
strncpy(val[i], buf, strlen(buf)-1);
i++;
}
pclose(pp);
return 0;
}
int do_str (target_t *aim, char **top_str)
{
int i=0;
for(i=0; i<STR_ROW; i++)
{
if(top_str[i] == NULL)
break;
sscanf(top_str[i], "%s %s", aim->cpu[i], aim->name[i]);
}
#if DEBUG
for(i=0; i<STR_ROW; i++)
{
if(top_str[i] == NULL)
break;
printf("cpu_loading=%s, name=%s\n", aim->cpu[i], aim->name[i]);
}
#endif
return 0;
}
void analysis (target_t *aim, int count, char *argv[])
{
int i=0, j=0, k=0;
//double *total_cpu=(double *)malloc(sizeof(double)*(count-1));
double cpu[STR_ROW];
double pcpu=0.0; //signal process cpu loading
double tcpu=0.0; //total process cpu loading, ex: (A+B)/cpu_core
for(i=0; i<STR_ROW; i++)
{
if((aim->cpu[i] != NULL) && (aim->name[i] != NULL))
{
cpu[i]=strtod(aim->cpu[i],NULL);
}
}
for(j=1; j<count; j++)
{
#if DEBUG
printf("aim_name[%d]=%s\n", j, argv[j]);
#endif
pcpu=0.0;
for(i=0; i<STR_ROW; i++)
{
if (strcmp(aim->name[i], argv[j]) == 0)
{
pcpu+=cpu[i];
k=i; //for cmd_name
#if DEBUG
printf("k=%d, cpu_loading=%s, cmd_name=%s\n", i, aim->cpu[i], aim->name[i]);
#endif
}
}
tcpu+=pcpu;
#ifdef CSV_FORMAT
if(!strcmp("", aim->name[k]))
printf("didn't find target name\n");
else
printf("%.2lf, %s, ", pcpu, aim->name[k]);
#else
printf("sum_cpu=%.2lf, name=%s ", pcpu, aim->name[k]);
#endif
//total_cpu[j-1]=sum_cpu;
}
#ifdef CSV_FORMAT
if(strcmp("", aim->name[k]))
printf("%.2lf, cpu\n", tcpu/CPU_CORE);
#else
printf("cpu=%.2lf\n", tcpu/CPU_CORE);
#endif
return;
}
void print_useage(void)
{
printf("\nPlease enter the target name:\n");
printf("Btw, 1, The limit is three process names\n");
printf(" 2, the output value takes about 10 seconds\n");
printf("ex: ./get_top process_name process_name\n");
}
int init (int argc, char *argv[])
{
if(argc < 2)
{
print_useage();
return 1;
}
if((strcmp(argv[0], "-h")==0) || (strcmp(argv[0], "--help")==0))
{
print_useage();
return 1;
}
return 0;
}
/*
* "top -n 3 -d 5", the output value takes about 10 seconds
* (d * (n-1))=5*2=10
* -n : Number-of-iterations
* use 2 because: When you first run it, it has no previous sample to compare to, so these initial values are the percentages since boot.
* -d : delay-time
*/
char *ccmd(int argc, char *argv[], const char *opt, int count)
{
int i=0;
char *cmd, *tmp1, *tmp2;
char *str;
cmd =(char *)malloc(sizeof(char)*STR_LEN*2);
tmp1=(char *)malloc(sizeof(char)*STR_LEN*2);
tmp2=(char *)malloc(sizeof(char)*STR_LEN*2);
if(!strcmp("top", opt))
str="top -n 3 -d 5 | grep ";
else
str="ps -ef | grep ";
memset(tmp1, 0, sizeof(char)*STR_LEN*2);
memset(tmp2, 0, sizeof(char)*STR_LEN*2);
strcpy(cmd, str);
int ret=0;
for(i=0; i<argc-1; i++)
{
if( strlen(tmp1) > STR_LEN*2-1)
{
printf("too many target_name\n");
return NULL;
}
ret=snprintf(tmp1, STR_LEN*2-1, "-e \'%s\' ", argv[i+1]);
strcat(tmp2, tmp1);
}
#if DEBUG
printf("%s, tmp1=%s, tmp2=%s\n", __FUNCTION__, tmp1, tmp2);
#endif
if(!strcmp("top", opt))
str="| tail -n %d |";
else
str="| grep -v grep | wc -l";
sprintf(tmp1, str, count);
strcat(cmd, tmp2);
strcat(cmd, tmp1);
if(!strcmp("top", opt))
str=" awk \'{print $10, $13}\'";
else
str="";
strcat(cmd, str);
#if DEBUG
printf("%s, cmd=%s\n", __FUNCTION__, cmd);
#endif
free(tmp1);
free(tmp2);
return cmd;
}
int main(int argc, char *argv[])
{
int i=0;
int count=0;
char **top_str = getMem();
char *cmd;
target_t aim;
if(init(argc, argv))
return 1;
signal(SIGINT , sigroutine);
signal(SIGQUIT, sigroutine);
STOP_FLAG=0;
aim.cpu=getMem();
aim.name=getMem();
cmd=ccmd(argc, argv, "ps", count);
if (cmd == NULL)
return 1;
count=get_count(cmd);
#if 1
if (count > STR_ROW || count < 0)
{
printf("Process more or less, the range is 0~%d\n", STR_LEN);
return 1;
}
cmd=ccmd(argc, argv, "top", count);
while(!STOP_FLAG)
{
ttop(cmd, top_str);
do_str(&aim, top_str);
analysis(&aim, argc, argv);
}
//free
for (i = 0; i <STR_ROW; i++)
{
free(top_str[i]);
free(aim.cpu[i]);
free(aim.name[i]);
}
#endif
free(top_str);
free(aim.cpu);
free(aim.name);
free(cmd);
return 0;
}
copy form Here
ps command (should not use):top command (should use):1. stackoverflow
標籤:
C,
Linux command
訂閱:
文章 (Atom)