#include "u_printer.h"
-#define PNP_STRING_LEN 1024
#define PRINTER_MINORS 4
#define GET_DEVICE_ID 0
#define GET_PORT_STATUS 1
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:
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);
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 */
if (wIndex != dev->interface)
break;
- *(u8 *)req->buf = dev->printer_status;
+ buf[0] = dev->printer_status;
value = min_t(u16, wLength, 1);
break;
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;
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;
mutex_unlock(&printer_ida_lock);
+ if (opts->pnp_string_allocated)
+ kfree(opts->pnp_string);
kfree(opts);
}
static char product_desc [40] = DRIVER_DESC;
static char serial_num [40] = "1";
-static char pnp_string[PNP_STRING_LEN] =
- "XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;";
+static char *pnp_string =
+ "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;";
/* static strings, in UTF-8 */
static struct usb_string strings [] = {
static int printer_bind(struct usb_composite_dev *cdev)
{
struct f_printer_opts *opts;
- int ret, len;
+ int ret;
fi_printer = usb_get_function_instance("printer");
if (IS_ERR(fi_printer))
return PTR_ERR(fi_printer);
- if (iPNPstring)
- strlcpy(&pnp_string[2], iPNPstring, PNP_STRING_LEN - 2);
-
- len = strlen(pnp_string);
- pnp_string[0] = (len >> 8) & 0xFF;
- pnp_string[1] = len & 0xFF;
-
opts = container_of(fi_printer, struct f_printer_opts, func_inst);
opts->minor = 0;
- memcpy(opts->pnp_string, pnp_string, PNP_STRING_LEN);
opts->q_len = QLEN;
+ if (iPNPstring) {
+ opts->pnp_string = kstrdup(iPNPstring, GFP_KERNEL);
+ if (!opts->pnp_string) {
+ ret = -ENOMEM;
+ goto fail_put_func_inst;
+ }
+ opts->pnp_string_allocated = true;
+ /*
+ * we don't free this memory in case of error
+ * as printer cleanup func will do this for us
+ */
+ } else {
+ opts->pnp_string = pnp_string;
+ }
ret = usb_string_ids_tab(cdev, strings);
if (ret < 0)