summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/fsl_updater.h
blob: 0adc30f088afcd0145ecbf6046425e3acef1348e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Freescale UUT driver
 *
 * Copyright 2008-2013 Freescale Semiconductor, Inc.
 * Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
 */

/*
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#ifndef __FSL_UPDATER_H
#define __FSL_UPDATER_H

#include <linux/miscdevice.h>
#include <linux/list.h>
#include <linux/vmalloc.h>
#include <linux/ioctl.h>
/* #include <mach/hardware.h> */

static int utp_init(struct fsg_dev *fsg);
static void utp_exit(struct fsg_dev *fsg);
static ssize_t utp_file_read(struct file *file,
			     char __user *buf,
			     size_t size,
			     loff_t *off);

static ssize_t utp_file_write(struct file *file,
			      const char __user *buf,
			      size_t size,
			      loff_t *off);

static long utp_ioctl(struct file *file,
	      unsigned int cmd, unsigned long arg);
static struct utp_user_data *utp_user_data_alloc(size_t size);
static void utp_user_data_free(struct utp_user_data *uud);
static int utp_get_sense(struct fsg_dev *fsg);
static int utp_do_read(struct fsg_dev *fsg, void *data, size_t size);
static int utp_do_write(struct fsg_dev *fsg, void *data, size_t size);
static inline void utp_set_sense(struct fsg_dev *fsg, u16 code, u64 reply);
static int utp_handle_message(struct fsg_dev *fsg,
			      char *cdb_data,
			      int default_reply);

#define UTP_REPLY_PASS		0
#define UTP_REPLY_EXIT		0x8001
#define UTP_REPLY_BUSY		0x8002
#define UTP_REPLY_SIZE		0x8003
#define UTP_SENSE_KEY		9

#define UTP_MINOR		222
/* MISC_DYNAMIC_MINOR would be better, but... */

#define UTP_COMMAND_SIZE	80

#define UTP_SS_EXIT(fsg, r)	utp_set_sense(fsg, UTP_REPLY_EXIT, (u64)r)
#define UTP_SS_PASS(fsg)	utp_set_sense(fsg, UTP_REPLY_PASS, 0)
#define UTP_SS_BUSY(fsg, r)	utp_set_sense(fsg, UTP_REPLY_BUSY, (u64)r)
#define UTP_SS_SIZE(fsg, r)	utp_set_sense(fsg, UTP_REPLY_SIZE, (u64)r)

#define	UTP_IOCTL_BASE	'U'
#define	UTP_GET_CPU_ID	_IOR(UTP_IOCTL_BASE, 0, int)
/* the structure of utp message which is mapped to 16-byte SCSI CBW's CDB */
#pragma pack(1)
struct utp_msg {
	u8  f0;
	u8  utp_msg_type;
	u32 utp_msg_tag;
	union {
		struct {
			u32 param_lsb;
			u32 param_msb;
		};
		u64 param;
	};
};

enum utp_msg_type {
	UTP_POLL = 0,
	UTP_EXEC,
	UTP_GET,
	UTP_PUT,
};

static struct utp_context {
	wait_queue_head_t wq;
	wait_queue_head_t list_full_wq;
	struct mutex lock;
	struct list_head read;
	struct list_head write;
	u32 sd, sdinfo, sdinfo_h;			/* sense data */
	int processed;
	u8 *buffer;
	u32 counter;
	u64 utp_version;
	u32 cur_state;
} utp_context;

static const struct file_operations utp_fops = {
	.open	= nonseekable_open,
	.read	= utp_file_read,
	.write	= utp_file_write,
	/* .ioctl  = utp_ioctl, */
	.unlocked_ioctl  = utp_ioctl,
};

static struct miscdevice utp_dev = {
	.minor	= UTP_MINOR,
	.name	= "utp",
	.fops	= &utp_fops,
};

#define UTP_FLAG_COMMAND	0x00000001
#define UTP_FLAG_DATA		0x00000002
#define UTP_FLAG_STATUS		0x00000004
#define UTP_FLAG_REPORT_BUSY	0x10000000
struct utp_message {
	u32	flags;
	size_t	size;
	union {
		struct {
			u64 payload;
			char command[1];
		};
		struct {
			size_t bufsize;
			u8 data[1];
		};
		u32 status;
	};
};

struct utp_user_data {
	struct  list_head	link;
	struct  utp_message	data;
};
#pragma pack()

static inline struct utp_context *UTP_CTX(struct fsg_dev *fsg)
{
	return (struct utp_context *)fsg->utp;
}

#endif /* __FSL_UPDATER_H */