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

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

Version: ~ [ linux-5.11-rc3 ] ~ [ linux-5.10.7 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.89 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.167 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.215 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.251 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.251 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp