Linux Audio

Check our new training course

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