~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/usb/6fire/comm.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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                 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 
 55 static 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 
 92 static 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 
106 static 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 
124 static 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 
142 int 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 
185 void 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 
193 void 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 }
201 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php