summaryrefslogtreecommitdiff
path: root/cmd/ipp/main.go
blob: 21cf0fc52accdfa3a111c18b3edf274385263565 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package main

import (
	"encoding/binary"
	"encoding/hex"
	"flag"
	"log"
	"strconv"
	"time"

	"pm3.dev/cvend"
)

var wait = flag.Duration("w", 5*time.Second, "how long to wait for a response")
var follow = flag.Bool("f", false, "don't exit after response")

func main() {
	flag.Parse()
	log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime | log.Lmicroseconds)
	log.Println("start")
	wc := make(chan struct{}, 1)
	cv, err := cvend.Open(cvend.Path, func(msgType byte, msgData []byte) {
		switch msgType {
		case 0x07:
			log.Printf("Heartbeat(%s)", hex.EncodeToString(msgData))
		case 0x0f:
			log.Printf("Startup(%s)", hex.EncodeToString(msgData))
		case 0xed:
			if len(msgData) == 0 {
				log.Printf("Log()")
			} else {
				log.Printf("Log(%d) %q", msgData[0], string(msgData[1:]))
			}
		case 0xbe:
			if len(msgData) < 22 || len(msgData) < 22+int(msgData[21]) {
				log.Printf("PICCRead(short)\n%s", hex.Dump(msgData))
			} else {
				_ = msgData[:11] // unknown
				uid := msgData[11:18]
				atqa := binary.LittleEndian.Uint16(msgData[18:20])
				sak := msgData[20]
				atrLen := msgData[21]
				atr := msgData[22 : 22+atrLen]
				_ = msgData[22+atrLen:] // unknown
				log.Printf("PICCRead(uid %s atqa 0x%04x sak %02x atr %s)\n%s", hex.EncodeToString(uid), atqa, sak, hex.EncodeToString(atr), hex.Dump(msgData))
			}
		case 0xd1:
			log.Printf("EMVTransactionSuccessUnk\n%s", hex.Dump(msgData))
		default:
			log.Printf("ipp %02x\n%s", msgType, hex.Dump(msgData))
		}
		select {
		case wc <- struct{}{}:
		default:
		}
	})
	if err != nil {
		panic(err)
	}
	defer cv.Close()
	for i := 0; i < flag.NArg(); i += 2 {
		var msgType byte
		var msgData []byte
		if n, err := strconv.ParseUint(flag.Arg(i), 0, 8); err != nil {
			panic(err)
		} else {
			msgType = byte(n)
		}
		if bs, err := hex.DecodeString(flag.Arg(i + 1)); err != nil {
			panic(err)
		} else {
			msgData = bs
		}
		if err := cv.SendIPP(msgType, msgData); err != nil {
			panic(err)
		}
		if *wait > 0 {
			select {
			case <-wc:
			case <-time.After(*wait):
			}
		}
	}
	if *follow || flag.NArg() == 0 {
		select {}
	}
}