aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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/*-------------------------------------------------------------------------*/