Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: printer: Remove pnp_string static buffer

pnp string is usually much shorter than 1k so let's stop wasting 1k of
memory for its buffer and make it dynamically alocated.
This also removes 1k len limitation for pnp_string and
adds a new line after string content if required.

Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>

authored by

Krzysztof Opasiak and committed by
Felipe Balbi
fdc01cc2 00b6c62e

+62 -28
+43 -14
drivers/usb/gadget/function/f_printer.c
··· 49 49 50 50 #include "u_printer.h" 51 51 52 - #define PNP_STRING_LEN 1024 53 52 #define PRINTER_MINORS 4 54 53 #define GET_DEVICE_ID 0 55 54 #define GET_PORT_STATUS 1 ··· 906 907 switch (ctrl->bRequest) { 907 908 case GET_DEVICE_ID: 908 909 w_index >>= 8; 909 - if (w_length <= PNP_STRING_LEN && 910 - (USB_DIR_IN & ctrl->bRequestType)) 910 + if (USB_DIR_IN & ctrl->bRequestType) 911 911 break; 912 912 return false; 913 913 case GET_PORT_STATUS: ··· 935 937 struct printer_dev *dev = func_to_printer(f); 936 938 struct usb_composite_dev *cdev = f->config->cdev; 937 939 struct usb_request *req = cdev->req; 940 + u8 *buf = req->buf; 938 941 int value = -EOPNOTSUPP; 939 942 u16 wIndex = le16_to_cpu(ctrl->wIndex); 940 943 u16 wValue = le16_to_cpu(ctrl->wValue); ··· 952 953 if ((wIndex>>8) != dev->interface) 953 954 break; 954 955 955 - value = (dev->pnp_string[0] << 8) | dev->pnp_string[1]; 956 - memcpy(req->buf, dev->pnp_string, value); 956 + if (!dev->pnp_string) { 957 + value = 0; 958 + break; 959 + } 960 + value = strlen(dev->pnp_string); 961 + buf[0] = (value >> 8) & 0xFF; 962 + buf[1] = value & 0xFF; 963 + memcpy(buf + 2, dev->pnp_string, value); 957 964 DBG(dev, "1284 PNP String: %x %s\n", value, 958 - &dev->pnp_string[2]); 965 + dev->pnp_string); 959 966 break; 960 967 961 968 case GET_PORT_STATUS: /* Get Port Status */ ··· 969 964 if (wIndex != dev->interface) 970 965 break; 971 966 972 - *(u8 *)req->buf = dev->printer_status; 967 + buf[0] = dev->printer_status; 973 968 value = min_t(u16, wLength, 1); 974 969 break; 975 970 ··· 1162 1157 char *page) 1163 1158 { 1164 1159 struct f_printer_opts *opts = to_f_printer_opts(item); 1165 - int result; 1160 + int result = 0; 1166 1161 1167 1162 mutex_lock(&opts->lock); 1168 - result = strlcpy(page, opts->pnp_string + 2, PNP_STRING_LEN - 2); 1163 + if (!opts->pnp_string) 1164 + goto unlock; 1165 + 1166 + result = strlcpy(page, opts->pnp_string, PAGE_SIZE); 1167 + if (result >= PAGE_SIZE) { 1168 + result = PAGE_SIZE; 1169 + } else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) { 1170 + page[result++] = '\n'; 1171 + page[result] = '\0'; 1172 + } 1173 + 1174 + unlock: 1169 1175 mutex_unlock(&opts->lock); 1170 1176 1171 1177 return result; ··· 1186 1170 const char *page, size_t len) 1187 1171 { 1188 1172 struct f_printer_opts *opts = to_f_printer_opts(item); 1189 - int result, l; 1173 + char *new_pnp; 1174 + int result; 1190 1175 1191 1176 mutex_lock(&opts->lock); 1192 - result = strlcpy(opts->pnp_string + 2, page, PNP_STRING_LEN - 2); 1193 - l = strlen(opts->pnp_string + 2) + 2; 1194 - opts->pnp_string[0] = (l >> 8) & 0xFF; 1195 - opts->pnp_string[1] = l & 0xFF; 1177 + 1178 + new_pnp = kstrndup(page, len, GFP_KERNEL); 1179 + if (!new_pnp) { 1180 + result = -ENOMEM; 1181 + goto unlock; 1182 + } 1183 + 1184 + if (opts->pnp_string_allocated) 1185 + kfree(opts->pnp_string); 1186 + 1187 + opts->pnp_string_allocated = true; 1188 + opts->pnp_string = new_pnp; 1189 + result = len; 1190 + unlock: 1196 1191 mutex_unlock(&opts->lock); 1197 1192 1198 1193 return result; ··· 1297 1270 1298 1271 mutex_unlock(&printer_ida_lock); 1299 1272 1273 + if (opts->pnp_string_allocated) 1274 + kfree(opts->pnp_string); 1300 1275 kfree(opts); 1301 1276 } 1302 1277
+2 -3
drivers/usb/gadget/function/u_printer.h
··· 18 18 19 19 #include <linux/usb/composite.h> 20 20 21 - #define PNP_STRING_LEN 1024 22 - 23 21 struct f_printer_opts { 24 22 struct usb_function_instance func_inst; 25 23 int minor; 26 - char pnp_string[PNP_STRING_LEN]; 24 + char *pnp_string; 25 + bool pnp_string_allocated; 27 26 unsigned q_len; 28 27 29 28 /*
+17 -11
drivers/usb/gadget/legacy/printer.c
··· 88 88 89 89 static char product_desc [40] = DRIVER_DESC; 90 90 static char serial_num [40] = "1"; 91 - static char pnp_string[PNP_STRING_LEN] = 92 - "XXMFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"; 91 + static char *pnp_string = 92 + "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"; 93 93 94 94 /* static strings, in UTF-8 */ 95 95 static struct usb_string strings [] = { ··· 143 143 static int printer_bind(struct usb_composite_dev *cdev) 144 144 { 145 145 struct f_printer_opts *opts; 146 - int ret, len; 146 + int ret; 147 147 148 148 fi_printer = usb_get_function_instance("printer"); 149 149 if (IS_ERR(fi_printer)) 150 150 return PTR_ERR(fi_printer); 151 151 152 - if (iPNPstring) 153 - strlcpy(&pnp_string[2], iPNPstring, PNP_STRING_LEN - 2); 154 - 155 - len = strlen(pnp_string); 156 - pnp_string[0] = (len >> 8) & 0xFF; 157 - pnp_string[1] = len & 0xFF; 158 - 159 152 opts = container_of(fi_printer, struct f_printer_opts, func_inst); 160 153 opts->minor = 0; 161 - memcpy(opts->pnp_string, pnp_string, PNP_STRING_LEN); 162 154 opts->q_len = QLEN; 155 + if (iPNPstring) { 156 + opts->pnp_string = kstrdup(iPNPstring, GFP_KERNEL); 157 + if (!opts->pnp_string) { 158 + ret = -ENOMEM; 159 + goto fail_put_func_inst; 160 + } 161 + opts->pnp_string_allocated = true; 162 + /* 163 + * we don't free this memory in case of error 164 + * as printer cleanup func will do this for us 165 + */ 166 + } else { 167 + opts->pnp_string = pnp_string; 168 + } 163 169 164 170 ret = usb_string_ids_tab(cdev, strings); 165 171 if (ret < 0)