はじめに
今回は、WIZnetの「W6300-EVB-Pico」を使って、ネットワーク経由でPCを遠隔起動するWake-on-LAN(WoL)を実装してみます。
W6300-EVB-Picoは、RP2040マイコンとWIZnet製Ethernetコントローラ「W6300」を搭載した開発ボードです。Raspberry Pi Picoと同じ感覚で扱えるため、手軽に有線LAN通信を試すことができます。
Wake-on-LANとは?
Wake-on-LAN(WoL)は、ネットワーク経由でPCの電源を入れる仕組みです。
通常、PCの電源を切るとCPUやOSは動作を停止します。しかし、Wake-on-LAN(WoL)が有効になっている場合は、LANコントローラの一部が待機状態のまま動作を続けています。そして、ネットワーク上から送信された特定のパケットを受信すると、自分宛ての起動要求であることを認識し、マザーボードに電源投入を指示します。
この特殊なパケットがMagic Packet(マジックパケット)です。
Magic Packetの構造
マジックパケットのフォーマットは以下のようになっています。
FF FF FF FF FF FF
MACアドレス × 16回
先頭に6バイトの0xFFを配置し、その後ろに起動対象PCのMACアドレスを16回連続して並べます。
例えば、対象PCのMACアドレスが
12:34:56:78:9A:BC
の場合、Magic Packetは次のようになります。
FF FF FF FF FF FF
12 34 56 78 9A BC
12 34 56 78 9A BC
12 34 56 78 9A BC
...
(16回)
パケットサイズは、6 + (6 × 16) = 102 byteとなります。
必要な環境
今回使用したものは以下の通りです。
- W6300-EVB-Pico
- WoL対応PC
今回はPC側のWoL設定が完了している前提で進めます。
私の環境では、以下の構成を使用しました。
- ASRock DeskMini A300
- Ubuntu Server 24.04
W6300-EVB-Picoのプログラム
ヘッダのインクルード
まずは必要なヘッダファイルをインクルードします。
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "wizchip_conf.h"
#include "wizchip_spi.h"
#include "socket.h"
ネットワーク設定
今回は固定IPアドレスを使用します。
IPアドレスやゲートウェイなどは、ご自身のネットワーク環境に合わせて変更してください。
static wiz_NetInfo g_net_info =
{
.mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56}, // MAC address
.ip = {192, 168, 0, 30}, // IP address
.sn = {255, 255, 255, 0}, // Subnet Mask
.gw = {192, 168, 0, 1}, // Gateway
.dns = {8, 8, 8, 8}, // DNS server
.dhcp = NETINFO_STATIC
};
ブロードキャストアドレスの設定
Magic Packetは通常、ブロードキャストで送信します。
例えば、
192.168.0.xxx
のネットワークなら、
192.168.0.255
がブロードキャストアドレスになります。
uint8_t dest_ip[4] =
{
192, 168, 0, 255
};
起動対象PCのMACアドレス
起動したいPCのMACアドレスを設定します。
uint8_t pc_mac[6] =
{
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC
};
マジックパケット生成
102バイトのマジックパケットを生成する関数を作成します。
void make_magic_packet(uint8_t* buf, uint8_t mac[6])
{
// 先頭6byteをFF
for(int i=0;i<6;i++)
{
buf[i]=0xFF;
}
// MACを16回コピー
for(int i=0;i<16;i++)
{
memcpy(buf + 6 + i*6, mac, 6);
}
}
W6300の初期化
RP2040とW6300を初期化します。
stdio_init_all();
sleep_ms(3000);
wizchip_spi_initialize();
wizchip_cris_initialize();
wizchip_reset();
wizchip_initialize();
wizchip_check();
network_initialize(g_net_info);
UDPソケット作成
Wake-on-LANではUDPを利用します。
#define WOL_SOCKET 0
#define WOL_PORT 9
UDPソケットを開きます。
socket(WOL_SOCKET, Sn_MR_UDP, WOL_PORT, 0);
マジックパケットの送信
生成したマジックパケットをブロードキャストアドレスへ送信します。
uint8_t packet[102];
make_magic_packet(
packet,
pc_mac
);
sendto(
WOL_SOCKET,
packet,
sizeof(packet),
dest_ip,
WOL_PORT
);
これで対象PCへマジックパケットが送信されます。
完成したコード
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "wizchip_conf.h"
#include "wizchip_spi.h"
#include "socket.h"
#define WOL_SOCKET 0
#define WOL_PORT 9
// W6300-EVB-Pico本体のネットワーク設定
static wiz_NetInfo g_net_info =
{
.mac = {0x00, 0x08, 0xDC, 0x12, 0x34, 0x56}, // MAC address
.ip = {192, 168, 0, 30}, // IP address
.sn = {255, 255, 255, 0}, // Subnet Mask
.gw = {192, 168, 0, 1}, // Gateway
.dns = {8, 8, 8, 8}, // DNS server
.dhcp = NETINFO_STATIC
};
// 起動したいPCのMACアドレス
uint8_t pc_mac[6]=
{
0xA8, 0xA1, 0x59, 0x25, 0xF4, 0x08
};
// ブロードキャスト
uint8_t dest_ip[4]=
{
192, 168, 0, 255
};
// マジックパケット生成関数
void make_magic_packet(uint8_t* buf)
{
for(int i=0;i<6;i++) {
buf[i]=0xff;
}
for(int i=0;i<16;i++)
{
memcpy(buf+6+i*6, pc_mac, 6);
}
}
// メイン関数
int main()
{
// 初期化処理
stdio_init_all();
sleep_ms(3000);
wizchip_spi_initialize();
wizchip_cris_initialize();
wizchip_reset();
wizchip_initialize();
wizchip_check();
network_initialize(g_net_info);
// マジックパケット作成
uint8_t packet[102];
make_magic_packet(packet);
// UDPソケット作成
socket(
WOL_SOCKET,
Sn_MR_UDP,
9,
0
);
// マジックパケット送信
sendto(
WOL_SOCKET,
packet,
sizeof(packet),
dest_ip,
9
);
}
動作確認
プログラムを実行し、対象のPCが起動すれば成功です。
Wiresharkを使用して、実際にマジックパケットが送信されているかも確認してみました。
キャプチャ結果を見ると、W6300-EVB-Picoから対象PCのMACアドレスを含むMagic Packetが正しく送信されていることが確認できます。
おわりに
マジックパケットは非常にシンプルな構造のため、WoLの実装自体はそれほど難しくありません。W6300-EVB-Picoでも、UDPソケットを作成して102バイトのMagic Packetを送信するだけで、PCをネットワーク経由で起動できます。
リモートサーバーの起動や自宅PCの遠隔操作など、さまざまな用途に活用できるので、ぜひ試してみてください。

