aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-printer9
-rw-r--r--Documentation/usb/gadget-testing.txt47
-rw-r--r--drivers/usb/gadget/Kconfig13
-rw-r--r--drivers/usb/gadget/function/f_printer.c130
-rw-r--r--drivers/usb/gadget/function/u_printer.h7
5 files changed, 204 insertions, 2 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-printer b/Documentation/ABI/testing/configfs-usb-gadget-printer
new file mode 100644
index 000000000000..6b0714e3c605
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-usb-gadget-printer
@@ -0,0 +1,9 @@
1What: /config/usb-gadget/gadget/functions/printer.name
2Date: Apr 2015
3KernelVersion: 4.1
4Description:
5 The attributes:
6
7 pnp_string - Data to be passed to the host in pnp string
8 q_len - Number of requests per endpoint
9
diff --git a/Documentation/usb/gadget-testing.txt b/Documentation/usb/gadget-testing.txt
index 076ac7ba7f93..f45b2bf4b41d 100644
--- a/Documentation/usb/gadget-testing.txt
+++ b/Documentation/usb/gadget-testing.txt
@@ -19,6 +19,7 @@ provided by gadgets.
1916. UAC1 function 1916. UAC1 function
2017. UAC2 function 2017. UAC2 function
2118. UVC function 2118. UVC function
2219. PRINTER function
22 23
23 24
241. ACM function 251. ACM function
@@ -726,3 +727,49 @@ with these patches:
726http://www.spinics.net/lists/linux-usb/msg99220.html 727http://www.spinics.net/lists/linux-usb/msg99220.html
727 728
728host: luvcview -f yuv 729host: luvcview -f yuv
730
73119. PRINTER function
732====================
733
734The function is provided by usb_f_printer.ko module.
735
736Function-specific configfs interface
737------------------------------------
738
739The function name to use when creating the function directory is "printer".
740The printer function provides these attributes in its function directory:
741
742 pnp_string - Data to be passed to the host in pnp string
743 q_len - Number of requests per endpoint
744
745Testing the PRINTER function
746----------------------------
747
748The most basic testing:
749
750device: run the gadget
751# ls -l /devices/virtual/usb_printer_gadget/
752
753should show g_printer<number>.
754
755If udev is active, then /dev/g_printer<number> should appear automatically.
756
757host:
758
759If udev is active, then e.g. /dev/usb/lp0 should appear.
760
761host->device transmission:
762
763device:
764# cat /dev/g_printer<number>
765host:
766# cat > /dev/usb/lp0
767
768device->host transmission:
769
770# cat > /dev/g_printer<number>
771host:
772# cat /dev/usb/lp0
773
774More advanced testing can be done with the prn_example
775described in Documentation/usb/gadget-printer.txt.
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 9d507cf98f94..3bb0e67fded2 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -437,6 +437,19 @@ config USB_CONFIGFS_F_UVC
437 device. It provides a userspace API to process UVC control requests 437 device. It provides a userspace API to process UVC control requests
438 and stream video data to the host. 438 and stream video data to the host.
439 439
440config USB_CONFIGFS_F_PRINTER
441 bool "Printer function"
442 select USB_F_PRINTER
443 help
444 The Printer function channels data between the USB host and a
445 userspace program driving the print engine. The user space
446 program reads and writes the device file /dev/g_printer<X> to
447 receive or send printer data. It can use ioctl calls to
448 the device file to get or set printer status.
449
450 For more information, see Documentation/usb/gadget_printer.txt
451 which includes sample code for accessing the device file.
452
440source "drivers/usb/gadget/legacy/Kconfig" 453source "drivers/usb/gadget/legacy/Kconfig"
441 454
442endchoice 455endchoice
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 7afe17d76f17..757fcf070013 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -1140,6 +1140,117 @@ static void printer_func_disable(struct usb_function *f)
1140 spin_unlock_irqrestore(&dev->lock, flags); 1140 spin_unlock_irqrestore(&dev->lock, flags);
1141} 1141}
1142 1142
1143static inline struct f_printer_opts
1144*to_f_printer_opts(struct config_item *item)
1145{
1146 return container_of(to_config_group(item), struct f_printer_opts,
1147 func_inst.group);
1148}
1149
1150CONFIGFS_ATTR_STRUCT(f_printer_opts);
1151CONFIGFS_ATTR_OPS(f_printer_opts);
1152
1153static void printer_attr_release(struct config_item *item)
1154{
1155 struct f_printer_opts *opts = to_f_printer_opts(item);
1156
1157 usb_put_function_instance(&opts->func_inst);
1158}
1159
1160static struct configfs_item_operations printer_item_ops = {
1161 .release = printer_attr_release,
1162 .show_attribute = f_printer_opts_attr_show,
1163 .store_attribute = f_printer_opts_attr_store,
1164};
1165
1166static ssize_t f_printer_opts_pnp_string_show(struct f_printer_opts *opts,
1167 char *page)
1168{
1169 int result;
1170
1171 mutex_lock(&opts->lock);
1172 result = strlcpy(page, opts->pnp_string + 2, PNP_STRING_LEN - 2);
1173 mutex_unlock(&opts->lock);
1174
1175 return result;
1176}
1177
1178static ssize_t f_printer_opts_pnp_string_store(struct f_printer_opts *opts,
1179 const char *page, size_t len)
1180{
1181 int result, l;
1182
1183 mutex_lock(&opts->lock);
1184 result = strlcpy(opts->pnp_string + 2, page, PNP_STRING_LEN - 2);
1185 l = strlen(opts->pnp_string + 2) + 2;
1186 opts->pnp_string[0] = (l >> 8) & 0xFF;
1187 opts->pnp_string[1] = l & 0xFF;
1188 mutex_unlock(&opts->lock);
1189
1190 return result;
1191}
1192
1193static struct f_printer_opts_attribute f_printer_opts_pnp_string =
1194 __CONFIGFS_ATTR(pnp_string, S_IRUGO | S_IWUSR,
1195 f_printer_opts_pnp_string_show,
1196 f_printer_opts_pnp_string_store);
1197
1198static ssize_t f_printer_opts_q_len_show(struct f_printer_opts *opts,
1199 char *page)
1200{
1201 int result;
1202
1203 mutex_lock(&opts->lock);
1204 result = sprintf(page, "%d\n", opts->q_len);
1205 mutex_unlock(&opts->lock);
1206
1207 return result;
1208}
1209
1210static ssize_t f_printer_opts_q_len_store(struct f_printer_opts *opts,
1211 const char *page, size_t len)
1212{
1213 int ret;
1214 u16 num;
1215
1216 mutex_lock(&opts->lock);
1217 if (opts->refcnt) {
1218 ret = -EBUSY;
1219 goto end;
1220 }
1221
1222 ret = kstrtou16(page, 0, &num);
1223 if (ret)
1224 goto end;
1225
1226 if (num > 65535) {
1227 ret = -EINVAL;
1228 goto end;
1229 }
1230
1231 opts->q_len = (unsigned)num;
1232 ret = len;
1233end:
1234 mutex_unlock(&opts->lock);
1235 return ret;
1236}
1237
1238static struct f_printer_opts_attribute f_printer_opts_q_len =
1239 __CONFIGFS_ATTR(q_len, S_IRUGO | S_IWUSR, f_printer_opts_q_len_show,
1240 f_printer_opts_q_len_store);
1241
1242static struct configfs_attribute *printer_attrs[] = {
1243 &f_printer_opts_pnp_string.attr,
1244 &f_printer_opts_q_len.attr,
1245 NULL,
1246};
1247
1248static struct config_item_type printer_func_type = {
1249 .ct_item_ops = &printer_item_ops,
1250 .ct_attrs = printer_attrs,
1251 .ct_owner = THIS_MODULE,
1252};
1253
1143static inline int gprinter_get_minor(void) 1254static inline int gprinter_get_minor(void)
1144{ 1255{
1145 return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL); 1256 return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
@@ -1180,6 +1291,7 @@ static struct usb_function_instance *gprinter_alloc_inst(void)
1180 if (!opts) 1291 if (!opts)
1181 return ERR_PTR(-ENOMEM); 1292 return ERR_PTR(-ENOMEM);
1182 1293
1294 mutex_init(&opts->lock);
1183 opts->func_inst.free_func_inst = gprinter_free_inst; 1295 opts->func_inst.free_func_inst = gprinter_free_inst;
1184 ret = &opts->func_inst; 1296 ret = &opts->func_inst;
1185 1297
@@ -1201,6 +1313,8 @@ static struct usb_function_instance *gprinter_alloc_inst(void)
1201 if (idr_is_empty(&printer_ida.idr)) 1313 if (idr_is_empty(&printer_ida.idr))
1202 gprinter_cleanup(); 1314 gprinter_cleanup();
1203 } 1315 }
1316 config_group_init_type_name(&opts->func_inst.group, "",
1317 &printer_func_type);
1204 1318
1205unlock: 1319unlock:
1206 mutex_unlock(&printer_ida_lock); 1320 mutex_unlock(&printer_ida_lock);
@@ -1210,8 +1324,13 @@ unlock:
1210static void gprinter_free(struct usb_function *f) 1324static void gprinter_free(struct usb_function *f)
1211{ 1325{
1212 struct printer_dev *dev = func_to_printer(f); 1326 struct printer_dev *dev = func_to_printer(f);
1327 struct f_printer_opts *opts;
1213 1328
1329 opts = container_of(f->fi, struct f_printer_opts, func_inst);
1214 kfree(dev); 1330 kfree(dev);
1331 mutex_lock(&opts->lock);
1332 --opts->refcnt;
1333 mutex_unlock(&opts->lock);
1215} 1334}
1216 1335
1217static void printer_func_unbind(struct usb_configuration *c, 1336static void printer_func_unbind(struct usb_configuration *c,
@@ -1265,16 +1384,23 @@ static struct usb_function *gprinter_alloc(struct usb_function_instance *fi)
1265 1384
1266 opts = container_of(fi, struct f_printer_opts, func_inst); 1385 opts = container_of(fi, struct f_printer_opts, func_inst);
1267 1386
1268 if (opts->minor >= minors) 1387 mutex_lock(&opts->lock);
1388 if (opts->minor >= minors) {
1389 mutex_unlock(&opts->lock);
1269 return ERR_PTR(-ENOENT); 1390 return ERR_PTR(-ENOENT);
1391 }
1270 1392
1271 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 1393 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
1272 if (!dev) 1394 if (!dev) {
1395 mutex_unlock(&opts->lock);
1273 return ERR_PTR(-ENOMEM); 1396 return ERR_PTR(-ENOMEM);
1397 }
1274 1398
1399 ++opts->refcnt;
1275 dev->minor = opts->minor; 1400 dev->minor = opts->minor;
1276 dev->pnp_string = opts->pnp_string; 1401 dev->pnp_string = opts->pnp_string;
1277 dev->q_len = opts->q_len; 1402 dev->q_len = opts->q_len;
1403 mutex_unlock(&opts->lock);
1278 1404
1279 dev->function.name = "printer"; 1405 dev->function.name = "printer";
1280 dev->function.bind = printer_func_bind; 1406 dev->function.bind = printer_func_bind;
diff --git a/drivers/usb/gadget/function/u_printer.h b/drivers/usb/gadget/function/u_printer.h
index b2338cacdfe4..0e2c49d4274e 100644
--- a/drivers/usb/gadget/function/u_printer.h
+++ b/drivers/usb/gadget/function/u_printer.h
@@ -25,6 +25,13 @@ struct f_printer_opts {
25 int minor; 25 int minor;
26 char pnp_string[PNP_STRING_LEN]; 26 char pnp_string[PNP_STRING_LEN];
27 unsigned q_len; 27 unsigned q_len;
28
29 /*
30 * Protect the data from concurrent access by read/write
31 * and create symlink/remove symlink
32 */
33 struct mutex lock;
34 int refcnt;
28}; 35};
29 36
30#endif /* U_PRINTER_H */ 37#endif /* U_PRINTER_H */