.disconnect = cp210x_disconnect,
};
-/* Control request types */
-#define REQTYPE_CTL_TO_DEVICE USB_TYPE_VENDOR
-#define REQTYPE_CTL_TO_HOST (USB_DIR_IN|REQTYPE_CTL_TO_DEVICE)
-
-/* Config request types */
-#define REQTYPE_HOST_TO_DEVICE (USB_TYPE_VENDOR|USB_RECIP_INTERFACE)
-#define REQTYPE_DEVICE_TO_HOST (USB_DIR_IN|REQTYPE_HOST_TO_DEVICE)
-
/* Config request codes */
#define CP210X_IFC_ENABLE 0x00
#define CP210X_SET_BAUDDIV 0x01
#define CP210x_PART_CP2102 0x02
#define CP210x_PART_CP2103 0x03
-/* Helper to make usb string size */
-#define USBSTRLEN(x) (x * 2 + 2)
+/* Return the size of the buffer needed to hold a string of len x formatted
+ * for send to CP210X, and its reverse.
+ */
+#define USBSTRLEN(strlen) (strlen * 2 + 2)
+
/* Populates usbstr with: (len) + (0x03) + unicode(str). Each char in str
* takes two bytes in unicode format.
* is the size of the buffer at kbuf.
* Returns the number of bytes used in kbuf.
*/
-static size_t cp210x_usbstr_from_user(char *kbuf, unsigned long ubuf,
- size_t klen)
+static size_t cp210x_usbstr_from_user(char *kbuf,
+ struct cp210x_buffer __user *ubuf, size_t klen)
{
struct cp210x_buffer t;
char *str;
size_t slen;
- if (!kbuf || !ubuf || !klen)
- return 0;
- if (copy_from_user(&t, (struct cp210x_buffer __user *)ubuf, sizeof(t)))
- return 0;
- if (!t.buf || !t.len || USBSTRLEN(t.len) > klen)
+ if (copy_from_user(&t, ubuf, sizeof(t)))
return 0;
slen = (klen - 2) / 2;
+ if (!t.buf || !t.len || t.len > slen)
+ return 0;
if (t.len < slen)
slen = t.len;
str = kbuf + klen - slen;
- if (copy_from_user(str, (u8 __user *)t.buf, slen))
+ if (copy_from_user(str, (__u8 __user *)t.buf, slen))
return 0;
return make_usb_string(kbuf, klen, str, slen);
}
+
/*
* cp210x_ctlmsg
* A generic usb control message interface.
/* Instructing the CP210X to reset seems to work more reliably than
* calling usb_reset_device().
*/
- cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_DEVICE,
+ cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
0x0008, 0x00, NULL, 0);
return 0;
}
_partnum = CP210x_PART_CP2101;
else if (addr == 0x01) {
/* Must query part to determine part number */
- if (cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_HOST,
+ if (cp210x_ctlmsg(port, 0xff,
+ USB_DIR_IN|USB_TYPE_VENDOR,
0x370b, 0x00, &_partnum, 1) != 1)
_partnum = CP210x_PART_UNKNOWN;
}
static inline int cp210x_setu16(struct usb_serial_port *port, int cmd,
unsigned int value)
{
- return cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_DEVICE,
+ return cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
0x3700 | (cmd & 0xff), value, NULL, 0);
}
static int cp210x_setstr(struct usb_serial_port *port, int cmd, char *usbstr)
{
unsigned len = usbstr[0];
- int ret = cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_DEVICE,
+ int ret = cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
0x3700 | (cmd & 0xff), 0, usbstr, len);
dbg("%s - cmd 0x%02x len %d ret %d", __func__, cmd, len, ret);
return ret;
{
dbg("%s - port %d, gpio = 0x%.2x", __func__, port->number, gpio);
- return cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_DEVICE,
+ return cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
0x37e1, ((uint16_t)gpio << 8) | GPIO_MASK, NULL, 0);
}
dbg("%s - port %d, gpiob = 0x%.4x", __func__, port->number, gpio);
- return cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_DEVICE,
+ return cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR,
0x37e1, gpio, NULL, 0);
}
dbg("%s - port %d", __func__, port->number);
- ret = cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_HOST,
+ ret = cp210x_ctlmsg(port, 0xff, USB_DIR_IN|USB_TYPE_VENDOR,
0x00c2, 0, gpio, 1);
dbg("%s - gpio = 0x%.2x (%d)", __func__, *gpio, ret);
lconfig.suspend.lowPower = 0;
lconfig.reset.lowPower = 0;
- ret = cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_DEVICE, 0x370c,
+ ret = cp210x_ctlmsg(port, 0xff, USB_TYPE_VENDOR, 0x370c,
0, &lconfig, sizeof(struct cp210x_port_config));
if (ret == sizeof(struct cp210x_port_config))
return 0;
dbg("%s", __func__);
- ret = cp210x_ctlmsg(port, 0xff, REQTYPE_CTL_TO_HOST,
+ ret = cp210x_ctlmsg(port, 0xff, USB_DIR_IN|USB_TYPE_VENDOR,
0x370c, 0, config, sizeof(struct cp210x_port_config));
if (ret == sizeof(struct cp210x_port_config)) {
/* Words from cp210x are MSB */
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- request, REQTYPE_DEVICE_TO_HOST, 0x0000,
- 0, buf, size, 300);
+ request,
+ USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+ 0x0000, 0, buf, size, 300);
/* Convert data into an array of integers */
for (i = 0; i < length; i++)
if (size > 2) {
result = usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- request, REQTYPE_HOST_TO_DEVICE, 0x0000,
+ usb_sndctrlpipe(serial->dev, 0), request,
+ USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0x0000,
0, buf, size, 300);
} else {
result = usb_control_msg(serial->dev,
- usb_sndctrlpipe(serial->dev, 0),
- request, REQTYPE_HOST_TO_DEVICE, data[0],
+ usb_sndctrlpipe(serial->dev, 0), request,
+ USB_TYPE_VENDOR|USB_RECIP_INTERFACE, data[0],
0, NULL, 0, 300);
}
case CP210x_IOCTL_SETPRODUCT:
{
char usbstr[USBSTRLEN(CP210x_MAX_PRODUCT_STRLEN)];
- size_t len = cp210x_usbstr_from_user(usbstr, arg,
+ size_t len = cp210x_usbstr_from_user(usbstr,
+ (struct cp210x_buffer __user *)arg,
sizeof(usbstr));
if (len && cp210x_setstr(port, 0x03, usbstr) == len)
return 0;
case CP210x_IOCTL_SETSERIAL:
{
char usbstr[USBSTRLEN(CP210x_MAX_SERIAL_STRLEN)];
- size_t len = cp210x_usbstr_from_user(usbstr, arg,
+ size_t len = cp210x_usbstr_from_user(usbstr,
+ (struct cp210x_buffer __user *)arg,
sizeof(usbstr));
if (len && cp210x_setstr(port, 0x04, usbstr) == len)
return 0;