ch32v307_camera/pc/qdx_port_win32.c
2026-03-13 22:22:45 +08:00

195 lines
5.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file qdx_port_win32.c
* @brief Windows (WinSock2 + WinAPI) 平台移植层
*
* 目的:将 qdx_port.h 声明的 HAL 接口映射到 Windows API
* 使 QDXnetworkStack 库能够在 PC 端运行。
*
* 注意:本文件仅用于 PC 端 Demo 模拟,不适用于 MCU 移植。
*/
#include "qdx_port.h"
#include <process.h> /* _beginthreadex */
#include <stddef.h>
#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
/* ============================================================
* 时间与延迟
* ============================================================ */
/* 获取系统启动以来的毫秒数 */
uint32_t qdx_port_get_tick_ms(void) { return (uint32_t)GetTickCount(); }
/* 阻塞延迟指定毫秒 */
void qdx_port_delay_ms(uint32_t ms) { Sleep(ms); }
/* ============================================================
* TCP 网络操作 (基于 WinSock2)
* ============================================================ */
/**
* @brief 创建 TCP 套接字并连接到远端
*
* 连接成功后设置 500ms 接收超时,防止接收线程永久阻塞。
*/
qdx_socket_t qdx_port_tcp_connect(const char *ip, uint16_t port) {
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
return NULL;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(ip);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR) {
closesocket(sock);
return NULL;
}
/* 设置接收超时 500ms使 recv 线程可定期检查连接状态 */
DWORD timeout_ms = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout_ms,
sizeof(timeout_ms));
printf("[Port] TCP 已连接: %s:%d\n", ip, port);
/* 将 SOCKET 转为不透明指针SOCKET 本身是 unsigned int 类型) */
return (qdx_socket_t)(intptr_t)sock;
}
/* 关闭 TCP 套接字 */
void qdx_port_tcp_close(qdx_socket_t sock) {
if (sock) {
closesocket((SOCKET)(intptr_t)sock);
}
}
/* TCP 发送 */
int32_t qdx_port_tcp_send(qdx_socket_t sock, const uint8_t *data,
uint32_t len) {
if (!sock)
return -1;
int ret = send((SOCKET)(intptr_t)sock, (const char *)data, (int)len, 0);
if (ret == SOCKET_ERROR) {
return -1;
}
return (int32_t)ret;
}
/**
* @brief TCP 接收(非阻塞/短超时)
*
* 返回值约定:
* > 0 : 实际收到的字节数
* = 0 : 超时无数据
* < 0 : 连接断开或错误
*/
int32_t qdx_port_tcp_recv(qdx_socket_t sock, uint8_t *buf, uint32_t max_len) {
if (!sock)
return -1;
int ret = recv((SOCKET)(intptr_t)sock, (char *)buf, (int)max_len, 0);
if (ret == SOCKET_ERROR) {
int err = WSAGetLastError();
/* WSAETIMEDOUT / WSAEWOULDBLOCK 表示超时,视为无数据可读 */
if (err == WSAETIMEDOUT || err == WSAEWOULDBLOCK) {
return 0;
}
return -1; /* 真实错误 */
}
if (ret == 0) {
return -1; /* 服务端主动关闭连接 */
}
return (int32_t)ret;
}
/* ============================================================
* 互斥锁 (基于 CRITICAL_SECTION)
* ============================================================ */
/* 创建互斥锁 */
qdx_mutex_t qdx_port_mutex_create(void) {
CRITICAL_SECTION *cs = (CRITICAL_SECTION *)malloc(sizeof(CRITICAL_SECTION));
if (!cs)
return NULL;
InitializeCriticalSection(cs);
return (qdx_mutex_t)cs;
}
/* 加锁 */
void qdx_port_mutex_lock(qdx_mutex_t mutex) {
if (mutex) {
EnterCriticalSection((CRITICAL_SECTION *)mutex);
}
}
/* 解锁 */
void qdx_port_mutex_unlock(qdx_mutex_t mutex) {
if (mutex) {
LeaveCriticalSection((CRITICAL_SECTION *)mutex);
}
}
/* 销毁互斥锁 */
void qdx_port_mutex_delete(qdx_mutex_t mutex) {
if (mutex) {
DeleteCriticalSection((CRITICAL_SECTION *)mutex);
free(mutex);
}
}
/* ============================================================
* 线程 (基于 _beginthreadex)
* ============================================================ */
/**
* @brief 线程启动包装器
*
* 目的_beginthreadex 要求 unsigned __stdcall 签名,
* 而 qdx_thread_entry_t 是 void(*)(void*)
* 需要通过此包装器做签名适配。
*/
typedef struct {
qdx_thread_entry_t entry;
void *arg;
} ThreadWrapper_t;
static unsigned __stdcall thread_wrapper(void *param) {
ThreadWrapper_t *tw = (ThreadWrapper_t *)param;
qdx_thread_entry_t entry = tw->entry;
void *arg = tw->arg;
free(tw); /* 释放包装结构,生命周期结束 */
entry(arg);
return 0;
}
/* 创建后台线程 */
int8_t qdx_port_thread_create(const char *name, qdx_thread_entry_t entry,
void *arg, uint32_t stack_size,
uint8_t priority) {
(void)name; /* Windows 线程不直接支持命名 */
(void)priority; /* 简化 Demo 不设线程优先级 */
ThreadWrapper_t *tw = (ThreadWrapper_t *)malloc(sizeof(ThreadWrapper_t));
if (!tw)
return -1;
tw->entry = entry;
tw->arg = arg;
HANDLE h =
(HANDLE)_beginthreadex(NULL, stack_size, thread_wrapper, tw, 0, NULL);
if (h == NULL) {
free(tw);
return -1;
}
/* 分离线程句柄,后台自动运行 */
CloseHandle(h);
return 0;
}