uboot/drivers/usb/gadget/rndis.c
<<
>>
Prefs
   1/*
   2 * RNDIS MSG parser
   3 *
   4 * Authors:     Benedikt Spranger, Pengutronix
   5 *              Robert Schwebel, Pengutronix
   6 *
   7 *              This software was originally developed in conformance with
   8 *              Microsoft's Remote NDIS Specification License Agreement.
   9 *
  10 * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
  11 *              Fixed message length bug in init_response
  12 *
  13 * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
  14 *              Fixed rndis_rm_hdr length bug.
  15 *
  16 * Copyright (C) 2004 by David Brownell
  17 *              updates to merge with Linux 2.6, better match RNDIS spec
  18 *
  19 * SPDX-License-Identifier:     GPL-2.0
  20 */
  21
  22#include <common.h>
  23#include <net.h>
  24#include <malloc.h>
  25#include <linux/types.h>
  26#include <linux/list.h>
  27#include <linux/netdevice.h>
  28
  29#include <asm/byteorder.h>
  30#include <asm/unaligned.h>
  31#include <linux/errno.h>
  32
  33#undef  RNDIS_PM
  34#undef  RNDIS_WAKEUP
  35#undef  VERBOSE
  36
  37#include "rndis.h"
  38
  39#define ETH_ALEN        6               /* Octets in one ethernet addr   */
  40#define ETH_HLEN        14              /* Total octets in header.       */
  41#define ETH_ZLEN        60              /* Min. octets in frame sans FCS */
  42#define ETH_DATA_LEN    1500            /* Max. octets in payload        */
  43#define ETH_FRAME_LEN   PKTSIZE_ALIGN   /* Max. octets in frame sans FCS */
  44
  45/*
  46 * The driver for your USB chip needs to support ep0 OUT to work with
  47 * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
  48 *
  49 * Windows hosts need an INF file like Documentation/usb/linux.inf
  50 * and will be happier if you provide the host_addr module parameter.
  51 */
  52
  53#define RNDIS_MAX_CONFIGS       1
  54
  55static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS];
  56
  57/* Driver Version */
  58static const __le32 rndis_driver_version = __constant_cpu_to_le32(1);
  59
  60/* Function Prototypes */
  61static rndis_resp_t *rndis_add_response(int configNr, u32 length);
  62
  63
  64/* supported OIDs */
  65static const u32 oid_supported_list[] = {
  66        /* the general stuff */
  67        OID_GEN_SUPPORTED_LIST,
  68        OID_GEN_HARDWARE_STATUS,
  69        OID_GEN_MEDIA_SUPPORTED,
  70        OID_GEN_MEDIA_IN_USE,
  71        OID_GEN_MAXIMUM_FRAME_SIZE,
  72        OID_GEN_LINK_SPEED,
  73        OID_GEN_TRANSMIT_BLOCK_SIZE,
  74        OID_GEN_RECEIVE_BLOCK_SIZE,
  75        OID_GEN_VENDOR_ID,
  76        OID_GEN_VENDOR_DESCRIPTION,
  77        OID_GEN_VENDOR_DRIVER_VERSION,
  78        OID_GEN_CURRENT_PACKET_FILTER,
  79        OID_GEN_MAXIMUM_TOTAL_SIZE,
  80        OID_GEN_MEDIA_CONNECT_STATUS,
  81        OID_GEN_PHYSICAL_MEDIUM,
  82#if 0
  83        OID_GEN_RNDIS_CONFIG_PARAMETER,
  84#endif
  85
  86        /* the statistical stuff */
  87        OID_GEN_XMIT_OK,
  88        OID_GEN_RCV_OK,
  89        OID_GEN_XMIT_ERROR,
  90        OID_GEN_RCV_ERROR,
  91        OID_GEN_RCV_NO_BUFFER,
  92#ifdef  RNDIS_OPTIONAL_STATS
  93        OID_GEN_DIRECTED_BYTES_XMIT,
  94        OID_GEN_DIRECTED_FRAMES_XMIT,
  95        OID_GEN_MULTICAST_BYTES_XMIT,
  96        OID_GEN_MULTICAST_FRAMES_XMIT,
  97        OID_GEN_BROADCAST_BYTES_XMIT,
  98        OID_GEN_BROADCAST_FRAMES_XMIT,
  99        OID_GEN_DIRECTED_BYTES_RCV,
 100        OID_GEN_DIRECTED_FRAMES_RCV,
 101        OID_GEN_MULTICAST_BYTES_RCV,
 102        OID_GEN_MULTICAST_FRAMES_RCV,
 103        OID_GEN_BROADCAST_BYTES_RCV,
 104        OID_GEN_BROADCAST_FRAMES_RCV,
 105        OID_GEN_RCV_CRC_ERROR,
 106        OID_GEN_TRANSMIT_QUEUE_LENGTH,
 107#endif  /* RNDIS_OPTIONAL_STATS */
 108
 109        /* mandatory 802.3 */
 110        /* the general stuff */
 111        OID_802_3_PERMANENT_ADDRESS,
 112        OID_802_3_CURRENT_ADDRESS,
 113        OID_802_3_MULTICAST_LIST,
 114        OID_802_3_MAC_OPTIONS,
 115        OID_802_3_MAXIMUM_LIST_SIZE,
 116
 117        /* the statistical stuff */
 118        OID_802_3_RCV_ERROR_ALIGNMENT,
 119        OID_802_3_XMIT_ONE_COLLISION,
 120        OID_802_3_XMIT_MORE_COLLISIONS,
 121#ifdef  RNDIS_OPTIONAL_STATS
 122        OID_802_3_XMIT_DEFERRED,
 123        OID_802_3_XMIT_MAX_COLLISIONS,
 124        OID_802_3_RCV_OVERRUN,
 125        OID_802_3_XMIT_UNDERRUN,
 126        OID_802_3_XMIT_HEARTBEAT_FAILURE,
 127        OID_802_3_XMIT_TIMES_CRS_LOST,
 128        OID_802_3_XMIT_LATE_COLLISIONS,
 129#endif  /* RNDIS_OPTIONAL_STATS */
 130
 131#ifdef  RNDIS_PM
 132        /* PM and wakeup are mandatory for USB: */
 133
 134        /* power management */
 135        OID_PNP_CAPABILITIES,
 136        OID_PNP_QUERY_POWER,
 137        OID_PNP_SET_POWER,
 138
 139#ifdef  RNDIS_WAKEUP
 140        /* wake up host */
 141        OID_PNP_ENABLE_WAKE_UP,
 142        OID_PNP_ADD_WAKE_UP_PATTERN,
 143        OID_PNP_REMOVE_WAKE_UP_PATTERN,
 144#endif  /* RNDIS_WAKEUP */
 145#endif  /* RNDIS_PM */
 146};
 147
 148
 149/* NDIS Functions */
 150static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf,
 151                                unsigned buf_len, rndis_resp_t *r)
 152{
 153        int                             retval = -ENOTSUPP;
 154        u32                             length = 4;     /* usually */
 155        __le32                          *outbuf;
 156        int                             i, count;
 157        rndis_query_cmplt_type          *resp;
 158        rndis_params                    *params;
 159
 160        if (!r)
 161                return -ENOMEM;
 162        resp = (rndis_query_cmplt_type *) r->buf;
 163
 164        if (!resp)
 165                return -ENOMEM;
 166
 167#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 168        if (buf_len) {
 169                debug("query OID %08x value, len %d:\n", OID, buf_len);
 170                for (i = 0; i < buf_len; i += 16) {
 171                        debug("%03d: %08x %08x %08x %08x\n", i,
 172                                get_unaligned_le32(&buf[i]),
 173                                get_unaligned_le32(&buf[i + 4]),
 174                                get_unaligned_le32(&buf[i + 8]),
 175                                get_unaligned_le32(&buf[i + 12]));
 176                }
 177        }
 178#endif
 179
 180        /* response goes here, right after the header */
 181        outbuf = (__le32 *) &resp[1];
 182        resp->InformationBufferOffset = __constant_cpu_to_le32(16);
 183
 184        params = &rndis_per_dev_params[configNr];
 185        switch (OID) {
 186
 187        /* general oids (table 4-1) */
 188
 189        /* mandatory */
 190        case OID_GEN_SUPPORTED_LIST:
 191                debug("%s: OID_GEN_SUPPORTED_LIST\n", __func__);
 192                length = sizeof(oid_supported_list);
 193                count  = length / sizeof(u32);
 194                for (i = 0; i < count; i++)
 195                        outbuf[i] = cpu_to_le32(oid_supported_list[i]);
 196                retval = 0;
 197                break;
 198
 199        /* mandatory */
 200        case OID_GEN_HARDWARE_STATUS:
 201                debug("%s: OID_GEN_HARDWARE_STATUS\n", __func__);
 202                /*
 203                 * Bogus question!
 204                 * Hardware must be ready to receive high level protocols.
 205                 * BTW:
 206                 * reddite ergo quae sunt Caesaris Caesari
 207                 * et quae sunt Dei Deo!
 208                 */
 209                *outbuf = __constant_cpu_to_le32(0);
 210                retval = 0;
 211                break;
 212
 213        /* mandatory */
 214        case OID_GEN_MEDIA_SUPPORTED:
 215                debug("%s: OID_GEN_MEDIA_SUPPORTED\n", __func__);
 216                *outbuf = cpu_to_le32(params->medium);
 217                retval = 0;
 218                break;
 219
 220        /* mandatory */
 221        case OID_GEN_MEDIA_IN_USE:
 222                debug("%s: OID_GEN_MEDIA_IN_USE\n", __func__);
 223                /* one medium, one transport... (maybe you do it better) */
 224                *outbuf = cpu_to_le32(params->medium);
 225                retval = 0;
 226                break;
 227
 228        /* mandatory */
 229        case OID_GEN_MAXIMUM_FRAME_SIZE:
 230                debug("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__);
 231                if (params->dev) {
 232                        *outbuf = cpu_to_le32(params->mtu);
 233                        retval = 0;
 234                }
 235                break;
 236
 237        /* mandatory */
 238        case OID_GEN_LINK_SPEED:
 239#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 240                debug("%s: OID_GEN_LINK_SPEED\n", __func__);
 241#endif
 242                if (params->media_state == NDIS_MEDIA_STATE_DISCONNECTED)
 243                        *outbuf = __constant_cpu_to_le32(0);
 244                else
 245                        *outbuf = cpu_to_le32(params->speed);
 246                retval = 0;
 247                break;
 248
 249        /* mandatory */
 250        case OID_GEN_TRANSMIT_BLOCK_SIZE:
 251                debug("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__);
 252                if (params->dev) {
 253                        *outbuf = cpu_to_le32(params->mtu);
 254                        retval = 0;
 255                }
 256                break;
 257
 258        /* mandatory */
 259        case OID_GEN_RECEIVE_BLOCK_SIZE:
 260                debug("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__);
 261                if (params->dev) {
 262                        *outbuf = cpu_to_le32(params->mtu);
 263                        retval = 0;
 264                }
 265                break;
 266
 267        /* mandatory */
 268        case OID_GEN_VENDOR_ID:
 269                debug("%s: OID_GEN_VENDOR_ID\n", __func__);
 270                *outbuf = cpu_to_le32(params->vendorID);
 271                retval = 0;
 272                break;
 273
 274        /* mandatory */
 275        case OID_GEN_VENDOR_DESCRIPTION:
 276                debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
 277                length = strlen(params->vendorDescr);
 278                memcpy(outbuf, params->vendorDescr, length);
 279                retval = 0;
 280                break;
 281
 282        case OID_GEN_VENDOR_DRIVER_VERSION:
 283                debug("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __func__);
 284                /* Created as LE */
 285                *outbuf = rndis_driver_version;
 286                retval = 0;
 287                break;
 288
 289        /* mandatory */
 290        case OID_GEN_CURRENT_PACKET_FILTER:
 291                debug("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __func__);
 292                *outbuf = cpu_to_le32(*params->filter);
 293                retval = 0;
 294                break;
 295
 296        /* mandatory */
 297        case OID_GEN_MAXIMUM_TOTAL_SIZE:
 298                debug("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__);
 299                *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
 300                retval = 0;
 301                break;
 302
 303        /* mandatory */
 304        case OID_GEN_MEDIA_CONNECT_STATUS:
 305#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 306                debug("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __func__);
 307#endif
 308                *outbuf = cpu_to_le32(params->media_state);
 309                retval = 0;
 310                break;
 311
 312        case OID_GEN_PHYSICAL_MEDIUM:
 313                debug("%s: OID_GEN_PHYSICAL_MEDIUM\n", __func__);
 314                *outbuf = __constant_cpu_to_le32(0);
 315                retval = 0;
 316                break;
 317
 318        /*
 319         * The RNDIS specification is incomplete/wrong.   Some versions
 320         * of MS-Windows expect OIDs that aren't specified there.  Other
 321         * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
 322         */
 323        case OID_GEN_MAC_OPTIONS:               /* from WinME */
 324                debug("%s: OID_GEN_MAC_OPTIONS\n", __func__);
 325                *outbuf = __constant_cpu_to_le32(
 326                                  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
 327                                | NDIS_MAC_OPTION_FULL_DUPLEX);
 328                retval = 0;
 329                break;
 330
 331        /* statistics OIDs (table 4-2) */
 332
 333        /* mandatory */
 334        case OID_GEN_XMIT_OK:
 335#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 336                debug("%s: OID_GEN_XMIT_OK\n", __func__);
 337#endif
 338                if (params->stats) {
 339                        *outbuf = cpu_to_le32(
 340                                        params->stats->tx_packets -
 341                                        params->stats->tx_errors -
 342                                        params->stats->tx_dropped);
 343                        retval = 0;
 344                }
 345                break;
 346
 347        /* mandatory */
 348        case OID_GEN_RCV_OK:
 349#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 350                debug("%s: OID_GEN_RCV_OK\n", __func__);
 351#endif
 352                if (params->stats) {
 353                        *outbuf = cpu_to_le32(
 354                                        params->stats->rx_packets -
 355                                        params->stats->rx_errors -
 356                                        params->stats->rx_dropped);
 357                        retval = 0;
 358                }
 359                break;
 360
 361        /* mandatory */
 362        case OID_GEN_XMIT_ERROR:
 363#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 364                debug("%s: OID_GEN_XMIT_ERROR\n", __func__);
 365#endif
 366                if (params->stats) {
 367                        *outbuf = cpu_to_le32(params->stats->tx_errors);
 368                        retval = 0;
 369                }
 370                break;
 371
 372        /* mandatory */
 373        case OID_GEN_RCV_ERROR:
 374#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 375                debug("%s: OID_GEN_RCV_ERROR\n", __func__);
 376#endif
 377                if (params->stats) {
 378                        *outbuf = cpu_to_le32(params->stats->rx_errors);
 379                        retval = 0;
 380                }
 381                break;
 382
 383        /* mandatory */
 384        case OID_GEN_RCV_NO_BUFFER:
 385                debug("%s: OID_GEN_RCV_NO_BUFFER\n", __func__);
 386                if (params->stats) {
 387                        *outbuf = cpu_to_le32(params->stats->rx_dropped);
 388                        retval = 0;
 389                }
 390                break;
 391
 392#ifdef  RNDIS_OPTIONAL_STATS
 393        case OID_GEN_DIRECTED_BYTES_XMIT:
 394                debug("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __func__);
 395                /*
 396                 * Aunt Tilly's size of shoes
 397                 * minus antarctica count of penguins
 398                 * divided by weight of Alpha Centauri
 399                 */
 400                if (params->stats) {
 401                        *outbuf = cpu_to_le32(
 402                                        (params->stats->tx_packets -
 403                                         params->stats->tx_errors -
 404                                         params->stats->tx_dropped)
 405                                        * 123);
 406                        retval = 0;
 407                }
 408                break;
 409
 410        case OID_GEN_DIRECTED_FRAMES_XMIT:
 411                debug("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __func__);
 412                /* dito */
 413                if (params->stats) {
 414                        *outbuf = cpu_to_le32(
 415                                        (params->stats->tx_packets -
 416                                         params->stats->tx_errors -
 417                                         params->stats->tx_dropped)
 418                                        / 123);
 419                        retval = 0;
 420                }
 421                break;
 422
 423        case OID_GEN_MULTICAST_BYTES_XMIT:
 424                debug("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __func__);
 425                if (params->stats) {
 426                        *outbuf = cpu_to_le32(params->stats->multicast * 1234);
 427                        retval = 0;
 428                }
 429                break;
 430
 431        case OID_GEN_MULTICAST_FRAMES_XMIT:
 432                debug("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __func__);
 433                if (params->stats) {
 434                        *outbuf = cpu_to_le32(params->stats->multicast);
 435                        retval = 0;
 436                }
 437                break;
 438
 439        case OID_GEN_BROADCAST_BYTES_XMIT:
 440                debug("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __func__);
 441                if (params->stats) {
 442                        *outbuf = cpu_to_le32(params->stats->tx_packets/42*255);
 443                        retval = 0;
 444                }
 445                break;
 446
 447        case OID_GEN_BROADCAST_FRAMES_XMIT:
 448                debug("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __func__);
 449                if (params->stats) {
 450                        *outbuf = cpu_to_le32(params->stats->tx_packets / 42);
 451                        retval = 0;
 452                }
 453                break;
 454
 455        case OID_GEN_DIRECTED_BYTES_RCV:
 456                debug("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __func__);
 457                *outbuf = __constant_cpu_to_le32(0);
 458                retval = 0;
 459                break;
 460
 461        case OID_GEN_DIRECTED_FRAMES_RCV:
 462                debug("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __func__);
 463                *outbuf = __constant_cpu_to_le32(0);
 464                retval = 0;
 465                break;
 466
 467        case OID_GEN_MULTICAST_BYTES_RCV:
 468                debug("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __func__);
 469                if (params->stats) {
 470                        *outbuf = cpu_to_le32(params->stats->multicast * 1111);
 471                        retval = 0;
 472                }
 473                break;
 474
 475        case OID_GEN_MULTICAST_FRAMES_RCV:
 476                debug("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __func__);
 477                if (params->stats) {
 478                        *outbuf = cpu_to_le32(params->stats->multicast);
 479                        retval = 0;
 480                }
 481                break;
 482
 483        case OID_GEN_BROADCAST_BYTES_RCV:
 484                debug("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __func__);
 485                if (params->stats) {
 486                        *outbuf = cpu_to_le32(params->stats->rx_packets/42*255);
 487                        retval = 0;
 488                }
 489                break;
 490
 491        case OID_GEN_BROADCAST_FRAMES_RCV:
 492                debug("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __func__);
 493                if (params->stats) {
 494                        *outbuf = cpu_to_le32(params->stats->rx_packets / 42);
 495                        retval = 0;
 496                }
 497                break;
 498
 499        case OID_GEN_RCV_CRC_ERROR:
 500                debug("%s: OID_GEN_RCV_CRC_ERROR\n", __func__);
 501                if (params->stats) {
 502                        *outbuf = cpu_to_le32(params->stats->rx_crc_errors);
 503                        retval = 0;
 504                }
 505                break;
 506
 507        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
 508                debug("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __func__);
 509                *outbuf = __constant_cpu_to_le32(0);
 510                retval = 0;
 511                break;
 512#endif  /* RNDIS_OPTIONAL_STATS */
 513
 514        /* ieee802.3 OIDs (table 4-3) */
 515
 516        /* mandatory */
 517        case OID_802_3_PERMANENT_ADDRESS:
 518                debug("%s: OID_802_3_PERMANENT_ADDRESS\n", __func__);
 519                if (params->dev) {
 520                        length = ETH_ALEN;
 521                        memcpy(outbuf, params->host_mac, length);
 522                        retval = 0;
 523                }
 524                break;
 525
 526        /* mandatory */
 527        case OID_802_3_CURRENT_ADDRESS:
 528                debug("%s: OID_802_3_CURRENT_ADDRESS\n", __func__);
 529                if (params->dev) {
 530                        length = ETH_ALEN;
 531                        memcpy(outbuf, params->host_mac, length);
 532                        retval = 0;
 533                }
 534                break;
 535
 536        /* mandatory */
 537        case OID_802_3_MULTICAST_LIST:
 538                debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 539                /* Multicast base address only */
 540                *outbuf = __constant_cpu_to_le32(0xE0000000);
 541                retval = 0;
 542                break;
 543
 544        /* mandatory */
 545        case OID_802_3_MAXIMUM_LIST_SIZE:
 546                debug("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __func__);
 547                /* Multicast base address only */
 548                *outbuf = __constant_cpu_to_le32(1);
 549                retval = 0;
 550                break;
 551
 552        case OID_802_3_MAC_OPTIONS:
 553                debug("%s: OID_802_3_MAC_OPTIONS\n", __func__);
 554                break;
 555
 556        /* ieee802.3 statistics OIDs (table 4-4) */
 557
 558        /* mandatory */
 559        case OID_802_3_RCV_ERROR_ALIGNMENT:
 560                debug("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__);
 561                if (params->stats) {
 562                        *outbuf = cpu_to_le32(params->stats->rx_frame_errors);
 563                        retval = 0;
 564                }
 565                break;
 566
 567        /* mandatory */
 568        case OID_802_3_XMIT_ONE_COLLISION:
 569                debug("%s: OID_802_3_XMIT_ONE_COLLISION\n", __func__);
 570                *outbuf = __constant_cpu_to_le32(0);
 571                retval = 0;
 572                break;
 573
 574        /* mandatory */
 575        case OID_802_3_XMIT_MORE_COLLISIONS:
 576                debug("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __func__);
 577                *outbuf = __constant_cpu_to_le32(0);
 578                retval = 0;
 579                break;
 580
 581#ifdef  RNDIS_OPTIONAL_STATS
 582        case OID_802_3_XMIT_DEFERRED:
 583                debug("%s: OID_802_3_XMIT_DEFERRED\n", __func__);
 584                /* TODO */
 585                break;
 586
 587        case OID_802_3_XMIT_MAX_COLLISIONS:
 588                debug("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __func__);
 589                /* TODO */
 590                break;
 591
 592        case OID_802_3_RCV_OVERRUN:
 593                debug("%s: OID_802_3_RCV_OVERRUN\n", __func__);
 594                /* TODO */
 595                break;
 596
 597        case OID_802_3_XMIT_UNDERRUN:
 598                debug("%s: OID_802_3_XMIT_UNDERRUN\n", __func__);
 599                /* TODO */
 600                break;
 601
 602        case OID_802_3_XMIT_HEARTBEAT_FAILURE:
 603                debug("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __func__);
 604                /* TODO */
 605                break;
 606
 607        case OID_802_3_XMIT_TIMES_CRS_LOST:
 608                debug("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __func__);
 609                /* TODO */
 610                break;
 611
 612        case OID_802_3_XMIT_LATE_COLLISIONS:
 613                debug("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __func__);
 614                /* TODO */
 615                break;
 616#endif  /* RNDIS_OPTIONAL_STATS */
 617
 618#ifdef  RNDIS_PM
 619        /* power management OIDs (table 4-5) */
 620        case OID_PNP_CAPABILITIES:
 621                debug("%s: OID_PNP_CAPABILITIES\n", __func__);
 622
 623                /* for now, no wakeup capabilities */
 624                length = sizeof(struct NDIS_PNP_CAPABILITIES);
 625                memset(outbuf, 0, length);
 626                retval = 0;
 627                break;
 628        case OID_PNP_QUERY_POWER:
 629                debug("%s: OID_PNP_QUERY_POWER D%d\n", __func__,
 630                                get_unaligned_le32(buf) - 1);
 631                /*
 632                 * only suspend is a real power state, and
 633                 * it can't be entered by OID_PNP_SET_POWER...
 634                 */
 635                length = 0;
 636                retval = 0;
 637                break;
 638#endif
 639
 640        default:
 641                debug("%s: query unknown OID 0x%08X\n", __func__, OID);
 642        }
 643        if (retval < 0)
 644                length = 0;
 645
 646        resp->InformationBufferLength = cpu_to_le32(length);
 647        r->length = length + sizeof *resp;
 648        resp->MessageLength = cpu_to_le32(r->length);
 649        return retval;
 650}
 651
 652static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len,
 653                                rndis_resp_t *r)
 654{
 655        rndis_set_cmplt_type            *resp;
 656        int                             retval = -ENOTSUPP;
 657        struct rndis_params             *params;
 658#if (defined(DEBUG) && defined(DEBUG_VERBOSE)) || defined(RNDIS_PM)
 659        int                             i;
 660#endif
 661
 662        if (!r)
 663                return -ENOMEM;
 664        resp = (rndis_set_cmplt_type *) r->buf;
 665        if (!resp)
 666                return -ENOMEM;
 667
 668#if defined(DEBUG) && defined(DEBUG_VERBOSE)
 669        if (buf_len) {
 670                debug("set OID %08x value, len %d:\n", OID, buf_len);
 671                for (i = 0; i < buf_len; i += 16) {
 672                        debug("%03d: %08x %08x %08x %08x\n", i,
 673                                get_unaligned_le32(&buf[i]),
 674                                get_unaligned_le32(&buf[i + 4]),
 675                                get_unaligned_le32(&buf[i + 8]),
 676                                get_unaligned_le32(&buf[i + 12]));
 677                }
 678        }
 679#endif
 680
 681        params = &rndis_per_dev_params[configNr];
 682        switch (OID) {
 683        case OID_GEN_CURRENT_PACKET_FILTER:
 684
 685                /*
 686                 * these NDIS_PACKET_TYPE_* bitflags are shared with
 687                 * cdc_filter; it's not RNDIS-specific
 688                 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
 689                 *      PROMISCUOUS, DIRECTED,
 690                 *      MULTICAST, ALL_MULTICAST, BROADCAST
 691                 */
 692                *params->filter = (u16) get_unaligned_le32(buf);
 693                debug("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
 694                        __func__, *params->filter);
 695
 696                /*
 697                 * this call has a significant side effect:  it's
 698                 * what makes the packet flow start and stop, like
 699                 * activating the CDC Ethernet altsetting.
 700                 */
 701#ifdef  RNDIS_PM
 702update_linkstate:
 703#endif
 704                retval = 0;
 705                if (*params->filter)
 706                        params->state = RNDIS_DATA_INITIALIZED;
 707                else
 708                        params->state = RNDIS_INITIALIZED;
 709                break;
 710
 711        case OID_802_3_MULTICAST_LIST:
 712                /* I think we can ignore this */
 713                debug("%s: OID_802_3_MULTICAST_LIST\n", __func__);
 714                retval = 0;
 715                break;
 716#if 0
 717        case OID_GEN_RNDIS_CONFIG_PARAMETER:
 718                {
 719                struct rndis_config_parameter   *param;
 720                param = (struct rndis_config_parameter *) buf;
 721                debug("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
 722                        __func__,
 723                        min(cpu_to_le32(param->ParameterNameLength), 80),
 724                        buf + param->ParameterNameOffset);
 725                retval = 0;
 726                }
 727                break;
 728#endif
 729
 730#ifdef  RNDIS_PM
 731        case OID_PNP_SET_POWER:
 732                /*
 733                 * The only real power state is USB suspend, and RNDIS requests
 734                 * can't enter it; this one isn't really about power.  After
 735                 * resuming, Windows forces a reset, and then SET_POWER D0.
 736                 * FIXME ... then things go batty; Windows wedges itself.
 737                 */
 738                i = get_unaligned_le32(buf);
 739                debug("%s: OID_PNP_SET_POWER D%d\n", __func__, i - 1);
 740                switch (i) {
 741                case NdisDeviceStateD0:
 742                        *params->filter = params->saved_filter;
 743                        goto update_linkstate;
 744                case NdisDeviceStateD3:
 745                case NdisDeviceStateD2:
 746                case NdisDeviceStateD1:
 747                        params->saved_filter = *params->filter;
 748                        retval = 0;
 749                        break;
 750                }
 751                break;
 752
 753#ifdef  RNDIS_WAKEUP
 754        /*
 755         * no wakeup support advertised, so wakeup OIDs always fail:
 756         *  - OID_PNP_ENABLE_WAKE_UP
 757         *  - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN
 758         */
 759#endif
 760
 761#endif  /* RNDIS_PM */
 762
 763        default:
 764                debug("%s: set unknown OID 0x%08X, size %d\n",
 765                        __func__, OID, buf_len);
 766        }
 767
 768        return retval;
 769}
 770
 771/*
 772 * Response Functions
 773 */
 774
 775static int rndis_init_response(int configNr, rndis_init_msg_type *buf)
 776{
 777        rndis_init_cmplt_type   *resp;
 778        rndis_resp_t            *r;
 779
 780        if (!rndis_per_dev_params[configNr].dev)
 781                return -ENOTSUPP;
 782
 783        r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type));
 784        if (!r)
 785                return -ENOMEM;
 786        resp = (rndis_init_cmplt_type *) r->buf;
 787
 788        resp->MessageType = __constant_cpu_to_le32(
 789                        REMOTE_NDIS_INITIALIZE_CMPLT);
 790        resp->MessageLength = __constant_cpu_to_le32(52);
 791        resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
 792        resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
 793        resp->MajorVersion = __constant_cpu_to_le32(RNDIS_MAJOR_VERSION);
 794        resp->MinorVersion = __constant_cpu_to_le32(RNDIS_MINOR_VERSION);
 795        resp->DeviceFlags = __constant_cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
 796        resp->Medium = __constant_cpu_to_le32(RNDIS_MEDIUM_802_3);
 797        resp->MaxPacketsPerTransfer = __constant_cpu_to_le32(1);
 798        resp->MaxTransferSize = cpu_to_le32(
 799                  rndis_per_dev_params[configNr].mtu
 800                + ETHER_HDR_SIZE
 801                + sizeof(struct rndis_packet_msg_type)
 802                + 22);
 803        resp->PacketAlignmentFactor = __constant_cpu_to_le32(0);
 804        resp->AFListOffset = __constant_cpu_to_le32(0);
 805        resp->AFListSize = __constant_cpu_to_le32(0);
 806
 807        if (rndis_per_dev_params[configNr].ack)
 808                rndis_per_dev_params[configNr].ack(
 809                        rndis_per_dev_params[configNr].dev);
 810
 811        return 0;
 812}
 813
 814static int rndis_query_response(int configNr, rndis_query_msg_type *buf)
 815{
 816        rndis_query_cmplt_type *resp;
 817        rndis_resp_t            *r;
 818
 819        debug("%s: OID = %08X\n", __func__, get_unaligned_le32(&buf->OID));
 820        if (!rndis_per_dev_params[configNr].dev)
 821                return -ENOTSUPP;
 822
 823        /*
 824         * we need more memory:
 825         * gen_ndis_query_resp expects enough space for
 826         * rndis_query_cmplt_type followed by data.
 827         * oid_supported_list is the largest data reply
 828         */
 829        r = rndis_add_response(configNr,
 830                sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type));
 831        if (!r)
 832                return -ENOMEM;
 833        resp = (rndis_query_cmplt_type *) r->buf;
 834
 835        resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_QUERY_CMPLT);
 836        resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
 837
 838        if (gen_ndis_query_resp(configNr, get_unaligned_le32(&buf->OID),
 839                        get_unaligned_le32(&buf->InformationBufferOffset)
 840                                        + 8 + (u8 *) buf,
 841                        get_unaligned_le32(&buf->InformationBufferLength),
 842                        r)) {
 843                /* OID not supported */
 844                resp->Status = __constant_cpu_to_le32(
 845                                                RNDIS_STATUS_NOT_SUPPORTED);
 846                resp->MessageLength = __constant_cpu_to_le32(sizeof *resp);
 847                resp->InformationBufferLength = __constant_cpu_to_le32(0);
 848                resp->InformationBufferOffset = __constant_cpu_to_le32(0);
 849        } else
 850                resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
 851
 852        if (rndis_per_dev_params[configNr].ack)
 853                rndis_per_dev_params[configNr].ack(
 854                        rndis_per_dev_params[configNr].dev);
 855        return 0;
 856}
 857
 858static int rndis_set_response(int configNr, rndis_set_msg_type *buf)
 859{
 860        u32                     BufLength, BufOffset;
 861        rndis_set_cmplt_type    *resp;
 862        rndis_resp_t            *r;
 863
 864        r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type));
 865        if (!r)
 866                return -ENOMEM;
 867        resp = (rndis_set_cmplt_type *) r->buf;
 868
 869        BufLength = get_unaligned_le32(&buf->InformationBufferLength);
 870        BufOffset = get_unaligned_le32(&buf->InformationBufferOffset);
 871
 872#ifdef  VERBOSE
 873        debug("%s: Length: %d\n", __func__, BufLength);
 874        debug("%s: Offset: %d\n", __func__, BufOffset);
 875        debug("%s: InfoBuffer: ", __func__);
 876
 877        for (i = 0; i < BufLength; i++)
 878                debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
 879
 880        debug("\n");
 881#endif
 882
 883        resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_SET_CMPLT);
 884        resp->MessageLength = __constant_cpu_to_le32(16);
 885        resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
 886        if (gen_ndis_set_resp(configNr, get_unaligned_le32(&buf->OID),
 887                        ((u8 *) buf) + 8 + BufOffset, BufLength, r))
 888                resp->Status = __constant_cpu_to_le32(
 889                                                RNDIS_STATUS_NOT_SUPPORTED);
 890        else
 891                resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
 892
 893        if (rndis_per_dev_params[configNr].ack)
 894                rndis_per_dev_params[configNr].ack(
 895                        rndis_per_dev_params[configNr].dev);
 896
 897        return 0;
 898}
 899
 900static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf)
 901{
 902        rndis_reset_cmplt_type  *resp;
 903        rndis_resp_t            *r;
 904
 905        r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type));
 906        if (!r)
 907                return -ENOMEM;
 908        resp = (rndis_reset_cmplt_type *) r->buf;
 909
 910        resp->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_RESET_CMPLT);
 911        resp->MessageLength = __constant_cpu_to_le32(16);
 912        resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
 913        /* resent information */
 914        resp->AddressingReset = __constant_cpu_to_le32(1);
 915
 916        if (rndis_per_dev_params[configNr].ack)
 917                rndis_per_dev_params[configNr].ack(
 918                        rndis_per_dev_params[configNr].dev);
 919
 920        return 0;
 921}
 922
 923static int rndis_keepalive_response(int configNr,
 924                                        rndis_keepalive_msg_type *buf)
 925{
 926        rndis_keepalive_cmplt_type      *resp;
 927        rndis_resp_t                    *r;
 928
 929        /* host "should" check only in RNDIS_DATA_INITIALIZED state */
 930
 931        r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type));
 932        if (!r)
 933                return -ENOMEM;
 934        resp = (rndis_keepalive_cmplt_type *) r->buf;
 935
 936        resp->MessageType = __constant_cpu_to_le32(
 937                        REMOTE_NDIS_KEEPALIVE_CMPLT);
 938        resp->MessageLength = __constant_cpu_to_le32(16);
 939        resp->RequestID = get_unaligned(&buf->RequestID); /* Still LE in msg buffer */
 940        resp->Status = __constant_cpu_to_le32(RNDIS_STATUS_SUCCESS);
 941
 942        if (rndis_per_dev_params[configNr].ack)
 943                rndis_per_dev_params[configNr].ack(
 944                        rndis_per_dev_params[configNr].dev);
 945
 946        return 0;
 947}
 948
 949
 950/*
 951 * Device to Host Comunication
 952 */
 953static int rndis_indicate_status_msg(int configNr, u32 status)
 954{
 955        rndis_indicate_status_msg_type  *resp;
 956        rndis_resp_t                    *r;
 957
 958        if (rndis_per_dev_params[configNr].state == RNDIS_UNINITIALIZED)
 959                return -ENOTSUPP;
 960
 961        r = rndis_add_response(configNr,
 962                                sizeof(rndis_indicate_status_msg_type));
 963        if (!r)
 964                return -ENOMEM;
 965        resp = (rndis_indicate_status_msg_type *) r->buf;
 966
 967        resp->MessageType = __constant_cpu_to_le32(
 968                        REMOTE_NDIS_INDICATE_STATUS_MSG);
 969        resp->MessageLength = __constant_cpu_to_le32(20);
 970        resp->Status = cpu_to_le32(status);
 971        resp->StatusBufferLength = __constant_cpu_to_le32(0);
 972        resp->StatusBufferOffset = __constant_cpu_to_le32(0);
 973
 974        if (rndis_per_dev_params[configNr].ack)
 975                rndis_per_dev_params[configNr].ack(
 976                        rndis_per_dev_params[configNr].dev);
 977        return 0;
 978}
 979
 980int rndis_signal_connect(int configNr)
 981{
 982        rndis_per_dev_params[configNr].media_state
 983                        = NDIS_MEDIA_STATE_CONNECTED;
 984        return rndis_indicate_status_msg(configNr,
 985                                          RNDIS_STATUS_MEDIA_CONNECT);
 986}
 987
 988int rndis_signal_disconnect(int configNr)
 989{
 990        rndis_per_dev_params[configNr].media_state
 991                        = NDIS_MEDIA_STATE_DISCONNECTED;
 992
 993#ifdef RNDIS_COMPLETE_SIGNAL_DISCONNECT
 994        return rndis_indicate_status_msg(configNr,
 995                                          RNDIS_STATUS_MEDIA_DISCONNECT);
 996#else
 997        return 0;
 998#endif
 999}
1000
1001void rndis_uninit(int configNr)
1002{
1003        u8 *buf;
1004        u32 length;
1005
1006        if (configNr >= RNDIS_MAX_CONFIGS)
1007                return;
1008        rndis_per_dev_params[configNr].used = 0;
1009        rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED;
1010
1011        /* drain the response queue */
1012        while ((buf = rndis_get_next_response(configNr, &length)))
1013                rndis_free_response(configNr, buf);
1014}
1015
1016void rndis_set_host_mac(int configNr, const u8 *addr)
1017{
1018        rndis_per_dev_params[configNr].host_mac = addr;
1019}
1020
1021enum rndis_state rndis_get_state(int configNr)
1022{
1023        if (configNr >= RNDIS_MAX_CONFIGS || configNr < 0)
1024                return -ENOTSUPP;
1025        return rndis_per_dev_params[configNr].state;
1026}
1027
1028/*
1029 * Message Parser
1030 */
1031int rndis_msg_parser(u8 configNr, u8 *buf)
1032{
1033        u32                             MsgType, MsgLength;
1034        __le32                          *tmp;
1035        struct rndis_params             *params;
1036
1037        debug("%s: configNr = %d, %p\n", __func__, configNr, buf);
1038
1039        if (!buf)
1040                return -ENOMEM;
1041
1042        tmp = (__le32 *) buf;
1043        MsgType   = get_unaligned_le32(tmp++);
1044        MsgLength = get_unaligned_le32(tmp++);
1045
1046        if (configNr >= RNDIS_MAX_CONFIGS)
1047                return -ENOTSUPP;
1048        params = &rndis_per_dev_params[configNr];
1049
1050        /*
1051         * NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
1052         * rx/tx statistics and link status, in addition to KEEPALIVE traffic
1053         * and normal HC level polling to see if there's any IN traffic.
1054         */
1055
1056        /* For USB: responses may take up to 10 seconds */
1057        switch (MsgType) {
1058        case REMOTE_NDIS_INITIALIZE_MSG:
1059                debug("%s: REMOTE_NDIS_INITIALIZE_MSG\n", __func__);
1060                params->state = RNDIS_INITIALIZED;
1061                return  rndis_init_response(configNr,
1062                                        (rndis_init_msg_type *) buf);
1063
1064        case REMOTE_NDIS_HALT_MSG:
1065                debug("%s: REMOTE_NDIS_HALT_MSG\n", __func__);
1066                params->state = RNDIS_UNINITIALIZED;
1067                return 0;
1068
1069        case REMOTE_NDIS_QUERY_MSG:
1070                return rndis_query_response(configNr,
1071                                        (rndis_query_msg_type *) buf);
1072
1073        case REMOTE_NDIS_SET_MSG:
1074                return rndis_set_response(configNr,
1075                                        (rndis_set_msg_type *) buf);
1076
1077        case REMOTE_NDIS_RESET_MSG:
1078                debug("%s: REMOTE_NDIS_RESET_MSG\n", __func__);
1079                return rndis_reset_response(configNr,
1080                                        (rndis_reset_msg_type *) buf);
1081
1082        case REMOTE_NDIS_KEEPALIVE_MSG:
1083                /* For USB: host does this every 5 seconds */
1084#if defined(DEBUG) && defined(DEBUG_VERBOSE)
1085                debug("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __func__);
1086#endif
1087                return rndis_keepalive_response(configNr,
1088                                        (rndis_keepalive_msg_type *) buf);
1089
1090        default:
1091                /*
1092                 * At least Windows XP emits some undefined RNDIS messages.
1093                 * In one case those messages seemed to relate to the host
1094                 * suspending itself.
1095                 */
1096                debug("%s: unknown RNDIS message 0x%08X len %d\n",
1097                        __func__ , MsgType, MsgLength);
1098                {
1099                        unsigned i;
1100                        for (i = 0; i < MsgLength; i += 16) {
1101                                debug("%03d: "
1102                                        " %02x %02x %02x %02x"
1103                                        " %02x %02x %02x %02x"
1104                                        " %02x %02x %02x %02x"
1105                                        " %02x %02x %02x %02x"
1106                                        "\n",
1107                                        i,
1108                                        buf[i], buf[i+1],
1109                                                buf[i+2], buf[i+3],
1110                                        buf[i+4], buf[i+5],
1111                                                buf[i+6], buf[i+7],
1112                                        buf[i+8], buf[i+9],
1113                                                buf[i+10], buf[i+11],
1114                                        buf[i+12], buf[i+13],
1115                                                buf[i+14], buf[i+15]);
1116                        }
1117                }
1118                break;
1119        }
1120
1121        return -ENOTSUPP;
1122}
1123
1124#ifndef CONFIG_DM_ETH
1125int rndis_register(int (*rndis_control_ack)(struct eth_device *))
1126#else
1127int rndis_register(int (*rndis_control_ack)(struct udevice *))
1128#endif
1129{
1130        u8 i;
1131
1132        for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1133                if (!rndis_per_dev_params[i].used) {
1134                        rndis_per_dev_params[i].used = 1;
1135                        rndis_per_dev_params[i].ack = rndis_control_ack;
1136                        debug("%s: configNr = %d\n", __func__, i);
1137                        return i;
1138                }
1139        }
1140        debug("%s failed\n", __func__);
1141
1142        return -1;
1143}
1144
1145void rndis_deregister(int configNr)
1146{
1147        debug("%s: configNr = %d\n", __func__, configNr);
1148
1149        if (configNr >= RNDIS_MAX_CONFIGS)
1150                return;
1151        rndis_per_dev_params[configNr].used = 0;
1152
1153        return;
1154}
1155
1156#ifndef CONFIG_DM_ETH
1157int  rndis_set_param_dev(u8 configNr, struct eth_device *dev, int mtu,
1158                         struct net_device_stats *stats, u16 *cdc_filter)
1159#else
1160int  rndis_set_param_dev(u8 configNr, struct udevice *dev, int mtu,
1161                         struct net_device_stats *stats, u16 *cdc_filter)
1162#endif
1163{
1164        debug("%s: configNr = %d\n", __func__, configNr);
1165        if (!dev || !stats)
1166                return -1;
1167        if (configNr >= RNDIS_MAX_CONFIGS)
1168                return -1;
1169
1170        rndis_per_dev_params[configNr].dev = dev;
1171        rndis_per_dev_params[configNr].stats = stats;
1172        rndis_per_dev_params[configNr].mtu = mtu;
1173        rndis_per_dev_params[configNr].filter = cdc_filter;
1174
1175        return 0;
1176}
1177
1178int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
1179{
1180        debug("%s: configNr = %d\n", __func__, configNr);
1181        if (!vendorDescr)
1182                return -1;
1183        if (configNr >= RNDIS_MAX_CONFIGS)
1184                return -1;
1185
1186        rndis_per_dev_params[configNr].vendorID = vendorID;
1187        rndis_per_dev_params[configNr].vendorDescr = vendorDescr;
1188
1189        return 0;
1190}
1191
1192int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
1193{
1194        debug("%s: configNr = %d, %u %u\n", __func__, configNr, medium, speed);
1195        if (configNr >= RNDIS_MAX_CONFIGS)
1196                return -1;
1197
1198        rndis_per_dev_params[configNr].medium = medium;
1199        rndis_per_dev_params[configNr].speed = speed;
1200
1201        return 0;
1202}
1203
1204void rndis_add_hdr(void *buf, int length)
1205{
1206        struct rndis_packet_msg_type    *header;
1207
1208        header = buf;
1209        memset(header, 0, sizeof *header);
1210        header->MessageType = __constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG);
1211        header->MessageLength = cpu_to_le32(length + sizeof *header);
1212        header->DataOffset = __constant_cpu_to_le32(36);
1213        header->DataLength = cpu_to_le32(length);
1214}
1215
1216void rndis_free_response(int configNr, u8 *buf)
1217{
1218        rndis_resp_t            *r;
1219        struct list_head        *act, *tmp;
1220
1221        list_for_each_safe(act, tmp,
1222                        &(rndis_per_dev_params[configNr].resp_queue))
1223        {
1224                r = list_entry(act, rndis_resp_t, list);
1225                if (r && r->buf == buf) {
1226                        list_del(&r->list);
1227                        free(r);
1228                }
1229        }
1230}
1231
1232u8 *rndis_get_next_response(int configNr, u32 *length)
1233{
1234        rndis_resp_t            *r;
1235        struct list_head        *act, *tmp;
1236
1237        if (!length)
1238                return NULL;
1239
1240        list_for_each_safe(act, tmp,
1241                        &(rndis_per_dev_params[configNr].resp_queue))
1242        {
1243                r = list_entry(act, rndis_resp_t, list);
1244                if (!r->send) {
1245                        r->send = 1;
1246                        *length = r->length;
1247                        return r->buf;
1248                }
1249        }
1250
1251        return NULL;
1252}
1253
1254static rndis_resp_t *rndis_add_response(int configNr, u32 length)
1255{
1256        rndis_resp_t    *r;
1257
1258        /* NOTE:  this gets copied into ether.c USB_BUFSIZ bytes ... */
1259        r = malloc(sizeof(rndis_resp_t) + length);
1260        if (!r)
1261                return NULL;
1262
1263        r->buf = (u8 *) (r + 1);
1264        r->length = length;
1265        r->send = 0;
1266
1267        list_add_tail(&r->list,
1268                &(rndis_per_dev_params[configNr].resp_queue));
1269        return r;
1270}
1271
1272int rndis_rm_hdr(void *buf, int length)
1273{
1274        /* tmp points to a struct rndis_packet_msg_type */
1275        __le32          *tmp = buf;
1276        int             offs, len;
1277
1278        /* MessageType, MessageLength */
1279        if (__constant_cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
1280                        != get_unaligned(tmp++))
1281                return -EINVAL;
1282        tmp++;
1283
1284        /* DataOffset, DataLength */
1285        offs = get_unaligned_le32(tmp++) + 8 /* offset of DataOffset */;
1286        if (offs != sizeof(struct rndis_packet_msg_type))
1287                debug("%s: unexpected DataOffset: %d\n", __func__, offs);
1288        if (offs >= length)
1289                return -EOVERFLOW;
1290
1291        len = get_unaligned_le32(tmp++);
1292        if (len + sizeof(struct rndis_packet_msg_type) != length)
1293                debug("%s: unexpected DataLength: %d, packet length=%d\n",
1294                                __func__, len, length);
1295
1296        memmove(buf, buf + offs, len);
1297
1298        return offs;
1299}
1300
1301int rndis_init(void)
1302{
1303        u8 i;
1304
1305        for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
1306                rndis_per_dev_params[i].confignr = i;
1307                rndis_per_dev_params[i].used = 0;
1308                rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED;
1309                rndis_per_dev_params[i].media_state
1310                                = NDIS_MEDIA_STATE_DISCONNECTED;
1311                INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue));
1312        }
1313
1314        return 0;
1315}
1316
1317void rndis_exit(void)
1318{
1319        /* Nothing to do */
1320}
1321