1
2
3
4
5
6
7 package spi
8
9 import (
10 "fmt"
11 "os"
12 "syscall"
13 "unsafe"
14
15 "golang.org/x/exp/io/spi/driver"
16 )
17
18 const (
19 devfs_MAGIC = 107
20
21 devfs_NRBITS = 8
22 devfs_TYPEBITS = 8
23 devfs_SIZEBITS = 13
24 devfs_DIRBITS = 3
25
26 devfs_NRSHIFT = 0
27 devfs_TYPESHIFT = devfs_NRSHIFT + devfs_NRBITS
28 devfs_SIZESHIFT = devfs_TYPESHIFT + devfs_TYPEBITS
29 devfs_DIRSHIFT = devfs_SIZESHIFT + devfs_SIZEBITS
30
31 devfs_READ = 2
32 devfs_WRITE = 4
33 )
34
35 type payload struct {
36 tx uint64
37 rx uint64
38 length uint32
39 speed uint32
40 delay uint16
41 bits uint8
42 csChange uint8
43 txNBits uint8
44 rxNBits uint8
45 pad uint16
46 }
47
48
49
50 type Devfs struct {
51
52
53
54 Dev string
55
56
57
58
59
60
61 Mode Mode
62
63
64
65 MaxSpeed int64
66 }
67
68
69
70 func (d *Devfs) Open() (driver.Conn, error) {
71 f, err := os.OpenFile(d.Dev, os.O_RDWR, os.ModeDevice)
72 if err != nil {
73 return nil, err
74 }
75 conn := &devfsConn{f: f}
76 if err := conn.Configure(driver.Mode, int(d.Mode)); err != nil {
77 conn.Close()
78 return nil, err
79 }
80 if err := conn.Configure(driver.MaxSpeed, int(d.MaxSpeed)); err != nil {
81 conn.Close()
82 return nil, err
83 }
84 return conn, nil
85 }
86
87 type devfsConn struct {
88 f *os.File
89 mode uint8
90 speed uint32
91 bits uint8
92 delay uint16
93 csChange uint8
94 }
95
96 func (c *devfsConn) Configure(k, v int) error {
97 switch k {
98 case driver.Mode:
99 m := uint8(v)
100 if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 1, 1), uintptr(unsafe.Pointer(&m))); err != nil {
101 return fmt.Errorf("error setting mode to %v: %v", m, err)
102 }
103 c.mode = m
104 case driver.Bits:
105 b := uint8(v)
106 if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 3, 1), uintptr(unsafe.Pointer(&b))); err != nil {
107 return fmt.Errorf("error setting bits per word to %v: %v", b, err)
108 }
109 c.bits = b
110 case driver.MaxSpeed:
111 s := uint32(v)
112 if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 4, 4), uintptr(unsafe.Pointer(&s))); err != nil {
113 return fmt.Errorf("error setting speed to %v: %v", s, err)
114 }
115 c.speed = s
116 case driver.Order:
117 o := uint8(v)
118 if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 2, 1), uintptr(unsafe.Pointer(&o))); err != nil {
119 return fmt.Errorf("error setting bit order to %v: %v", o, err)
120 }
121 case driver.Delay:
122 c.delay = uint16(v)
123 case driver.CSChange:
124 c.csChange = uint8(v)
125 default:
126 return fmt.Errorf("unknown key: %v", k)
127 }
128 return nil
129 }
130
131 func (c *devfsConn) Tx(w, r []byte) error {
132 if r == nil {
133 r = make([]byte, len(w))
134 }
135
136
137 p := payload{
138 tx: uint64(uintptr(unsafe.Pointer(&w[0]))),
139 rx: uint64(uintptr(unsafe.Pointer(&r[0]))),
140 length: uint32(len(w)),
141 speed: c.speed,
142 delay: c.delay,
143 bits: c.bits,
144 csChange: c.csChange,
145 }
146
147 return c.ioctl(msgRequestCode(1), uintptr(unsafe.Pointer(&p)))
148 }
149
150 func (c *devfsConn) Close() error {
151 return c.f.Close()
152 }
153
154
155
156 func requestCode(dir, typ, nr, size uintptr) uintptr {
157 return (dir << devfs_DIRSHIFT) | (typ << devfs_TYPESHIFT) | (nr << devfs_NRSHIFT) | (size << devfs_SIZESHIFT)
158 }
159
160
161
162
163 func msgRequestCode(n uint32) uintptr {
164 return uintptr(0x40006B00 + (n * 0x200000))
165 }
166
167
168 func (c *devfsConn) ioctl(a1, a2 uintptr) error {
169 _, _, errno := syscall.Syscall(
170 syscall.SYS_IOCTL, c.f.Fd(), a1, a2,
171 )
172 if errno != 0 {
173 return syscall.Errno(errno)
174 }
175 return nil
176 }
177
View as plain text