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 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 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 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 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 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 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 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 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 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 213 void usb6fire_comm_destroy(struct sfire_chip *chip) 214 { 215 usb6fire_comm_free(chip->comm); 216 } 217