1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Linux driver for TerraTec DMX 6Fire USB
4 *
5 * Device communications
6 *
7 * Author: Torsten Schenk <torsten.schenk@zoho.com>
8 * Created: Jan 01, 2011
9 * Copyright: (C) Torsten Schenk
10 */
11
12 #include "comm.h"
13 #include "chip.h"
14 #include "midi.h"
15
16 enum {
17 COMM_EP = 1,
18 COMM_FPGA_EP = 2
19 };
20
usb6fire_comm_init_urb(struct comm_runtime * rt,struct urb * urb,u8 * buffer,void * context,void (* handler)(struct urb * urb))21 static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb,
22 u8 *buffer, void *context, void(*handler)(struct urb *urb))
23 {
24 urb->transfer_buffer = buffer;
25 urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP);
26 urb->complete = handler;
27 urb->context = context;
28 urb->interval = 1;
29 urb->dev = rt->chip->dev;
30 }
31
usb6fire_comm_receiver_handler(struct urb * urb)32 static void usb6fire_comm_receiver_handler(struct urb *urb)
33 {
34 struct comm_runtime *rt = urb->context;
35 struct midi_runtime *midi_rt = rt->chip->midi;
36
37 if (!urb->status) {
38 u8 len = rt->receiver_buffer[1];
39
40 if (rt->receiver_buffer[0] == 0x10 && /* midi in event */
41 len <= COMM_RECEIVER_BUFSIZE - 2 &&
42 urb->actual_length >= len + 2)
43 if (midi_rt)
44 midi_rt->in_received(midi_rt,
45 rt->receiver_buffer + 2, len);
46 }
47
48 if (!rt->chip->shutdown) {
49 urb->status = 0;
50 urb->actual_length = 0;
51 if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
52 dev_warn(&urb->dev->dev,
53 "comm data receiver aborted.\n");
54 }
55 }
56
usb6fire_comm_init_buffer(u8 * buffer,u8 id,u8 request,u8 reg,u8 vl,u8 vh)57 static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request,
58 u8 reg, u8 vl, u8 vh)
59 {
60 buffer[0] = 0x01;
61 buffer[2] = request;
62 buffer[3] = id;
63 switch (request) {
64 case 0x02:
65 buffer[1] = 0x05; /* length (starting at buffer[2]) */
66 buffer[4] = reg;
67 buffer[5] = vl;
68 buffer[6] = vh;
69 break;
70
71 case 0x12:
72 buffer[1] = 0x0b; /* length (starting at buffer[2]) */
73 buffer[4] = 0x00;
74 buffer[5] = 0x18;
75 buffer[6] = 0x05;
76 buffer[7] = 0x00;
77 buffer[8] = 0x01;
78 buffer[9] = 0x00;
79 buffer[10] = 0x9e;
80 buffer[11] = reg;
81 buffer[12] = vl;
82 break;
83
84 case 0x20:
85 case 0x21:
86 case 0x22:
87 buffer[1] = 0x04;
88 buffer[4] = reg;
89 buffer[5] = vl;
90 break;
91 }
92 }
93
usb6fire_comm_send_buffer(u8 * buffer,struct usb_device * dev)94 static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
95 {
96 int ret;
97 int actual_len;
98
99 ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP),
100 buffer, buffer[1] + 2, &actual_len, 1000);
101 if (ret < 0)
102 return ret;
103 else if (actual_len != buffer[1] + 2)
104 return -EIO;
105 return 0;
106 }
107
usb6fire_comm_write8(struct comm_runtime * rt,u8 request,u8 reg,u8 value)108 static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
109 u8 reg, u8 value)
110 {
111 u8 *buffer;
112 int ret;
113
114 /* 13: maximum length of message */
115 buffer = kmalloc(13, GFP_KERNEL);
116 if (!buffer)
117 return -ENOMEM;
118
119 usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
120 ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
121
122 kfree(buffer);
123 return ret;
124 }
125
usb6fire_comm_write16(struct comm_runtime * rt,u8 request,u8 reg,u8 vl,u8 vh)126 static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
127 u8 reg, u8 vl, u8 vh)
128 {
129 u8 *buffer;
130 int ret;
131
132 /* 13: maximum length of message */
133 buffer = kmalloc(13, GFP_KERNEL);
134 if (!buffer)
135 return -ENOMEM;
136
137 usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
138 ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
139
140 kfree(buffer);
141 return ret;
142 }
143
usb6fire_comm_free(struct comm_runtime * rt)144 static void usb6fire_comm_free(struct comm_runtime *rt)
145 {
146 if (!rt)
147 return;
148
149 if (rt->chip)
150 rt->chip->comm = NULL;
151
152 usb_free_urb(rt->receiver);
153 kfree(rt->receiver_buffer);
154 kfree(rt);
155 }
156
usb6fire_comm_init(struct sfire_chip * chip)157 int usb6fire_comm_init(struct sfire_chip *chip)
158 {
159 struct comm_runtime *rt = kzalloc_obj(struct comm_runtime);
160 struct urb *urb;
161 int ret;
162
163 if (!rt)
164 return -ENOMEM;
165
166 rt->receiver_buffer = kzalloc(COMM_RECEIVER_BUFSIZE, GFP_KERNEL);
167 if (!rt->receiver_buffer) {
168 ret = -ENOMEM;
169 goto error;
170 }
171
172 urb = usb_alloc_urb(0, GFP_KERNEL);
173 if (!urb) {
174 ret = -ENOMEM;
175 goto error;
176 }
177 rt->receiver = urb;
178 rt->serial = 1;
179 rt->chip = chip;
180 rt->init_urb = usb6fire_comm_init_urb;
181 rt->write8 = usb6fire_comm_write8;
182 rt->write16 = usb6fire_comm_write16;
183
184 /* submit an urb that receives communication data from device */
185 urb->transfer_buffer = rt->receiver_buffer;
186 urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE;
187 urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP);
188 urb->dev = chip->dev;
189 urb->complete = usb6fire_comm_receiver_handler;
190 urb->context = rt;
191 urb->interval = 1;
192 ret = usb_submit_urb(urb, GFP_KERNEL);
193 if (ret < 0) {
194 dev_err(&chip->dev->dev, "cannot create comm data receiver.");
195 goto error;
196 }
197 chip->comm = rt;
198 return 0;
199
200 error:
201 usb6fire_comm_free(rt);
202 return ret;
203 }
204
usb6fire_comm_abort(struct sfire_chip * chip)205 void usb6fire_comm_abort(struct sfire_chip *chip)
206 {
207 struct comm_runtime *rt = chip->comm;
208
209 if (rt)
210 usb_poison_urb(rt->receiver);
211 }
212
usb6fire_comm_destroy(struct sfire_chip * chip)213 void usb6fire_comm_destroy(struct sfire_chip *chip)
214 {
215 usb6fire_comm_free(chip->comm);
216 }
217