/*
* Src/wol.c
* https://wiki.wireshark.org/WakeOnLAN
*
* Packet Format
* |Synchronization Stream |Target MAC |Password (optional) |
* |6 |96 |0, 4 or 6 |
*
* The Synchronization Stream is defined as 6 bytes of FFh.
*
* The Target MAC block contains 16 duplications of the IEEE address
* of the target, with no breaks or interruptions.
*
* The Password field is optional, but if present, contains either 4
* bytes or 6 bytes. The WakeOnLAN dissector was implemented to dissect
* the password, if present, according to the command-line format that
* ether-wake uses, therefore, if a 4-byte password is present, it will
* be dissected as an IPv4 address and if a 6-byte password is present,
* it will be dissected as an Ethernet address.
*/
#include <stdint.h>
#include <string.h>
#include "stm32f7xx_hal.h"
#include "lwip.h"
#include "lwip/udp.h"
#include "wol.h"
void Error_Handler(void);
// 被唤醒机器的MAC地址
static const uint8_t targetAddress[ETHARP_HWADDR_LEN] =
{ 0x28, 0xd2, 0x44, 0x3e, 0x07, 0x56 };
static void fillMagicPacket(uint8_t buf[])
{
int i;
memset(&buf[0], 0xff, ETHARP_HWADDR_LEN);
for (i = 0; i < 16; i++)
{
memcpy(&buf[(1 + i) * ETHARP_HWADDR_LEN], &targetAddress[0],
ETHARP_HWADDR_LEN);
}
}
static void sendMagicPacket(void)
{
static struct udp_pcb *pcb = NULL;
struct pbuf *pbuf = NULL;
err_t err;
if (pcb == NULL)
{
pcb = udp_new();
if (pcb == NULL)
{
Error_Handler();
}
err = udp_connect(pcb, IP_ADDR_BROADCAST, 9);
if (err != ERR_OK)
{
Error_Handler();
}
}
pbuf = pbuf_alloc(PBUF_TRANSPORT, (1 + 16) * ETHARP_HWADDR_LEN,
PBUF_RAM);
if (pbuf == NULL)
{
Error_Handler();
}
fillMagicPacket(pbuf->payload);
err = udp_send(pcb, pbuf);
if (err != ERR_OK)
{
Error_Handler();
}
pbuf_free(pbuf);
pbuf = NULL;
#if 0 // 不要释放pcb,后面还要用
udp_remove(pcb);
pcb = NULL;
#endif
}
void WOL_Process(void)
{
static int fired = 0;
uint32_t tick;
tick = HAL_GetTick();
if(fired == 0 && tick >= 2000) // 上电2秒后发送Magic Packet
{
sendMagicPacket();
HAL_GPIO_WritePin(GPIOB, LED_RED_Pin, GPIO_PIN_SET);
fired = 1;
}
}
void BTN_Process(void)
{
static uint32_t tick_prev = 0;
static uint32_t btn_state = 0;
uint32_t tick;
tick = HAL_GetTick();
if(tick != tick_prev)
{
tick_prev = tick;
btn_state <<= 1;
if(HAL_GPIO_ReadPin(BTN_USER_GPIO_Port, BTN_USER_Pin))
{
btn_state |= 1;
HAL_GPIO_WritePin(GPIOB, LED_BLUE_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, LED_RED_Pin, GPIO_PIN_RESET);
}
else
{
btn_state |= 0;
HAL_GPIO_WritePin(GPIOB, LED_BLUE_Pin, GPIO_PIN_RESET);
}
if(btn_state == 0xffff0000) // 按钮释放立即发送Magic Packet
{
sendMagicPacket();
HAL_GPIO_WritePin(GPIOB, LED_RED_Pin, GPIO_PIN_SET);
}
}
}
void LED_Process(void)
{
if(HAL_GetTick() & 0x100)
{
HAL_GPIO_WritePin(GPIOB, LED_GREEN_Pin, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOB, LED_GREEN_Pin, GPIO_PIN_RESET);
}
}