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