aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>2015-03-03 04:52:28 -0500
committerFelipe Balbi <balbi@ti.com>2015-03-10 16:33:40 -0400
commitb26394bd567e5ebe57ec4dee7fe6cd14023c96e9 (patch)
treefe1dcc7107817aee8ca63240946316ae8e42a762 /drivers/usb/gadget
parentb185f01a9ab7af586133be2555298e960237359b (diff)
usb: gadget: f_printer: convert to new function interface with backward compatibility
In order to add configfs support, a usb function must be converted to use the new interface. This patch converts the function to the new interface and provides backward compatiblity layer, which can be removed after all its users are converted to use the new interface. Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/Kconfig3
-rw-r--r--drivers/usb/gadget/function/Makefile2
-rw-r--r--drivers/usb/gadget/function/f_printer.c185
-rw-r--r--drivers/usb/gadget/function/u_printer.h30
-rw-r--r--drivers/usb/gadget/legacy/printer.c1
5 files changed, 220 insertions, 1 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index b454d05be583..9d507cf98f94 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -196,6 +196,9 @@ config USB_F_MIDI
196config USB_F_HID 196config USB_F_HID
197 tristate 197 tristate
198 198
199config USB_F_PRINTER
200 tristate
201
199choice 202choice
200 tristate "USB Gadget Drivers" 203 tristate "USB Gadget Drivers"
201 default USB_ETH 204 default USB_ETH
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index f71b1aaa0edf..bd7def576955 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -42,3 +42,5 @@ usb_f_midi-y := f_midi.o
42obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o 42obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o
43usb_f_hid-y := f_hid.o 43usb_f_hid-y := f_hid.o
44obj-$(CONFIG_USB_F_HID) += usb_f_hid.o 44obj-$(CONFIG_USB_F_HID) += usb_f_hid.o
45usb_f_printer-y := f_printer.o
46obj-$(CONFIG_USB_F_PRINTER) += usb_f_printer.o
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 0847972b9686..93f4d4e61fef 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -24,6 +24,7 @@
24#include <linux/mutex.h> 24#include <linux/mutex.h>
25#include <linux/errno.h> 25#include <linux/errno.h>
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/idr.h>
27#include <linux/timer.h> 28#include <linux/timer.h>
28#include <linux/list.h> 29#include <linux/list.h>
29#include <linux/interrupt.h> 30#include <linux/interrupt.h>
@@ -46,6 +47,8 @@
46#include <linux/usb/gadget.h> 47#include <linux/usb/gadget.h>
47#include <linux/usb/g_printer.h> 48#include <linux/usb/g_printer.h>
48 49
50#include "u_printer.h"
51
49#define PNP_STRING_LEN 1024 52#define PNP_STRING_LEN 1024
50#define PRINTER_MINORS 4 53#define PRINTER_MINORS 4
51#define GET_DEVICE_ID 0 54#define GET_DEVICE_ID 0
@@ -54,6 +57,10 @@
54 57
55static int major, minors; 58static int major, minors;
56static struct class *usb_gadget_class; 59static struct class *usb_gadget_class;
60#ifndef USBF_PRINTER_INCLUDED
61static DEFINE_IDA(printer_ida);
62static DEFINE_MUTEX(printer_ida_lock); /* protects access do printer_ida */
63#endif
57 64
58/*-------------------------------------------------------------------------*/ 65/*-------------------------------------------------------------------------*/
59 66
@@ -999,7 +1006,7 @@ unknown:
999 return value; 1006 return value;
1000} 1007}
1001 1008
1002static int __init printer_func_bind(struct usb_configuration *c, 1009static int printer_func_bind(struct usb_configuration *c,
1003 struct usb_function *f) 1010 struct usb_function *f)
1004{ 1011{
1005 struct usb_gadget *gadget = c->cdev->gadget; 1012 struct usb_gadget *gadget = c->cdev->gadget;
@@ -1111,6 +1118,7 @@ fail_tx_reqs:
1111 1118
1112} 1119}
1113 1120
1121#ifdef USBF_PRINTER_INCLUDED
1114static void printer_func_unbind(struct usb_configuration *c, 1122static void printer_func_unbind(struct usb_configuration *c,
1115 struct usb_function *f) 1123 struct usb_function *f)
1116{ 1124{
@@ -1155,6 +1163,7 @@ static void printer_func_unbind(struct usb_configuration *c,
1155 usb_free_all_descriptors(f); 1163 usb_free_all_descriptors(f);
1156 kfree(dev); 1164 kfree(dev);
1157} 1165}
1166#endif
1158 1167
1159static int printer_func_set_alt(struct usb_function *f, 1168static int printer_func_set_alt(struct usb_function *f,
1160 unsigned intf, unsigned alt) 1169 unsigned intf, unsigned alt)
@@ -1180,6 +1189,7 @@ static void printer_func_disable(struct usb_function *f)
1180 spin_unlock_irqrestore(&dev->lock, flags); 1189 spin_unlock_irqrestore(&dev->lock, flags);
1181} 1190}
1182 1191
1192#ifdef USBF_PRINTER_INCLUDED
1183static int f_printer_bind_config(struct usb_configuration *c, char *pnp_str, 1193static int f_printer_bind_config(struct usb_configuration *c, char *pnp_str,
1184 char *pnp_string, unsigned q_len, int minor) 1194 char *pnp_string, unsigned q_len, int minor)
1185{ 1195{
@@ -1240,6 +1250,179 @@ static int f_printer_bind_config(struct usb_configuration *c, char *pnp_str,
1240 INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); 1250 INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
1241 return 0; 1251 return 0;
1242} 1252}
1253#else
1254static inline int gprinter_get_minor(void)
1255{
1256 return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
1257}
1258
1259static inline void gprinter_put_minor(int minor)
1260{
1261 ida_simple_remove(&printer_ida, minor);
1262}
1263
1264static int gprinter_setup(int);
1265static void gprinter_cleanup(void);
1266
1267static void gprinter_free_inst(struct usb_function_instance *f)
1268{
1269 struct f_printer_opts *opts;
1270
1271 opts = container_of(f, struct f_printer_opts, func_inst);
1272
1273 mutex_lock(&printer_ida_lock);
1274
1275 gprinter_put_minor(opts->minor);
1276 if (idr_is_empty(&printer_ida.idr))
1277 gprinter_cleanup();
1278
1279 mutex_unlock(&printer_ida_lock);
1280
1281 kfree(opts);
1282}
1283
1284static struct usb_function_instance *gprinter_alloc_inst(void)
1285{
1286 struct f_printer_opts *opts;
1287 struct usb_function_instance *ret;
1288 int status = 0;
1289
1290 opts = kzalloc(sizeof(*opts), GFP_KERNEL);
1291 if (!opts)
1292 return ERR_PTR(-ENOMEM);
1293
1294 opts->func_inst.free_func_inst = gprinter_free_inst;
1295 ret = &opts->func_inst;
1296
1297 mutex_lock(&printer_ida_lock);
1298
1299 if (idr_is_empty(&printer_ida.idr)) {
1300 status = gprinter_setup(PRINTER_MINORS);
1301 if (status) {
1302 ret = ERR_PTR(status);
1303 kfree(opts);
1304 goto unlock;
1305 }
1306 }
1307
1308 opts->minor = gprinter_get_minor();
1309 if (opts->minor < 0) {
1310 ret = ERR_PTR(opts->minor);
1311 kfree(opts);
1312 if (idr_is_empty(&printer_ida.idr))
1313 gprinter_cleanup();
1314 }
1315
1316unlock:
1317 mutex_unlock(&printer_ida_lock);
1318 return ret;
1319}
1320
1321static void gprinter_free(struct usb_function *f)
1322{
1323 struct printer_dev *dev = func_to_printer(f);
1324
1325 kfree(dev);
1326}
1327
1328static void printer_func_unbind(struct usb_configuration *c,
1329 struct usb_function *f)
1330{
1331 struct printer_dev *dev;
1332 struct usb_request *req;
1333
1334 dev = func_to_printer(f);
1335
1336 device_destroy(usb_gadget_class, MKDEV(major, dev->minor));
1337
1338 /* Remove Character Device */
1339 cdev_del(&dev->printer_cdev);
1340
1341 /* we must already have been disconnected ... no i/o may be active */
1342 WARN_ON(!list_empty(&dev->tx_reqs_active));
1343 WARN_ON(!list_empty(&dev->rx_reqs_active));
1344
1345 /* Free all memory for this driver. */
1346 while (!list_empty(&dev->tx_reqs)) {
1347 req = container_of(dev->tx_reqs.next, struct usb_request,
1348 list);
1349 list_del(&req->list);
1350 printer_req_free(dev->in_ep, req);
1351 }
1352
1353 if (dev->current_rx_req != NULL)
1354 printer_req_free(dev->out_ep, dev->current_rx_req);
1355
1356 while (!list_empty(&dev->rx_reqs)) {
1357 req = container_of(dev->rx_reqs.next,
1358 struct usb_request, list);
1359 list_del(&req->list);
1360 printer_req_free(dev->out_ep, req);
1361 }
1362
1363 while (!list_empty(&dev->rx_buffers)) {
1364 req = container_of(dev->rx_buffers.next,
1365 struct usb_request, list);
1366 list_del(&req->list);
1367 printer_req_free(dev->out_ep, req);
1368 }
1369 usb_free_all_descriptors(f);
1370}
1371
1372static struct usb_function *gprinter_alloc(struct usb_function_instance *fi)
1373{
1374 struct printer_dev *dev;
1375 struct f_printer_opts *opts;
1376
1377 opts = container_of(fi, struct f_printer_opts, func_inst);
1378
1379 if (opts->minor >= minors)
1380 return ERR_PTR(-ENOENT);
1381
1382 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1383 if (!dev)
1384 return ERR_PTR(-ENOMEM);
1385
1386 dev->minor = opts->minor;
1387 dev->pnp_string = opts->pnp_string;
1388 dev->q_len = opts->q_len;
1389
1390 dev->function.name = "printer";
1391 dev->function.bind = printer_func_bind;
1392 dev->function.setup = printer_func_setup;
1393 dev->function.unbind = printer_func_unbind;
1394 dev->function.set_alt = printer_func_set_alt;
1395 dev->function.disable = printer_func_disable;
1396 dev->function.req_match = gprinter_req_match;
1397 dev->function.free_func = gprinter_free;
1398
1399 INIT_LIST_HEAD(&dev->tx_reqs);
1400 INIT_LIST_HEAD(&dev->rx_reqs);
1401 INIT_LIST_HEAD(&dev->rx_buffers);
1402 INIT_LIST_HEAD(&dev->tx_reqs_active);
1403 INIT_LIST_HEAD(&dev->rx_reqs_active);
1404
1405 spin_lock_init(&dev->lock);
1406 mutex_init(&dev->lock_printer_io);
1407 init_waitqueue_head(&dev->rx_wait);
1408 init_waitqueue_head(&dev->tx_wait);
1409 init_waitqueue_head(&dev->tx_flush_wait);
1410
1411 dev->interface = -1;
1412 dev->printer_cdev_open = 0;
1413 dev->printer_status = PRINTER_NOT_ERROR;
1414 dev->current_rx_req = NULL;
1415 dev->current_rx_bytes = 0;
1416 dev->current_rx_buf = NULL;
1417
1418 return &dev->function;
1419}
1420
1421DECLARE_USB_FUNCTION_INIT(printer, gprinter_alloc_inst, gprinter_alloc);
1422MODULE_LICENSE("GPL");
1423MODULE_AUTHOR("Craig Nadler");
1424
1425#endif
1243 1426
1244static int gprinter_setup(int count) 1427static int gprinter_setup(int count)
1245{ 1428{
diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h
new file mode 100644
index 000000000000..b2338cacdfe4
--- /dev/null
+++ b/drivers/usb/gadget/function/u_printer.h
@@ -0,0 +1,30 @@
1/*
2 * u_printer.h
3 *
4 * Utility definitions for the printer function
5 *
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * http://www.samsung.com
8 *
9 * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#ifndef U_PRINTER_H
17#define U_PRINTER_H
18
19#include <linux/usb/composite.h>
20
21#define PNP_STRING_LEN 1024
22
23struct f_printer_opts {
24 struct usb_function_instance func_inst;
25 int minor;
26 char pnp_string[PNP_STRING_LEN];
27 unsigned q_len;
28};
29
30#endif /* U_PRINTER_H */
diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c
index 4d926d08df02..770b5041323e 100644
--- a/drivers/usb/gadget/legacy/printer.c
+++ b/drivers/usb/gadget/legacy/printer.c
@@ -33,6 +33,7 @@ static const char driver_desc [] = DRIVER_DESC;
33 * This will be changed when f_printer is converted 33 * This will be changed when f_printer is converted
34 * to the new function interface. 34 * to the new function interface.
35 */ 35 */
36#define USBF_PRINTER_INCLUDED
36#include "f_printer.c" 37#include "f_printer.c"
37 38
38/*-------------------------------------------------------------------------*/ 39/*-------------------------------------------------------------------------*/