root/sound/usb/6fire/comm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usb6fire_comm_init_urb
  2. usb6fire_comm_receiver_handler
  3. usb6fire_comm_init_buffer
  4. usb6fire_comm_send_buffer
  5. usb6fire_comm_write8
  6. usb6fire_comm_write16
  7. usb6fire_comm_init
  8. usb6fire_comm_abort
  9. usb6fire_comm_destroy

   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, HZ);
  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 }

/* [<][>][^][v][top][bottom][index][help] */