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

cytherm.c (8640B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* -*- linux-c -*-
      3 * Cypress USB Thermometer driver 
      4 * 
      5 * Copyright (c) 2004 Erik Rigtorp <erkki@linux.nu> <erik@rigtorp.com>
      6 * 
      7 * This driver works with Elektor magazine USB Interface as published in 
      8 * issue #291. It should also work with the original starter kit/demo board
      9 * from Cypress.
     10 */
     11
     12
     13#include <linux/kernel.h>
     14#include <linux/errno.h>
     15#include <linux/slab.h>
     16#include <linux/module.h>
     17#include <linux/usb.h>
     18
     19#define DRIVER_AUTHOR "Erik Rigtorp"
     20#define DRIVER_DESC "Cypress USB Thermometer driver"
     21
     22#define USB_SKEL_VENDOR_ID	0x04b4
     23#define USB_SKEL_PRODUCT_ID	0x0002
     24
     25static const struct usb_device_id id_table[] = {
     26	{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
     27	{ }
     28};
     29MODULE_DEVICE_TABLE (usb, id_table);
     30
     31/* Structure to hold all of our device specific stuff */
     32struct usb_cytherm {
     33	struct usb_device    *udev;	 /* save off the usb device pointer */
     34	struct usb_interface *interface; /* the interface for this device */
     35	int brightness;
     36};
     37
     38
     39/* Vendor requests */
     40/* They all operate on one byte at a time */
     41#define PING       0x00
     42#define READ_ROM   0x01 /* Reads form ROM, value = address */
     43#define READ_RAM   0x02 /* Reads form RAM, value = address */
     44#define WRITE_RAM  0x03 /* Write to RAM, value = address, index = data */
     45#define READ_PORT  0x04 /* Reads from port, value = address */
     46#define WRITE_PORT 0x05 /* Write to port, value = address, index = data */ 
     47
     48
     49/* Send a vendor command to device */
     50static int vendor_command(struct usb_device *dev, unsigned char request, 
     51			  unsigned char value, unsigned char index,
     52			  void *buf, int size)
     53{
     54	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
     55			       request, 
     56			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
     57			       value, 
     58			       index, buf, size,
     59			       USB_CTRL_GET_TIMEOUT);
     60}
     61
     62
     63
     64#define BRIGHTNESS 0x2c     /* RAM location for brightness value */
     65#define BRIGHTNESS_SEM 0x2b /* RAM location for brightness semaphore */
     66
     67static ssize_t brightness_show(struct device *dev, struct device_attribute *attr, char *buf)
     68{
     69	struct usb_interface *intf = to_usb_interface(dev);    
     70	struct usb_cytherm *cytherm = usb_get_intfdata(intf);     
     71
     72	return sprintf(buf, "%i", cytherm->brightness);
     73}
     74
     75static ssize_t brightness_store(struct device *dev, struct device_attribute *attr, const char *buf,
     76			      size_t count)
     77{
     78	struct usb_interface *intf = to_usb_interface(dev);
     79	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
     80
     81	unsigned char *buffer;
     82	int retval;
     83   
     84	buffer = kmalloc(8, GFP_KERNEL);
     85	if (!buffer)
     86		return 0;
     87
     88	cytherm->brightness = simple_strtoul(buf, NULL, 10);
     89   
     90	if (cytherm->brightness > 0xFF)
     91		cytherm->brightness = 0xFF;
     92	else if (cytherm->brightness < 0)
     93		cytherm->brightness = 0;
     94   
     95	/* Set brightness */
     96	retval = vendor_command(cytherm->udev, WRITE_RAM, BRIGHTNESS, 
     97				cytherm->brightness, buffer, 8);
     98	if (retval)
     99		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    100	/* Inform µC that we have changed the brightness setting */
    101	retval = vendor_command(cytherm->udev, WRITE_RAM, BRIGHTNESS_SEM,
    102				0x01, buffer, 8);
    103	if (retval)
    104		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    105   
    106	kfree(buffer);
    107   
    108	return count;
    109}
    110static DEVICE_ATTR_RW(brightness);
    111
    112
    113#define TEMP 0x33 /* RAM location for temperature */
    114#define SIGN 0x34 /* RAM location for temperature sign */
    115
    116static ssize_t temp_show(struct device *dev, struct device_attribute *attr, char *buf)
    117{
    118
    119	struct usb_interface *intf = to_usb_interface(dev);
    120	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
    121
    122	int retval;
    123	unsigned char *buffer;
    124
    125	int temp, sign;
    126   
    127	buffer = kmalloc(8, GFP_KERNEL);
    128	if (!buffer)
    129		return 0;
    130
    131	/* read temperature */
    132	retval = vendor_command(cytherm->udev, READ_RAM, TEMP, 0, buffer, 8);
    133	if (retval)
    134		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    135	temp = buffer[1];
    136   
    137	/* read sign */
    138	retval = vendor_command(cytherm->udev, READ_RAM, SIGN, 0, buffer, 8);
    139	if (retval)
    140		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    141	sign = buffer[1];
    142
    143	kfree(buffer);
    144   
    145	return sprintf(buf, "%c%i.%i", sign ? '-' : '+', temp >> 1,
    146		       5*(temp - ((temp >> 1) << 1)));
    147}
    148static DEVICE_ATTR_RO(temp);
    149
    150
    151#define BUTTON 0x7a
    152
    153static ssize_t button_show(struct device *dev, struct device_attribute *attr, char *buf)
    154{
    155
    156	struct usb_interface *intf = to_usb_interface(dev);
    157	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
    158
    159	int retval;
    160	unsigned char *buffer;
    161
    162	buffer = kmalloc(8, GFP_KERNEL);
    163	if (!buffer)
    164		return 0;
    165
    166	/* check button */
    167	retval = vendor_command(cytherm->udev, READ_RAM, BUTTON, 0, buffer, 8);
    168	if (retval)
    169		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    170   
    171	retval = buffer[1];
    172
    173	kfree(buffer);
    174
    175	if (retval)
    176		return sprintf(buf, "1");
    177	else
    178		return sprintf(buf, "0");
    179}
    180static DEVICE_ATTR_RO(button);
    181
    182
    183static ssize_t port0_show(struct device *dev, struct device_attribute *attr, char *buf)
    184{
    185	struct usb_interface *intf = to_usb_interface(dev);
    186	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
    187
    188	int retval;
    189	unsigned char *buffer;
    190
    191	buffer = kmalloc(8, GFP_KERNEL);
    192	if (!buffer)
    193		return 0;
    194
    195	retval = vendor_command(cytherm->udev, READ_PORT, 0, 0, buffer, 8);
    196	if (retval)
    197		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    198
    199	retval = buffer[1];
    200
    201	kfree(buffer);
    202
    203	return sprintf(buf, "%d", retval);
    204}
    205
    206
    207static ssize_t port0_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
    208{
    209	struct usb_interface *intf = to_usb_interface(dev);
    210	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
    211
    212	unsigned char *buffer;
    213	int retval;
    214	int tmp;
    215   
    216	buffer = kmalloc(8, GFP_KERNEL);
    217	if (!buffer)
    218		return 0;
    219
    220	tmp = simple_strtoul(buf, NULL, 10);
    221   
    222	if (tmp > 0xFF)
    223		tmp = 0xFF;
    224	else if (tmp < 0)
    225		tmp = 0;
    226   
    227	retval = vendor_command(cytherm->udev, WRITE_PORT, 0,
    228				tmp, buffer, 8);
    229	if (retval)
    230		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    231
    232	kfree(buffer);
    233
    234	return count;
    235}
    236static DEVICE_ATTR_RW(port0);
    237
    238static ssize_t port1_show(struct device *dev, struct device_attribute *attr, char *buf)
    239{
    240	struct usb_interface *intf = to_usb_interface(dev);
    241	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
    242
    243	int retval;
    244	unsigned char *buffer;
    245
    246	buffer = kmalloc(8, GFP_KERNEL);
    247	if (!buffer)
    248		return 0;
    249
    250	retval = vendor_command(cytherm->udev, READ_PORT, 1, 0, buffer, 8);
    251	if (retval)
    252		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    253   
    254	retval = buffer[1];
    255
    256	kfree(buffer);
    257
    258	return sprintf(buf, "%d", retval);
    259}
    260
    261
    262static ssize_t port1_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
    263{
    264	struct usb_interface *intf = to_usb_interface(dev);
    265	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
    266
    267	unsigned char *buffer;
    268	int retval;
    269	int tmp;
    270   
    271	buffer = kmalloc(8, GFP_KERNEL);
    272	if (!buffer)
    273		return 0;
    274
    275	tmp = simple_strtoul(buf, NULL, 10);
    276   
    277	if (tmp > 0xFF)
    278		tmp = 0xFF;
    279	else if (tmp < 0)
    280		tmp = 0;
    281   
    282	retval = vendor_command(cytherm->udev, WRITE_PORT, 1,
    283				tmp, buffer, 8);
    284	if (retval)
    285		dev_dbg(&cytherm->udev->dev, "retval = %d\n", retval);
    286
    287	kfree(buffer);
    288
    289	return count;
    290}
    291static DEVICE_ATTR_RW(port1);
    292
    293static struct attribute *cytherm_attrs[] = {
    294	&dev_attr_brightness.attr,
    295	&dev_attr_temp.attr,
    296	&dev_attr_button.attr,
    297	&dev_attr_port0.attr,
    298	&dev_attr_port1.attr,
    299	NULL,
    300};
    301ATTRIBUTE_GROUPS(cytherm);
    302
    303static int cytherm_probe(struct usb_interface *interface, 
    304			 const struct usb_device_id *id)
    305{
    306	struct usb_device *udev = interface_to_usbdev(interface);
    307	struct usb_cytherm *dev = NULL;
    308	int retval = -ENOMEM;
    309
    310	dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL);
    311	if (!dev)
    312		goto error_mem;
    313
    314	dev->udev = usb_get_dev(udev);
    315
    316	usb_set_intfdata (interface, dev);
    317
    318	dev->brightness = 0xFF;
    319
    320	dev_info (&interface->dev,
    321		  "Cypress thermometer device now attached\n");
    322	return 0;
    323
    324error_mem:
    325	return retval;
    326}
    327
    328static void cytherm_disconnect(struct usb_interface *interface)
    329{
    330	struct usb_cytherm *dev;
    331
    332	dev = usb_get_intfdata (interface);
    333
    334	/* first remove the files, then NULL the pointer */
    335	usb_set_intfdata (interface, NULL);
    336
    337	usb_put_dev(dev->udev);
    338
    339	kfree(dev);
    340
    341	dev_info(&interface->dev, "Cypress thermometer now disconnected\n");
    342}
    343
    344/* usb specific object needed to register this driver with the usb subsystem */
    345static struct usb_driver cytherm_driver = {
    346	.name =		"cytherm",
    347	.probe =	cytherm_probe,
    348	.disconnect =	cytherm_disconnect,
    349	.id_table =	id_table,
    350	.dev_groups =	cytherm_groups,
    351};
    352
    353module_usb_driver(cytherm_driver);
    354
    355MODULE_AUTHOR(DRIVER_AUTHOR);
    356MODULE_DESCRIPTION(DRIVER_DESC);
    357MODULE_LICENSE("GPL");