diff options
author | Giuseppe Scrivano <giuseppe@southpole.se> | 2011-08-03 18:10:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-04 04:43:30 -0400 |
commit | 36c35416a94f5632c3addad05217ff02c39b3b61 (patch) | |
tree | cd62778aeb57b3958228e2cd325d18fd1cd1cc35 /drivers/net/usb | |
parent | 5ee5a07ce3a54de3d1192f8c9c2378d51a51e3bd (diff) |
cdc_ncm: fix endianness problem.
Fix a misusage of the struct usb_cdc_notification to pass arguments to the
usb_control_msg function. The usb_control_msg function expects host endian
arguments but usb_cdc_notification stores these values as little endian.
Now usb_control_msg is directly invoked with host endian values.
Signed-off-by: Giuseppe Scrivano <giuseppe@southpole.se>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r-- | drivers/net/usb/cdc_ncm.c | 156 |
1 files changed, 56 insertions, 100 deletions
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index fd622a66ebbf..a03336e086d5 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
@@ -53,7 +53,7 @@ | |||
53 | #include <linux/usb/usbnet.h> | 53 | #include <linux/usb/usbnet.h> |
54 | #include <linux/usb/cdc.h> | 54 | #include <linux/usb/cdc.h> |
55 | 55 | ||
56 | #define DRIVER_VERSION "01-June-2011" | 56 | #define DRIVER_VERSION "04-Aug-2011" |
57 | 57 | ||
58 | /* CDC NCM subclass 3.2.1 */ | 58 | /* CDC NCM subclass 3.2.1 */ |
59 | #define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10 | 59 | #define USB_CDC_NCM_NDP16_LENGTH_MIN 0x10 |
@@ -163,35 +163,8 @@ cdc_ncm_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info) | |||
163 | usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info)); | 163 | usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info)); |
164 | } | 164 | } |
165 | 165 | ||
166 | static int | ||
167 | cdc_ncm_do_request(struct cdc_ncm_ctx *ctx, struct usb_cdc_notification *req, | ||
168 | void *data, u16 flags, u16 *actlen, u16 timeout) | ||
169 | { | ||
170 | int err; | ||
171 | |||
172 | err = usb_control_msg(ctx->udev, (req->bmRequestType & USB_DIR_IN) ? | ||
173 | usb_rcvctrlpipe(ctx->udev, 0) : | ||
174 | usb_sndctrlpipe(ctx->udev, 0), | ||
175 | req->bNotificationType, req->bmRequestType, | ||
176 | req->wValue, | ||
177 | req->wIndex, data, | ||
178 | req->wLength, timeout); | ||
179 | |||
180 | if (err < 0) { | ||
181 | if (actlen) | ||
182 | *actlen = 0; | ||
183 | return err; | ||
184 | } | ||
185 | |||
186 | if (actlen) | ||
187 | *actlen = err; | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | 166 | static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) |
193 | { | 167 | { |
194 | struct usb_cdc_notification req; | ||
195 | u32 val; | 168 | u32 val; |
196 | u8 flags; | 169 | u8 flags; |
197 | u8 iface_no; | 170 | u8 iface_no; |
@@ -200,14 +173,14 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | |||
200 | 173 | ||
201 | iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber; | 174 | iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber; |
202 | 175 | ||
203 | req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE; | 176 | err = usb_control_msg(ctx->udev, |
204 | req.bNotificationType = USB_CDC_GET_NTB_PARAMETERS; | 177 | usb_rcvctrlpipe(ctx->udev, 0), |
205 | req.wValue = 0; | 178 | USB_CDC_GET_NTB_PARAMETERS, |
206 | req.wIndex = cpu_to_le16(iface_no); | 179 | USB_TYPE_CLASS | USB_DIR_IN |
207 | req.wLength = cpu_to_le16(sizeof(ctx->ncm_parm)); | 180 | | USB_RECIP_INTERFACE, |
208 | 181 | 0, iface_no, &ctx->ncm_parm, | |
209 | err = cdc_ncm_do_request(ctx, &req, &ctx->ncm_parm, 0, NULL, 1000); | 182 | sizeof(ctx->ncm_parm), 10000); |
210 | if (err) { | 183 | if (err < 0) { |
211 | pr_debug("failed GET_NTB_PARAMETERS\n"); | 184 | pr_debug("failed GET_NTB_PARAMETERS\n"); |
212 | return 1; | 185 | return 1; |
213 | } | 186 | } |
@@ -253,31 +226,26 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | |||
253 | 226 | ||
254 | /* inform device about NTB input size changes */ | 227 | /* inform device about NTB input size changes */ |
255 | if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) { | 228 | if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) { |
256 | req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT | | ||
257 | USB_RECIP_INTERFACE; | ||
258 | req.bNotificationType = USB_CDC_SET_NTB_INPUT_SIZE; | ||
259 | req.wValue = 0; | ||
260 | req.wIndex = cpu_to_le16(iface_no); | ||
261 | 229 | ||
262 | if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) { | 230 | if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) { |
263 | struct usb_cdc_ncm_ndp_input_size ndp_in_sz; | 231 | struct usb_cdc_ncm_ndp_input_size ndp_in_sz; |
264 | 232 | err = usb_control_msg(ctx->udev, | |
265 | req.wLength = 8; | 233 | usb_sndctrlpipe(ctx->udev, 0), |
266 | ndp_in_sz.dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); | 234 | USB_CDC_SET_NTB_INPUT_SIZE, |
267 | ndp_in_sz.wNtbInMaxDatagrams = | 235 | USB_TYPE_CLASS | USB_DIR_OUT |
268 | cpu_to_le16(CDC_NCM_DPT_DATAGRAMS_MAX); | 236 | | USB_RECIP_INTERFACE, |
269 | ndp_in_sz.wReserved = 0; | 237 | 0, iface_no, &ndp_in_sz, 8, 1000); |
270 | err = cdc_ncm_do_request(ctx, &req, &ndp_in_sz, 0, NULL, | ||
271 | 1000); | ||
272 | } else { | 238 | } else { |
273 | __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); | 239 | __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max); |
274 | 240 | err = usb_control_msg(ctx->udev, | |
275 | req.wLength = 4; | 241 | usb_sndctrlpipe(ctx->udev, 0), |
276 | err = cdc_ncm_do_request(ctx, &req, &dwNtbInMaxSize, 0, | 242 | USB_CDC_SET_NTB_INPUT_SIZE, |
277 | NULL, 1000); | 243 | USB_TYPE_CLASS | USB_DIR_OUT |
244 | | USB_RECIP_INTERFACE, | ||
245 | 0, iface_no, &dwNtbInMaxSize, 4, 1000); | ||
278 | } | 246 | } |
279 | 247 | ||
280 | if (err) | 248 | if (err < 0) |
281 | pr_debug("Setting NTB Input Size failed\n"); | 249 | pr_debug("Setting NTB Input Size failed\n"); |
282 | } | 250 | } |
283 | 251 | ||
@@ -332,29 +300,24 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | |||
332 | 300 | ||
333 | /* set CRC Mode */ | 301 | /* set CRC Mode */ |
334 | if (flags & USB_CDC_NCM_NCAP_CRC_MODE) { | 302 | if (flags & USB_CDC_NCM_NCAP_CRC_MODE) { |
335 | req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT | | 303 | err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0), |
336 | USB_RECIP_INTERFACE; | 304 | USB_CDC_SET_CRC_MODE, |
337 | req.bNotificationType = USB_CDC_SET_CRC_MODE; | 305 | USB_TYPE_CLASS | USB_DIR_OUT |
338 | req.wValue = cpu_to_le16(USB_CDC_NCM_CRC_NOT_APPENDED); | 306 | | USB_RECIP_INTERFACE, |
339 | req.wIndex = cpu_to_le16(iface_no); | 307 | USB_CDC_NCM_CRC_NOT_APPENDED, |
340 | req.wLength = 0; | 308 | iface_no, NULL, 0, 1000); |
341 | 309 | if (err < 0) | |
342 | err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000); | ||
343 | if (err) | ||
344 | pr_debug("Setting CRC mode off failed\n"); | 310 | pr_debug("Setting CRC mode off failed\n"); |
345 | } | 311 | } |
346 | 312 | ||
347 | /* set NTB format, if both formats are supported */ | 313 | /* set NTB format, if both formats are supported */ |
348 | if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) { | 314 | if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) { |
349 | req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT | | 315 | err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0), |
350 | USB_RECIP_INTERFACE; | 316 | USB_CDC_SET_NTB_FORMAT, USB_TYPE_CLASS |
351 | req.bNotificationType = USB_CDC_SET_NTB_FORMAT; | 317 | | USB_DIR_OUT | USB_RECIP_INTERFACE, |
352 | req.wValue = cpu_to_le16(USB_CDC_NCM_NTB16_FORMAT); | 318 | USB_CDC_NCM_NTB16_FORMAT, |
353 | req.wIndex = cpu_to_le16(iface_no); | 319 | iface_no, NULL, 0, 1000); |
354 | req.wLength = 0; | 320 | if (err < 0) |
355 | |||
356 | err = cdc_ncm_do_request(ctx, &req, NULL, 0, NULL, 1000); | ||
357 | if (err) | ||
358 | pr_debug("Setting NTB format to 16-bit failed\n"); | 321 | pr_debug("Setting NTB format to 16-bit failed\n"); |
359 | } | 322 | } |
360 | 323 | ||
@@ -364,17 +327,13 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | |||
364 | if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) { | 327 | if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) { |
365 | __le16 max_datagram_size; | 328 | __le16 max_datagram_size; |
366 | u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); | 329 | u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize); |
367 | 330 | err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0), | |
368 | req.bmRequestType = USB_TYPE_CLASS | USB_DIR_IN | | 331 | USB_CDC_GET_MAX_DATAGRAM_SIZE, |
369 | USB_RECIP_INTERFACE; | 332 | USB_TYPE_CLASS | USB_DIR_IN |
370 | req.bNotificationType = USB_CDC_GET_MAX_DATAGRAM_SIZE; | 333 | | USB_RECIP_INTERFACE, |
371 | req.wValue = 0; | 334 | 0, iface_no, &max_datagram_size, |
372 | req.wIndex = cpu_to_le16(iface_no); | 335 | 2, 1000); |
373 | req.wLength = cpu_to_le16(2); | 336 | if (err < 0) { |
374 | |||
375 | err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, 0, NULL, | ||
376 | 1000); | ||
377 | if (err) { | ||
378 | pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n", | 337 | pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n", |
379 | CDC_NCM_MIN_DATAGRAM_SIZE); | 338 | CDC_NCM_MIN_DATAGRAM_SIZE); |
380 | } else { | 339 | } else { |
@@ -395,17 +354,15 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx) | |||
395 | CDC_NCM_MIN_DATAGRAM_SIZE; | 354 | CDC_NCM_MIN_DATAGRAM_SIZE; |
396 | 355 | ||
397 | /* if value changed, update device */ | 356 | /* if value changed, update device */ |
398 | req.bmRequestType = USB_TYPE_CLASS | USB_DIR_OUT | | 357 | err = usb_control_msg(ctx->udev, |
399 | USB_RECIP_INTERFACE; | 358 | usb_sndctrlpipe(ctx->udev, 0), |
400 | req.bNotificationType = USB_CDC_SET_MAX_DATAGRAM_SIZE; | 359 | USB_CDC_SET_MAX_DATAGRAM_SIZE, |
401 | req.wValue = 0; | 360 | USB_TYPE_CLASS | USB_DIR_OUT |
402 | req.wIndex = cpu_to_le16(iface_no); | 361 | | USB_RECIP_INTERFACE, |
403 | req.wLength = 2; | 362 | 0, |
404 | max_datagram_size = cpu_to_le16(ctx->max_datagram_size); | 363 | iface_no, &max_datagram_size, |
405 | 364 | 2, 1000); | |
406 | err = cdc_ncm_do_request(ctx, &req, &max_datagram_size, | 365 | if (err < 0) |
407 | 0, NULL, 1000); | ||
408 | if (err) | ||
409 | pr_debug("SET_MAX_DATAGRAM_SIZE failed\n"); | 366 | pr_debug("SET_MAX_DATAGRAM_SIZE failed\n"); |
410 | } | 367 | } |
411 | 368 | ||
@@ -671,7 +628,7 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb) | |||
671 | u32 rem; | 628 | u32 rem; |
672 | u32 offset; | 629 | u32 offset; |
673 | u32 last_offset; | 630 | u32 last_offset; |
674 | u16 n = 0; | 631 | u16 n = 0, index; |
675 | u8 ready2send = 0; | 632 | u8 ready2send = 0; |
676 | 633 | ||
677 | /* if there is a remaining skb, it gets priority */ | 634 | /* if there is a remaining skb, it gets priority */ |
@@ -859,8 +816,8 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb) | |||
859 | cpu_to_le16(sizeof(ctx->tx_ncm.nth16)); | 816 | cpu_to_le16(sizeof(ctx->tx_ncm.nth16)); |
860 | ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq); | 817 | ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq); |
861 | ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset); | 818 | ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset); |
862 | ctx->tx_ncm.nth16.wNdpIndex = ALIGN(sizeof(struct usb_cdc_ncm_nth16), | 819 | index = ALIGN(sizeof(struct usb_cdc_ncm_nth16), ctx->tx_ndp_modulus); |
863 | ctx->tx_ndp_modulus); | 820 | ctx->tx_ncm.nth16.wNdpIndex = cpu_to_le16(index); |
864 | 821 | ||
865 | memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16)); | 822 | memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16)); |
866 | ctx->tx_seq++; | 823 | ctx->tx_seq++; |
@@ -873,12 +830,11 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb) | |||
873 | ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem); | 830 | ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem); |
874 | ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */ | 831 | ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */ |
875 | 832 | ||
876 | memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex, | 833 | memcpy(((u8 *)skb_out->data) + index, |
877 | &(ctx->tx_ncm.ndp16), | 834 | &(ctx->tx_ncm.ndp16), |
878 | sizeof(ctx->tx_ncm.ndp16)); | 835 | sizeof(ctx->tx_ncm.ndp16)); |
879 | 836 | ||
880 | memcpy(((u8 *)skb_out->data) + ctx->tx_ncm.nth16.wNdpIndex + | 837 | memcpy(((u8 *)skb_out->data) + index + sizeof(ctx->tx_ncm.ndp16), |
881 | sizeof(ctx->tx_ncm.ndp16), | ||
882 | &(ctx->tx_ncm.dpe16), | 838 | &(ctx->tx_ncm.dpe16), |
883 | (ctx->tx_curr_frame_num + 1) * | 839 | (ctx->tx_curr_frame_num + 1) * |
884 | sizeof(struct usb_cdc_ncm_dpe16)); | 840 | sizeof(struct usb_cdc_ncm_dpe16)); |