赤外線通信において、接続相手の情報などは、accept時などにSOCKADDR_IRDA形式で格納される。
SOCKADDR_IRDA (af_irda.h) - Win32 apps | Microsoft Docs
ここから本格的に赤外線通信をしていくが、まずは準備など。
この日のために、数年前から中古で買っておいたSTOLA。
ようやく今日、日の目を見る。
そしてSigmatelのIrDAドングル。
最後の1本。
もうおそらく製造も販売もしていない。
壊れやすいので、これが壊れたら終わり。
ひたすらアドレス帳に登録していく。
もちろん架空の情報を。
Windows 10 で赤外線ポート(Irda)を使う方法
当初はここを参考にWindows10で準備。
この時点で赤外線はない。
コマンドプロンプトの管理者実行。
Microsoft Windows [Version 10.0.18363.900]
(c) 2019 Microsoft Corporation. All rights reserved.
C:\WINDOWS\system32>netcfg -u ms_irdanetcfg -c p -I ms_irda
ms_irdanetcfg をアンインストールしようとしています ...
... ms_irdanetcfg はインストールされていません。
... 完了しました。
ms_irda をインストールしようとしています ...
... 失敗しました。エラー コード: 0x80070002。
C:\WINDOWS\system32>
なぜか失敗。
Windows 10 で赤外線ポート(Irda)を使う方法
PowerShellでやり直す。
PS C:\WINDOWS\system32> get-WindowsCapability -online -Name "Network.Irda~~~~0.0.1.0"
Name : Network.Irda~~~~0.0.1.0
State : NotPresent
DisplayName : IrDA 赤外線
Description : IrDA デバイスのサポート。特別な IrDA ハードウェアが必要です。
DownloadSize : 604101
InstallSize : 1236233
PS C:\WINDOWS\system32>
して、
PS C:\WINDOWS\system32> Remove-WindowsCapability -online -Name "Network.Irda~~~~0.0.1.0"
Path :
Online : True
RestartNeeded : False
PS C:\WINDOWS\system32>
して、
PS C:\WINDOWS\system32> add-WindowsCapability -online -Name "Network.Irda~~~~0.0.1.0"
Path :
Online : True
RestartNeeded : False
PS C:\WINDOWS\system32>
これはかかった。
そして、
PS C:\WINDOWS\system32> get-WindowsCapability -online -Name "Network.Irda~~~~0.0.1.0"
Name : Network.Irda~~~~0.0.1.0
State : Installed
DisplayName : IrDA 赤外線
Description : IrDA デバイスのサポート。特別な IrDA ハードウェアが必要です。
DownloadSize : 604101
InstallSize : 1236233
PS C:\WINDOWS\system32>
これで使えるのでは。
赤外線が出現。
クリックして設定。
保存先を変更。
ドングルを接続していない時はこうなる。
接続しているとこうなる。
設定の変更とかよくやるけど効果なし。
(9660にすると受信しやすいとか昔あったけどなあ。)
STOLAから1件のアドレス送信をずっと試してたけど、どうも現在のWindows10だと反応もしない。
Windows7だと反応した。
ドライバかな・・・。
(Windows7は以前からドライバのインストールとか既に準備済みだった模様。
Windows10の初期のドライバを入れていても、Windows10の最近のバージョンで動くかは不明だし。)
STOLAで赤外線受信にするとPCから送信するための画面も出る。
(この時irftpが出るのかな。)
というわけでなんとか標準の赤外線通信はできそう。
ただし、全件送信時の認証には対応してなかった気がするので1つずつだけ。
さて、これをどうやってプログラムで実現するか。
#include <tchar.h>
#include <winsock2.h>
#include <windows.h>
#include <af_irda.h>
int _tmain(int argc, TCHAR *argv[]){
WSADATA wsaData;
int iRet;
int soc;
int iBind;
SOCKADDR_IRDA soc_addr = {AF_IRDA, 0, 0, 0, 0, "OBEX"};
iRet = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iRet == 0){
_tprintf(_T("WSAStartup success!\n"));
soc = socket(AF_IRDA, SOCK_STREAM, 0);
if (soc != INVALID_SOCKET){
_tprintf(_T("soc = %d\n"), soc);
iBind = bind(soc, (const struct sockaddr *)&soc_addr, sizeof(SOCKADDR_IRDA));
if (iBind != SOCKET_ERROR){
_tprintf(_T("bind success!\n"));
}
else{
_tprintf(_T("bind failed!\n"));
}
closesocket(soc);
}
WSACleanup();
}
return 0;
}
SOCKADDR_IRDAのsoc_addrを上記のように初期化し、バインドしてみる。
WSAStartup success!
soc = 128
bind failed!
続行するには何かキーを押してください . . .
失敗する。
標準の"Irmon"が邪魔しているからだ。
Irmonを停止させる。
停止状態。
こうすると、
WSAStartup success!
soc = 128
bind success!
続行するには何かキーを押してください . . .
バインド成功。
(なのでサービス停止とかを扱ったが、プログラムでやる必要もなくなった。
また、PCが送信側の場合はirftpプロセスが邪魔になった記憶があった気がしたので、
プロセス制御も扱ったが、この先で使うことはなかったので、勘違いだったかもしれない。)
ひとまずこの部分をクリアしたので、
soc = socket(AF_IRDA, SOCK_STREAM, 0);
if (soc != INVALID_SOCKET){
_tprintf(_T("soc = %d\n"), soc);
iBind = bind(soc, (const struct sockaddr *)&soc_addr, sizeof(SOCKADDR_IRDA));
if (iBind != SOCKET_ERROR){
_tprintf(_T("bind success!\n"));
iListen = listen(soc, 1);
if (iListen != SOCKET_ERROR){
_tprintf(_T("listen success!\n"));
acc = accept(soc, (struct sockaddr *)&acc_addr, &acc_addr_len);
if (soc != INVALID_SOCKET){
_tprintf(_T("acc = %d\n"), acc);
_tprintf(_T("acc_addr.irdaAddressFamily = %hu\n"), acc_addr.irdaAddressFamily);
_tprintf(_T("acc_addr.irdaDeviceID = %02X %02X %02X %02X\n"), acc_addr.irdaDeviceID[3], acc_addr.irdaDeviceID[2], acc_addr.irdaDeviceID[1], acc_addr.irdaDeviceID[0]);
iServerNameLen = MultiByteToWideChar(CP_ACP, 0, acc_addr.irdaServiceName, -1, NULL, 0);
MultiByteToWideChar(CP_ACP, 0, acc_addr.irdaServiceName, -1, tszServerName, iServerNameLen);
_tprintf(_T("acc_addr.irdaServiceName = %s\n"), tszServerName);
closesocket(acc);
}
}
else{
_tprintf(_T("listen failed!\n"));
}
}
else{
_tprintf(_T("bind failed!\n"));
}
closesocket(soc);
}
接続先情報を出力する。
C# + .NET Frameworkで赤外線通信をする時は、32feet.NETを使うだろう。
CodePlex Archive
これのIrDA Clientのサンプルをビルドして起動すると、
16進数8桁のDeviceIDが出ると思う。
これと同じものが、上のコンソールプログラムでも、
WSAStartup success!
soc = 128
bind success!
listen success!
acc = 132
acc_addr.irdaAddressFamily = 26
acc_addr.irdaDeviceID = CB 42 06 90
acc_addr.irdaServiceName = LSAP-SEL2
続行するには何かキーを押してください . . .
出る。
残念ながらSTOLAは毎回DeviceIDが変更される仕組みになっている模様。
DeviceIDは固定の端末もある。
(1度だけスクショと同じIDが出た時があったのだが、スクショし忘れる失態・・・。)
さて、ここまで来たら、あとは赤外線通信をするだけだ。
https://www.ttc.or.jp/application/files/5015/5417/2604/JF-IR007.10v2.pdf
ここに赤外線通信仕様がある。
(以前のURLリンクから変わった模様。)
PDFにおける66ページ目に例があるので、それを参考にするといい。
最低限、1件のアドレスを受信できるプログラムを作った。
(いろいろ実装すると大変なのであくまで最低限。)
結果はこんな感じ。
鈴木一郎.vcfが保存されてる。
こんな感じのvCardが送られてくる。
いやはや、WinSockでこれをやるのは大変。
32feet.NETもたいして変わらないけど、これよりはマシ。
Sample/winapi/SOCKADDR_IRDA/SOCKADDR_IRDA/src/SOCKADDR_IRDA at master · bg1bgst333/Sample · GitHub