|
@@ -49,7 +49,6 @@
|
|
|
|
|
|
#include "u_printer.h"
|
|
|
|
|
|
-#define PNP_STRING_LEN 1024
|
|
|
#define PRINTER_MINORS 4
|
|
|
#define GET_DEVICE_ID 0
|
|
|
#define GET_PORT_STATUS 1
|
|
@@ -907,8 +906,7 @@ static bool gprinter_req_match(struct usb_function *f,
|
|
|
switch (ctrl->bRequest) {
|
|
|
case GET_DEVICE_ID:
|
|
|
w_index >>= 8;
|
|
|
- if (w_length <= PNP_STRING_LEN &&
|
|
|
- (USB_DIR_IN & ctrl->bRequestType))
|
|
|
+ if (USB_DIR_IN & ctrl->bRequestType)
|
|
|
break;
|
|
|
return false;
|
|
|
case GET_PORT_STATUS:
|
|
@@ -937,6 +935,7 @@ static int printer_func_setup(struct usb_function *f,
|
|
|
struct printer_dev *dev = func_to_printer(f);
|
|
|
struct usb_composite_dev *cdev = f->config->cdev;
|
|
|
struct usb_request *req = cdev->req;
|
|
|
+ u8 *buf = req->buf;
|
|
|
int value = -EOPNOTSUPP;
|
|
|
u16 wIndex = le16_to_cpu(ctrl->wIndex);
|
|
|
u16 wValue = le16_to_cpu(ctrl->wValue);
|
|
@@ -953,10 +952,16 @@ static int printer_func_setup(struct usb_function *f,
|
|
|
if ((wIndex>>8) != dev->interface)
|
|
|
break;
|
|
|
|
|
|
- value = (dev->pnp_string[0] << 8) | dev->pnp_string[1];
|
|
|
- memcpy(req->buf, dev->pnp_string, value);
|
|
|
+ if (!dev->pnp_string) {
|
|
|
+ value = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ value = strlen(dev->pnp_string);
|
|
|
+ buf[0] = (value >> 8) & 0xFF;
|
|
|
+ buf[1] = value & 0xFF;
|
|
|
+ memcpy(buf + 2, dev->pnp_string, value);
|
|
|
DBG(dev, "1284 PNP String: %x %s\n", value,
|
|
|
- &dev->pnp_string[2]);
|
|
|
+ dev->pnp_string);
|
|
|
break;
|
|
|
|
|
|
case GET_PORT_STATUS: /* Get Port Status */
|
|
@@ -964,7 +969,7 @@ static int printer_func_setup(struct usb_function *f,
|
|
|
if (wIndex != dev->interface)
|
|
|
break;
|
|
|
|
|
|
- *(u8 *)req->buf = dev->printer_status;
|
|
|
+ buf[0] = dev->printer_status;
|
|
|
value = min_t(u16, wLength, 1);
|
|
|
break;
|
|
|
|
|
@@ -1157,10 +1162,21 @@ static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
|
|
|
char *page)
|
|
|
{
|
|
|
struct f_printer_opts *opts = to_f_printer_opts(item);
|
|
|
- int result;
|
|
|
+ int result = 0;
|
|
|
|
|
|
mutex_lock(&opts->lock);
|
|
|
- result = strlcpy(page, opts->pnp_string + 2, PNP_STRING_LEN - 2);
|
|
|
+ if (!opts->pnp_string)
|
|
|
+ goto unlock;
|
|
|
+
|
|
|
+ result = strlcpy(page, opts->pnp_string, PAGE_SIZE);
|
|
|
+ if (result >= PAGE_SIZE) {
|
|
|
+ result = PAGE_SIZE;
|
|
|
+ } else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) {
|
|
|
+ page[result++] = '\n';
|
|
|
+ page[result] = '\0';
|
|
|
+ }
|
|
|
+
|
|
|
+unlock:
|
|
|
mutex_unlock(&opts->lock);
|
|
|
|
|
|
return result;
|
|
@@ -1170,13 +1186,24 @@ static ssize_t f_printer_opts_pnp_string_store(struct config_item *item,
|
|
|
const char *page, size_t len)
|
|
|
{
|
|
|
struct f_printer_opts *opts = to_f_printer_opts(item);
|
|
|
- int result, l;
|
|
|
+ char *new_pnp;
|
|
|
+ int result;
|
|
|
|
|
|
mutex_lock(&opts->lock);
|
|
|
- result = strlcpy(opts->pnp_string + 2, page, PNP_STRING_LEN - 2);
|
|
|
- l = strlen(opts->pnp_string + 2) + 2;
|
|
|
- opts->pnp_string[0] = (l >> 8) & 0xFF;
|
|
|
- opts->pnp_string[1] = l & 0xFF;
|
|
|
+
|
|
|
+ new_pnp = kstrndup(page, len, GFP_KERNEL);
|
|
|
+ if (!new_pnp) {
|
|
|
+ result = -ENOMEM;
|
|
|
+ goto unlock;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opts->pnp_string_allocated)
|
|
|
+ kfree(opts->pnp_string);
|
|
|
+
|
|
|
+ opts->pnp_string_allocated = true;
|
|
|
+ opts->pnp_string = new_pnp;
|
|
|
+ result = len;
|
|
|
+unlock:
|
|
|
mutex_unlock(&opts->lock);
|
|
|
|
|
|
return result;
|
|
@@ -1270,6 +1297,8 @@ static void gprinter_free_inst(struct usb_function_instance *f)
|
|
|
|
|
|
mutex_unlock(&printer_ida_lock);
|
|
|
|
|
|
+ if (opts->pnp_string_allocated)
|
|
|
+ kfree(opts->pnp_string);
|
|
|
kfree(opts);
|
|
|
}
|
|
|
|