diff options
-rw-r--r-- | drivers/media/dvb/dvb-usb/af9035.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/drivers/media/dvb/dvb-usb/af9035.c b/drivers/media/dvb/dvb-usb/af9035.c index 6a83120afcd6..92d27aa80800 100644 --- a/drivers/media/dvb/dvb-usb/af9035.c +++ b/drivers/media/dvb/dvb-usb/af9035.c | |||
@@ -36,6 +36,22 @@ static struct af9033_config af9035_af9033_config[] = { | |||
36 | } | 36 | } |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static u16 af9035_checksum(const u8 *buf, size_t len) | ||
40 | { | ||
41 | size_t i; | ||
42 | u16 checksum = 0; | ||
43 | |||
44 | for (i = 1; i < len; i++) { | ||
45 | if (i % 2) | ||
46 | checksum += buf[i] << 8; | ||
47 | else | ||
48 | checksum += buf[i]; | ||
49 | } | ||
50 | checksum = ~checksum; | ||
51 | |||
52 | return checksum; | ||
53 | } | ||
54 | |||
39 | static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) | 55 | static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) |
40 | { | 56 | { |
41 | #define BUF_LEN 63 | 57 | #define BUF_LEN 63 |
@@ -44,11 +60,11 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) | |||
44 | #define CHECKSUM_LEN 2 | 60 | #define CHECKSUM_LEN 2 |
45 | #define USB_TIMEOUT 2000 | 61 | #define USB_TIMEOUT 2000 |
46 | 62 | ||
47 | int ret, i, act_len; | 63 | int ret, act_len; |
48 | u8 buf[BUF_LEN]; | 64 | u8 buf[BUF_LEN]; |
49 | u32 msg_len; | 65 | u32 msg_len; |
50 | static u8 seq; /* packet sequence number */ | 66 | static u8 seq; /* packet sequence number */ |
51 | u16 checksum = 0; | 67 | u16 checksum, tmpsum; |
52 | 68 | ||
53 | /* buffer overflow check */ | 69 | /* buffer overflow check */ |
54 | if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || | 70 | if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) || |
@@ -69,14 +85,7 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) | |||
69 | memcpy(&buf[4], req->wbuf, req->wlen); | 85 | memcpy(&buf[4], req->wbuf, req->wlen); |
70 | 86 | ||
71 | /* calc and add checksum */ | 87 | /* calc and add checksum */ |
72 | for (i = 1; i < buf[0]-1; i++) { | 88 | checksum = af9035_checksum(buf, buf[0] - 1); |
73 | if (i % 2) | ||
74 | checksum += buf[i] << 8; | ||
75 | else | ||
76 | checksum += buf[i]; | ||
77 | } | ||
78 | checksum = ~checksum; | ||
79 | |||
80 | buf[buf[0]-1] = (checksum >> 8); | 89 | buf[buf[0]-1] = (checksum >> 8); |
81 | buf[buf[0]-0] = (checksum & 0xff); | 90 | buf[buf[0]-0] = (checksum & 0xff); |
82 | 91 | ||
@@ -106,7 +115,23 @@ static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req) | |||
106 | ret = -EIO; | 115 | ret = -EIO; |
107 | goto err_mutex_unlock; | 116 | goto err_mutex_unlock; |
108 | } | 117 | } |
118 | if (act_len != msg_len) { | ||
119 | err("recv bulk message truncated (%d != %u)\n", | ||
120 | act_len, (unsigned int)msg_len); | ||
121 | ret = -EIO; | ||
122 | goto err_mutex_unlock; | ||
123 | } | ||
109 | 124 | ||
125 | /* verify checksum */ | ||
126 | checksum = af9035_checksum(buf, act_len - 2); | ||
127 | tmpsum = (buf[act_len - 2] << 8) | buf[act_len - 1]; | ||
128 | if (tmpsum != checksum) { | ||
129 | err("%s: command=%02X checksum mismatch (%04X != %04X)\n", | ||
130 | __func__, req->cmd, | ||
131 | (unsigned int)tmpsum, (unsigned int)checksum); | ||
132 | ret = -EIO; | ||
133 | goto err_mutex_unlock; | ||
134 | } | ||
110 | /* check status */ | 135 | /* check status */ |
111 | if (buf[2]) { | 136 | if (buf[2]) { |
112 | pr_debug("%s: command=%02x failed fw error=%d\n", __func__, | 137 | pr_debug("%s: command=%02x failed fw error=%d\n", __func__, |