cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

comm.c (4299B)


      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
     16enum {
     17	COMM_EP = 1,
     18	COMM_FPGA_EP = 2
     19};
     20
     21static 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
     33static 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
     55static 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
     92static 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
    106static 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
    124static 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
    142int 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
    185void 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
    193void 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}