0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CASIOの古いネームランドを、AIとUSB解析で復活させた話

0
Last updated at Posted at 2026-08-06

KL-M20をOrange Pi Zero接続のWebラベルプリンターにする

image.png

PXL_20260806_024642057.jpg

この記事は非公式の記録です
CASIO NAME LAND KL-M20を対象に、実機で確認した非公式の解析・実装記録です。
未確認の機種へ、いきなり印刷・送り・カット命令を送らないでください。

はじめに

CASIOのラベルプリンター「ネームランド KL-M20」。

かなり古い機種です。

けれど、ラベルプリンターとしての機械部分は今も元気です。テープも手に入ります。本体だけで文字を打って印刷することもできます。

ただ、いま使うと少しつらい。

  • キーボードの反応
  • 日本語変換
  • QRコードの作成
  • 文字サイズや余白の調整
  • 複数のラベルを同じレイアウトで再印刷する作業
  • ファイル背表紙用の縦レイアウト

こうした操作は、現在のPCやスマートフォンに慣れた感覚からすると、どうしても煩雑です。

そして本体にはUSB端子があります。

せっかくUSBでつながるのに、現代のブラウザーから自由にラベルを作れないのは、あまりにもったいない。

そこでAIと相談しながらUSB通信を調べ、KL-M20をLAN内のWebラベルプリンターとして復活させました。

サーバー役は、使っていなかったOrange Pi Zeroです。

これは、新しい機械を買って古い機械を捨てる話ではありません。

まだ働ける機械に、いまの時代の操作系を与えて、もう一度仕事へ戻ってもらう話です。


できたもの

KL-M20をOrange Pi ZeroへUSB接続し、同じLAN内のブラウザーから操作します。

現在のWeb UIでは、次の機能を使えます。

  • 印刷文字列の入力
  • QRコード生成
  • 横向き印刷
  • ファイル背表紙向け縦レイアウト
  • 書体選択
  • 行ごとの文字サイズ指定
  • テープ幅に合わせた文字サイズ自動調整
  • ラベル長の自動計算
  • 先頭・後端余白の指定
  • QRコードの左右配置
  • 複数枚印刷
  • ラベル間ハーフカット
  • 最終フルカット
  • 1枚ずつ切り離す印刷
  • カットなし印刷
  • 「タテ・ヨコ 1枚ずつ印刷」
  • プリセット保存・読込
  • JSON形式での書き出し・読み込み
  • PC・スマートフォン対応画面
  • 電源投入後のWeb UI自動起動
  • 6 / 9 / 12 / 18 / 24mmテープの自動判定
  • テープ実幅と実際の印字位置を反映したプレビュー

image.png
image.png

最終的には、6mmから24mmまで、横印刷・背表紙印刷とも実機を見ながら数dot単位で位置を調整しました。

特に18mm、24mmでは、単純に「128dotの中央へ描けば終わり」とはならず、文字とQRコードをそれぞれ実物の印刷結果に合わせて追い込んでいます。


今回追加した機能

初版のあと、実際に日常で使いながらいくつか改修しました。

1. 6 / 9 / 12 / 18 / 24mmを実機校正

テープ幅ごとに、

  • 描画高さ
  • 転送高さ
  • 転送位置
  • QRコードのサイズ
  • QRコードの位置
  • 文字の位置

を実印刷で確認しました。

単に「印刷できた」だけではなく、テープの上下左右で文字やQRが切れないところまで調整しています。

2. 背表紙印刷を別に校正

ファイル背表紙用の縦レイアウトでは、横印刷とは別に、

  • 文字サイズ
  • 左右センタリング
  • QRコードサイズ
  • QRコード位置
  • 不要なテープ余長

を調整しました。

最初は安全のため短いラスターを30mmまで延長していましたが、背表紙ではこれが「妙に長い余白」の原因になりました。

現在は、背表紙について意図的な最低余長を持たせず、内容から必要な長さを計算します。

3. プレビューを「ラスター画像」から「実テープの見た目」へ変更

当初のプレビューは、プリンターへ送る描画キャンバスをほぼそのままPNGにしていました。

しかし、それでは24mmテープでも128dotの画像だけが表示されるため、

「実際の24mmテープのどこへ印刷されるのか」

が分かりません。

現在は、

  • 公称テープ幅
  • 描画領域
  • 転送オフセット
  • 実機校正済みの位置

を反映して、実際にテープを手に持ったときの見え方に近いプレビューを作っています。

印刷前に余白やセンタリングをかなり正確に確認できるようになりました。

4. 「タテ・ヨコ 1枚ずつ印刷」

同じ内容を、

ヨコ1枚
  ↓
ハーフカット
  ↓
タテ1枚
  ↓
フルカット

の順で一度に印刷できるボタンを追加しました。

ファイル整理では、

  • ファイル表面用の横ラベル
  • 背表紙用の縦ラベル

をセットで作ることが多いため、かなり便利です。

この処理では、異なる二つのラスター画像を同じUSB印刷セッション内でKL-M20へ送っています。


なぜ公式ソフトを使わなかったのか

CASIOのサポートページには、KL-M20用ソフトウェアとドライバーのダウンロードページが残っています。

しかしKL-M20は古い機種で、今後も現在のPC環境で長く使える保証はありません。

それなら、

  • 家中のスマートフォンやPCから使う
  • QRコードや自動レイアウトを自由に扱う
  • 古い本体を今後も使い続けられる形にする

という方向へ振ることにしました。

そこでUSB通信を直接扱う、小さなLinuxサーバーを作っています。


構成

スマートフォン / PC
        │
        │ HTTP(家庭内LAN)
        ▼
Orange Pi Zero
  ├─ Debian系Linux
  ├─ Flask / Waitress
  ├─ Pillow / qrcode
  ├─ C + libusb-1.0
  └─ systemd自動起動
        │
        │ USB
        ▼
CASIO NAME LAND KL-M20

実機検証環境

Host:
  Orange Pi Zero
  ARM 32-bit(armhf)
  systemd
  Debian系Linux
  Python 3
  Flask / Waitress
  Pillow
  qrcode
  libusb-1.0

Printer:
  CASIO NAME LAND KL-M20
  USB VID:PID = 07cf:4109

Verified tape widths:
  6mm
  9mm
  12mm
  18mm
  24mm

AIだけで簡単にできたのか

ソフトウェアを書く部分は、AIによってかなり進めやすくなりました。

Web UI、画像レンダリング、USB制御プログラム、systemd設定、バックアップ付き更新スクリプトなどは、AIとの対話で組み上げています。

しかし、AIだけでは分からないこともあります。

  • テープ幅ごとの識別値
  • 正しいラベル設定値
  • 1列あたり何byteを送るのか
  • 実際に印字されるdot位置
  • QRコードが何dotまでなら切れないか
  • カットや送りの順序
  • 正常に見えるか
  • 数dotの上下左右ずれ

これらは実機が答えを持っています。

実際にテープを交換し、試験パターンを印刷し、一つずつ確かめました。

特に6mmテープは手強い相手でした。

最初は64dot転送だと思いました。文字を印刷すると上下に分裂しました。

次に32dot転送を試すと、列データが混ざりました。

64dot枠の中央32dotでも直りませんでした。

最終的には、16byteずつの128dot転送枠を使い、その中の48dotだけへ描画する構造だと分かりました。

6mmテープ:
  転送高さ 128dot
  描画高さ 48dot
  描画開始 y=42

18mm、24mmでも似たことが起きました。

理論上は128dotキャンバスをそのまま使えます。

ところが実物を見ると、文字やQRコードが数dotずれている。

そこで、

2dot下へ
4dot右へ
QRだけ少し縮小

という世界まで実機を見ながら追い込みました。

AIは仮説を作るのが得意です。

人間は現物を見て、

「でも本当にそう?」

と確かめられます。

この組み合わせは、古いハードウェア解析とかなり相性が良いと感じました。


実機で確認したUSB情報

以下はKL-M20でのみ確認した値です。

USB Vendor ID : 0x07cf
USB Product ID: 0x4109

Interface     : 0
Bulk OUT      : 0x01
Bulk IN       : 0x82

OUT max packet: 64 bytes
IN max packet : 8 bytes
ACK           : 0x06

通常コマンド

通常コマンドは16byte固定です。

byte 0    0x02
byte 1    opcode
byte 2    payload length
byte 3    0x00
byte 4... payload
残り      0x00

Python風に書くと、次の形です。

def command16(opcode: int, payload: bytes = b"") -> bytes:
    if len(payload) > 12:
        raise ValueError("payload too long")

    packet = bytearray(16)
    packet[0] = 0x02
    packet[1] = opcode
    packet[2] = len(payload)
    packet[4:4 + len(payload)] = payload
    return bytes(packet)

テープ幅の取得

テープ情報取得には、次のコマンドを使います。

PROBE

opcode : 0x1d
payload: なし

GET_TAPE_SIZE

opcode : 0x1a
payload: なし

応答のbyte 4がテープ幅シグネチャでした。

実測したテープ設定

現在のWeb実装では、次の値を使用しています。

テープ幅 signature SET_LABEL_SIZE payload width mode 描画高さ 転送高さ 実装上の転送Y offset
6mm 0x81 0x81 0x02 0x02 48dot 128dot 42
9mm 0x85 0x85 0x00 0x01 64dot 64dot 0
12mm 0x83 0x83 0x01 0x00 96dot 128dot 18
18mm 0x87 0x87 0x03 0x00 128dot 128dot 4
24mm 0x86 0x86 0x04 0x00 128dot 128dot 8

ここでいうY offsetは、現在のWeb実装で実印刷位置を合わせるために使用している値です。

初期解析時の理論中央値とは異なり、最終的には実際の印字結果を見て調整しています。

注意点です。

  • 6mmは48dot画像を128dot転送領域へ配置します。
  • 9mmだけは64dot転送です。
  • 12mmは96dot画像を128dot転送領域へ配置します。
  • 18mm、24mmも転送領域は128dotです。
  • 24mmテープでも印字ヘッドの有効範囲そのものが24mmになるわけではありません。
  • KL-M20は、不適切と思われる設定値にもACKを返しました。
  • ACKが返ることだけでは、設定値が正しい証拠になりません。

200dpi・128dotなら、理論上のヘッド幅は約16.26mmです。

つまり24mmテープでは、テープ全面24mmへ印字するのではなく、

24mmテープ
┌────────────────────┐
│    約16.3mm印字領域    │
└────────────────────┘

のような関係になります。

24mmには、

  • 広い余白
  • 貼りやすさ
  • 見出しとしての存在感

という価値があります。


横印刷の実機校正

横印刷では、6 / 9 / 12 / 18 / 24mmをそれぞれ実際に印刷し、

  • 上余白
  • 下余白
  • 文字位置
  • QRコード位置
  • QRコードの切れ

を確認しました。

12mm、18mm、24mmでは、当初入れていた描画側のcross_marginを外し、利用可能な印字高さをできるだけ使うようにしています。

18mm、24mmでは文字位置とQRコード位置を別に校正しました。

最終的にQRコードについては、テープ端で切れないよう1モジュール相当の描画サイズも調整しています。

QRコードは単に画像をリサイズするのではなく、モジュール単位を崩さないことが重要です。


背表紙印刷

ファイル背表紙用として、文字を一文字ずつ縦方向へ並べるレイアウトを実装しました。

単純に横文字を90度回転するのではなく、

第
一
巻

のように文字自体は正立したまま配置します。

最初に起きた問題

背表紙ラベルを自動長にすると、内容に対してテープが妙に長くなりました。

原因の一つは、短すぎるラスターを避けるために入れていた、

MINIMUM_RASTER_LENGTH_MM = 30.0

でした。

これにより内容が短くても約30mmまでラスターが強制的に延長されます。

現在は背表紙印刷について、この最低ラスター長を適用しません。

また、

  • 先頭余白
  • 後端余白
  • 自動長計算上の安全用余長

も背表紙ではいったんゼロとして計算しています。

その結果、内容に必要な長さへかなり素直に収まるようになりました。

文字サイズ

初期実装には、

min(max_width, 72)

という72dot上限がありました。

18mm、24mmでも文字が必要以上に細くなるため、背表紙ではこの上限を撤廃しました。

現在はテープの描画可能幅を基準にフォントサイズを決定しています。

18mmと24mmの左右補正

6 / 9 / 12mmは理論中央でほぼ問題ありませんでした。

18mm、24mmでは実印刷を見ると左側で内容が切れ、右側に余裕がありました。

そこで背表紙専用に、

18mm:
  全体を右へ微調整

24mm:
  QRコード位置を右へ調整
  文字位置をさらに右へ調整
  QRコードをわずかに縮小

という実機補正を入れています。

ここはKL-M20一般の絶対値というより、今回の実機と現在の描画方式で得られた校正値として扱うのが安全です。


印刷初期化シーケンス

実機で使用している順序です。

1. MODEL_INFO

opcode : 0x82
payload: なし

2. SET_LABEL_SIZE

opcode        : 0x17
payload length: 0x02
payload       : [signature, label_option]

例として18mmなら、

0x87 0x03

です。

3. INIT_01

opcode : 0x01
payload: なし

4. INIT_1C

opcode : 0x1c
payload: 0x01

5. INIT_0D

opcode : 0x0d
payload: 0x40

6. SET_PRINT_CONFIG

opcode        : 0x09
payload length: 0x06
payload:
  [width_mode, 0x00, 0xff, 0xff, 0x00, 0x00]

7. SET_CUT_MODE

opcode        : 0x19
payload length: 0x01

使用した値は次の通りです。

動作
0x01 通常。ラベル間のハーフカットを要求
0x00 1枚ずつ切り離す
0xff カットしない

ラスターデータ

画像は1bitで作成します。

処理の概略は次の通りです。

  1. テープ幅に応じた描画用画像を作る
  2. 必要に応じて128dot転送キャンバスへYオフセット付きで貼る
  3. 画像を転置し、列単位データへ変換する
  4. 各byteのbit順を反転する
  5. 左から右へ送る

Pillowでは、概ね次の処理です。

from PIL import Image

def encode_raster(image: Image.Image) -> bytes:
    bit_reverse = bytes(
        int(f"{value:08b}"[::-1], 2)
        for value in range(256)
    )

    return (
        image
        .transpose(Image.Transpose.TRANSPOSE)
        .tobytes()
        .translate(bit_reverse)
    )

1列あたりのbyte数は次の通りです。

テープ幅 1列
9mm 8byte
6 / 12 / 18 / 24mm 16byte

データ転送パケット

byte 0    0x02
byte 1    0xfe
byte 2    payload length
byte 3    0x00
byte 4... raster payload

ラスターpayloadは最大60byteずつ送ります。

def raster_packet(payload: bytes) -> bytes:
    if not 1 <= len(payload) <= 60:
        raise ValueError("payload must be 1..60 bytes")

    return bytes([
        0x02,
        0xfe,
        len(payload),
        0x00,
    ]) + payload

各パケット送信後、0x06のACKを確認します。


ラベル終了、送り、カット

各ラベルのラスター送信後に、次の処理を行います。

END_LABEL

16byte command
opcode : 0x04
payload: なし

MOVE_TAPE

これは16byteコマンドではなく、1byteをそのまま送ります。

0x0c

複数枚では、各ラベルについて、

ラスター送信
↓
END_LABEL
↓
MOVE_TAPE

を繰り返します。

すべてのラベルが終了したあと、最終送りを行います。

FEED

opcode : 0x1b
payload: 0x15

FINAL_FULL_CUT

カットなし以外では、最後に1byteをそのまま送ります。

0x07

今回の実装では、送りとカットの順序を変更しないようにしています。


「タテ・ヨコ 1枚ずつ印刷」

ファイル整理で意外に便利だったのが、この機能です。

同じ内容から、

ヨコ
↓
ハーフカット
↓
背表紙
↓
フルカット

を一度に出します。

単純にWeb側から通常印刷ジョブを2回投げるだけでは、最初の印刷終了時にフルカットされてしまいます。

そこでネイティブUSBプログラムへ、二つの異なるラスターを同一セッションで受け取る機能を追加しました。

CLIは次のような形です。

klm20-native \
  --raster horizontal.raster \
  --raster2 vertical.raster \
  --cut normal \
  --copies 1

内部では、

SET_CUT_MODE = normal / 0x01

1枚目ラスター
END_LABEL
MOVE_TAPE

2枚目ラスター
END_LABEL
MOVE_TAPE

FEED
FINAL_FULL_CUT

と処理します。

0x01のカット設定が有効な状態でラベル境界を処理するため、1枚目と2枚目の間にハーフカットが入ります。

最後だけ0x07でフルカットします。

Web UIのボタン名は、そのまま、

タテ・ヨコ 1枚ずつ印刷

です。

このボタンでは画面上の部数設定は使わず、必ず1枚+1枚としています。


実テープ幅を反映したプレビュー

プレビューも途中で大きく作り直しました。

初期版では、

image = render_label(...)
preview_png(image)

のように、描画キャンバスそのものを表示していました。

しかし24mmテープで128dot画像だけを表示すると、

24mmテープの中のどこへ印刷されるのか

が分かりません。

現在はプレビュー専用に、

build_physical_preview(...)

という処理を入れています。

ここでは、

  • テープの公称幅
  • 描画キャンバス高さ
  • 転送高さ
  • 転送オフセット
  • 横印刷・背表紙印刷の校正結果

を使って、実テープ上での見え方に近い画像を生成します。

24mmなら、

24mmテープ全体
┌────────────────────────┐
│       実際の印字領域       │
└────────────────────────┘

という関係が画面でも分かります。

また、初期版でプレビューへ付けていた架空の右余白や、CSSによる最低260pxへの強制拡大も撤去しました。

現在は印刷前に、

  • 左右余白
  • 上下余白
  • センタリング
  • QRコード位置

をかなり正確に確認できます。


Web UI側の構造

印刷機能は大きく二つへ分けています。

Webアプリ
  ├─ 入力・プリセット
  ├─ QRコード生成
  ├─ 文字レイアウト
  ├─ 実テープ幅プレビュー
  ├─ 1bitラスター作成
  ├─ 通常印刷ジョブ
  └─ タテ・ヨコ連続印刷ジョブ

ネイティブUSBプログラム
  ├─ KL-M20検出
  ├─ テープ幅取得
  ├─ 初期化
  ├─ 1ラスター転送
  ├─ 2ラスター連続転送
  ├─ 送り
  └─ カット

USB部分はCとlibusbで作りました。

WebアプリはUSBプログラムをCLIとして呼び出します。

klm20-native --status-json

通常印刷は、

klm20-native \
  --raster label.raster \
  --cut normal \
  --copies 2

タテ・ヨコ印刷は、

klm20-native \
  --raster horizontal.raster \
  --raster2 vertical.raster \
  --cut normal \
  --copies 1

です。

この境界を保つことで、Web UIとUSB実装を分離できます。

将来Windows版を作る人は、同じ入出力を持つklm20-native.exeを用意すれば、Web UIの多くを再利用できます。


Linux版

正式な実機確認

  • Orange Pi Zero
  • ARM 32-bit
  • Debian系Linux
  • KL-M20
  • 6 / 9 / 12 / 18 / 24mmテープ

対応見込み

  • Debian / Ubuntuのx86_64
  • Raspberry Pi OS 64bit
  • その他のDebian系ARM環境

C部分はlibusbを使用し、CPU固有のアセンブリは使っていません。

そのため別アーキテクチャでも、ソースからコンパイルできる可能性があります。


Windows版は作らないのか

USB直結のWindows版も、技術的には作れると考えています。

必要になる主な変更は次の通りです。

  • libusbのWindows対応
  • WinUSBドライバー割り当て
  • Linuxのfcntl排他処理の置換
  • systemdの置換
  • Windows用保存先
  • Windows用フォント処理
  • klm20-native.exeのビルド
  • インストーラー作成

ただしWindows版を公開すると、CASIO純正ドライバーとの競合なども考える必要があります。

移植に必要な通信情報と設計を公開しますので、興味があれば作ってみてください。


AIへ渡す移植用プロンプト

以下を新しいAIチャットへ貼り付け、対象OSと希望する配布形式を追記してください。

AI移植用プロンプトを開く
あなたはUSBデバイス制御とラスタープリンター実装に詳しい
ソフトウェアエンジニアです。

以下の実機検証済み情報を使用して、
CASIO KL-M20用の印刷ソフトを対象OSへ移植してください。

推測値で既存の検証値を変更しないでください。
未確認の機種へコマンドを送信しないでください。

対象OS:
  [ここへ Windows 11 x64、macOS、別Linuxなどを記入]

希望する成果物:
  [CLI、GUI、ローカルWeb UI、インストーラーなどを記入]

## 対象機

実機確認済み:
  CASIO NAME LAND KL-M20

USB:
  Vendor ID          0x07cf
  Product ID         0x4109
  Interface          0
  Bulk OUT endpoint  0x01
  Bulk IN endpoint   0x82
  OUT max packet     64 bytes
  IN max packet      8 bytes

他のネームランド機種での互換性は未確認です。

## 通常コマンド形式

通常コマンドは16byte固定。

byte 0: 0x02
byte 1: opcode
byte 2: payload length
byte 3: 0x00
byte 4以降: payload
残り: 0x00

通常の成功応答は1byteのACK:

0x06

KL-M20は不適切と思われる設定値にもACKを返すことがある。
ACKだけを設定値が正しい証拠として扱わないこと。

## 初期照会

PROBE:
  opcode 0x1d
  payloadなし

GET_TAPE_SIZE:
  opcode 0x1a
  payloadなし

GET_TAPE_SIZE応答のbyte 4がテープ幅シグネチャ。

## 実機確認済みテープ設定

6mm:
  signature          0x81
  SET_LABEL_SIZE     0x81 0x02
  width_mode         0x02
  drawing_height     48dot
  transfer_height    128dot
  transfer_offset_y  42
  bytes_per_column   16

9mm:
  signature          0x85
  SET_LABEL_SIZE     0x85 0x00
  width_mode         0x01
  drawing_height     64dot
  transfer_height    64dot
  transfer_offset_y  0
  bytes_per_column   8

12mm:
  signature          0x83
  SET_LABEL_SIZE     0x83 0x01
  width_mode         0x00
  drawing_height     96dot
  transfer_height    128dot
  transfer_offset_y  18
  bytes_per_column   16

18mm:
  signature          0x87
  SET_LABEL_SIZE     0x87 0x03
  width_mode         0x00
  drawing_height     128dot
  transfer_height    128dot
  transfer_offset_y  4
  bytes_per_column   16

24mm:
  signature          0x86
  SET_LABEL_SIZE     0x86 0x04
  width_mode         0x00
  drawing_height     128dot
  transfer_height    128dot
  transfer_offset_y  8
  bytes_per_column   16

注意:
  上記transfer_offset_yは現在のWeb実装における
  実機校正済み値。

  24mmのsignatureは0x86。0x89ではない。

  24mmテープでも印字ヘッド有効高さは128dot。

  QRコードの縦横比やモジュール構造を壊さないこと。

## 印刷初期化

1. MODEL_INFO
   opcode 0x82
   payloadなし

2. SET_LABEL_SIZE
   opcode 0x17
   payload length 0x02
   payload [signature, label_option]

3. INIT_01
   opcode 0x01
   payloadなし

4. INIT_1C
   opcode 0x1c
   payload 0x01

5. INIT_0D
   opcode 0x0d
   payload 0x40

6. SET_PRINT_CONFIG
   opcode 0x09
   payload length 0x06
   payload:
     [width_mode, 0x00, 0xff, 0xff, 0x00, 0x00]

7. SET_CUT_MODE
   opcode 0x19
   payload length 0x01

   0x01 通常、ラベル間ハーフカット
   0x00 1枚ずつ切り離す
   0xff カットなし

## ラスター変換

画像は1bit。

1. テープ別のdrawing_heightで画像を作る。
2. transfer_heightが異なる場合、
   transfer_offset_yへ貼り付ける。
3. 画像を転置して列単位へ変換する。
4. 各byteのbit順を反転する。
5. 左から右へ転送する。

データ転送パケット:

byte 0: 0x02
byte 1: 0xfe
byte 2: payload length
byte 3: 0x00
byte 4以降: raster payload

payloadは最大60byte。
各パケット送信後にACK 0x06を確認する。

## 各ラベルの終了

END_LABEL:
  16byte command
  opcode 0x04
  payloadなし

MOVE_TAPE:
  1byteを直接送信
  0x0c

複数枚では各ラベルについて繰り返す。

## 全ラベル終了後

FEED:
  opcode 0x1b
  payload 0x15

FINAL_FULL_CUT:
  カットなし以外では1byteを直接送信
  0x07

## 異なる2枚を連続印刷する場合

同一USBセッション内で、

1枚目ラスター
END_LABEL
MOVE_TAPE

2枚目ラスター
END_LABEL
MOVE_TAPE

FEED
FINAL_FULL_CUT

と処理できる。

SET_CUT_MODE = 0x01で、
1枚目と2枚目の間にハーフカットを要求する。

CLIを作る場合は例えば、

--raster FILE1
--raster2 FILE2

のように二つのラスターを受け取れる設計にするとよい。

## 安全条件

- VID/PIDが07cf:4109であることを確認する。
- GET_TAPE_SIZE応答とテープ設定が一致しなければ印刷しない。
- 未確認signatureでは印刷しない。
- USBアクセスをプロセス間で排他する。
- ACKだけで未知の設定値を正しいと判断しない。
- ラスターサイズがbytes_per_columnで割り切れることを確認する。
- 送りとカットの順序を変更しない。
- 最初はstatus取得だけを実装する。
- status確認後に、カットなしの短い校正パターンを1枚印刷する。
- 実機確認なしで「対応済み」と記載しない。

## 要求する成果物

1. 状態取得コマンド
2. テープ幅自動判定
3. PNGまたは1bit画像からのラスター変換
4. 1枚印刷
5. 複数枚印刷
6. 異なる2ラスターの連続印刷
7. 3種類のカット指定
8. USB排他処理
9. エラー時の安全な終了処理
10. ビルド手順
11. インストール手順
12. 純正ドライバーへ戻す手順
13. 実機未確認部分の明示

一度に全機能を作らず、
状態取得、校正印刷、通常印刷の順に進めてください。

ほかのネームランドでも使えるか

CASIOの旧PCラベルユーティリティー「BA-P20」は、KL-M20のほかにも多数のネームランドやPCミニプリンターを対象機種としていました。

掲載されていた機種には、次のようなものがあります。

KL-V460 / KL-V450 / KL-V400
KL-T100 / KL-T70 / KL-T50
KL-G2 / KL-G1
KL-M40 / KL-M30 / KL-M20
KLD-350 / KLD-300 / KLD-700
KL-A50E / KL-S30
EL-5000W / EL-700
KL-E20 / KL-E11
MP-1000

ただし、今回確認したのはKL-M20だけです。

同じCASIO製、同じ世代、同じ公式ソフト対応機種だからといって、USBコマンドやテープ設定が同じとは限りません。

未知の機種へ今回の値をそのまま送ることは勧めません。


安全上の注意

この解析情報を利用する場合、少なくとも次を守ってください。

  • CASIO非公式であることを理解する
  • KL-M20以外は未確認として扱う
  • 未知の機器へ印刷・送り・カット命令を送らない
  • 印刷前にテープ幅を再確認する
  • USBアクセスを排他する
  • 電源断やUSB切断を印刷中に行わない
  • 失敗時に無限再送しない
  • まずカットなしで試す
  • テープを無駄にしても困らない短い校正パターンを使う
  • 本体異音やエラーが出たら停止する
  • 公開サーバーにせず、家庭内LANで利用する

特に今回分かったのは、

ACKは「その設定が正しい」という保証ではない

という点です。

KL-M20は命令を受理しても、印刷結果が正しくない場合があります。

最後は実物を見る必要があります。


ライセンスと商標

  • 「CASIO」「NAME LAND」「ネームランド」は、各権利者の商標または登録商標です。
  • 本プロジェクトはCASIO COMPUTER CO., LTD.とは関係のない非公式プロジェクトです。
  • フォントを同梱する場合は、それぞれのライセンスを確認してください。
  • ソースコードのライセンスは、公開リポジトリで明記します。
  • USB解析値については、実機観察結果として提供します。

まとめ

古い機械は、ソフトウェアの都合で先に「使えないもの」扱いされることがあります。

でも、機械そのものは壊れていない。

USB端子があり、テープが手に入り、印字ヘッドもカッターも動く。

足りなかったのは、いまの暮らしに合った入口だけでした。

今回、KL-M20は、

  • ブラウザー操作
  • QRコード
  • 6〜24mmテープ自動判定
  • 横印刷
  • 背表紙印刷
  • 自動長
  • 実テープ幅プレビュー
  • ハーフカット
  • タテ・ヨコ連続印刷
  • プリセット
  • JSONバックアップ

まで使えるようになりました。

最新機種と同じものになったわけではありません。

でも、少なくとも我が家では、以前よりずっと使いやすいKL-M20になりました。

ここまで来ると「古いプリンターを延命した」というより、

機械部分はそのままに、操作系だけ2026年へ更新した

という感覚に近いです。

AIによって、こうした小さな専用ソフトを個人でも作りやすくなりました。

ただし、AIが全部やってくれるわけではありません。

AIが、

この可能性があります

と言う。

実機を印刷する。

数dotずれている。

また直す。

そしてもう一度、

「でも本当にそう?」

と確認する。

この繰り返しでした。

最後には、24mm背表紙のQRコードを数dot動かし、文字をさらに数dot右へ寄せるところまで追い込みました。

そこまでやる必要があったのか。

たぶん、普通はありません。

でも、きれいに印刷できると気持ちがいい。

そして、まだ働ける機械がまた日常の道具として戻ってくるのは、もっと気持ちがいい。

この記録が、どこかの棚で眠っているネームランドを、もう一度起こすきっかけになればうれしいです。


参考資料

  • CASIO「KL-M20 ソフトウェアダウンロード」
  • CASIO「KL-M20 プリンタードライバー ダウンロード」
  • CASIO「サポート終了製品ソフトウェアダウンロード」
  • CASIO「PCラベルユーティリティー BA-P20」
  • CASIO「ラベルライター 取扱説明書」
  • libusb documentation
  • Flask documentation
  • Waitress documentation
  • Pillow documentation
  • qrcode for Python documentation

公開時には、GitHubリポジトリ、導入手順、診断スクリプト、実機検証ログへのリンクをこの節へ追記します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?