7 #include "rndis.class.h"
9 #define htole32(x) AROS_LONG2LE(x)
10 #define letoh32(x) AROS_LE2LONG(x)
13 #define ps ncp->ncp_Base
16 uint32_t urndis_ctrl_msg(struct NepClassEth
*ncp
, uint8_t rt
, uint8_t r
,
17 uint16_t index
, uint16_t value
, void *buf
, size_t buflen
)
24 if((mp
= CreateMsgPort()))
26 if((pp
= psdAllocPipe(ncp
->ncp_Device
, mp
, NULL
)))
29 psdSetAttrs(PGA_PIPE
, pp
,
30 PPA_NakTimeout
, FALSE
,
31 PPA_NakTimeoutTime
, 5000,
32 PPA_AllowRuntPackets
, TRUE
,
35 // bug("urndis_ctrl_msg:pipesetup( %d,%d,%d,%d,%d )\n",pp, rt, r, value, index);
36 psdPipeSetup(pp
, rt
, r
, value
, index
);
37 // bug("urndis_ctrl_msg:psdDoPipe(%d,%d,%d)\n",pp, buf, buflen);
38 err
= psdDoPipe(pp
, buf
, buflen
);
40 bug("urndis_ctrl_msg:error %d,%s\n",err
,psdNumToStr(NTS_IOERR
, err
, "unknown"));
51 uint32_t urndis_ctrl_send(struct NepClassEth
*ncp
, void *buf
, size_t len
)
54 LONG sc_ifaceno_ctl
=0;
56 bug("urndis_ctrl_send:\n");
59 err
= urndis_ctrl_msg(ncp
, UT_WRITE_CLASS_INTERFACE
, UR_GET_STATUS
, sc_ifaceno_ctl
, 0, buf
, len
);
62 bug("%s:urndis_ctrl_send error %d\n",DEVNAME
,err
);
69 #define RNDIS_RESPONSE_LEN 0x400
71 struct urndis_comp_hdr
*
72 urndis_ctrl_recv(struct NepClassEth
*ncp
)
75 struct urndis_comp_hdr
*hdr
;
78 LONG sc_ifaceno_ctl
=0;
81 buf
= psdAllocVec(RNDIS_RESPONSE_LEN
);
83 bug("%s: out of memory\n", DEVNAME
);
87 err
= urndis_ctrl_msg(ncp
, UT_READ_CLASS_INTERFACE
, UR_CLEAR_FEATURE
,
88 sc_ifaceno_ctl
, 0, buf
, RNDIS_RESPONSE_LEN
);
91 bug("%s: urndis_comp_hdr error\n", DEVNAME
);
96 hdr
= (struct urndis_comp_hdr
*)buf
;
97 bug("%s: urndis_ctrl_recv: type 0x%x len %u\n",
100 letoh32(hdr
->rm_len
));
102 //dumpmem(buf,hdr->rm_len);
104 if (letoh32(hdr
->rm_len
) > RNDIS_RESPONSE_LEN
) {
105 bug("%s: ctrl message error: wrong size %u > %u\n",
107 letoh32(hdr
->rm_len
),
118 urndis_ctrl_handle_init(struct NepClassEth
*ncp
,
119 const struct urndis_comp_hdr
*hdr
)
121 const struct urndis_init_comp
*msg
;
123 msg
= (struct urndis_init_comp
*) hdr
;
125 bug("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
126 "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
127 "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
129 letoh32(msg
->rm_len
),
130 letoh32(msg
->rm_rid
),
131 letoh32(msg
->rm_status
),
132 letoh32(msg
->rm_ver_major
),
133 letoh32(msg
->rm_ver_minor
),
134 letoh32(msg
->rm_devflags
),
135 letoh32(msg
->rm_medium
),
136 letoh32(msg
->rm_pktmaxcnt
),
137 letoh32(msg
->rm_pktmaxsz
),
138 letoh32(msg
->rm_align
),
139 letoh32(msg
->rm_aflistoffset
),
140 letoh32(msg
->rm_aflistsz
));
142 if (letoh32(msg
->rm_status
) != RNDIS_STATUS_SUCCESS
) {
143 bug("%s: init failed 0x%x\n",
145 letoh32(msg
->rm_status
));
147 return letoh32(msg
->rm_status
);
150 if (letoh32(msg
->rm_devflags
) != RNDIS_DF_CONNECTIONLESS
) {
151 bug("%s: wrong device type (current type: 0x%x)\n",
153 letoh32(msg
->rm_devflags
));
155 return RNDIS_STATUS_FAILURE
;
158 if (letoh32(msg
->rm_medium
) != RNDIS_MEDIUM_802_3
) {
159 bug("%s: medium not 802.3 (current medium: 0x%x)\n",
160 DEVNAME
, letoh32(msg
->rm_medium
));
162 return RNDIS_STATUS_FAILURE
;
165 ncp
->sc_lim_pktsz
= letoh32(msg
->rm_pktmaxsz
);
167 return letoh32(msg
->rm_status
);
172 urndis_ctrl_handle_query(struct NepClassEth
*ncp
,
173 const struct urndis_comp_hdr
*hdr
, void **buf
, size_t *bufsz
)
175 const struct urndis_query_comp
*msg
;
177 msg
= (struct urndis_query_comp
*) hdr
;
179 bug("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x "
180 "buflen %u bufoff %u\n",
182 letoh32(msg
->rm_len
),
183 letoh32(msg
->rm_rid
),
184 letoh32(msg
->rm_status
),
185 letoh32(msg
->rm_infobuflen
),
186 letoh32(msg
->rm_infobufoffset
));
193 if (letoh32(msg
->rm_status
) != RNDIS_STATUS_SUCCESS
) {
194 bug("%s: query failed 0x%x\n",
196 letoh32(msg
->rm_status
));
198 return letoh32(msg
->rm_status
);
201 if (letoh32(msg
->rm_infobuflen
) + letoh32(msg
->rm_infobufoffset
) +
202 RNDIS_HEADER_OFFSET
> letoh32(msg
->rm_len
)) {
203 bug("%s: ctrl message error: invalid query info "
204 "len/offset/end_position(%d/%d/%d) -> "
205 "go out of buffer limit %d\n",
207 letoh32(msg
->rm_infobuflen
),
208 letoh32(msg
->rm_infobufoffset
),
209 letoh32(msg
->rm_infobuflen
) +
210 letoh32(msg
->rm_infobufoffset
) + RNDIS_HEADER_OFFSET
,
211 letoh32(msg
->rm_len
));
212 return RNDIS_STATUS_FAILURE
;
216 *buf
= psdAllocVec(letoh32(msg
->rm_infobuflen
));
218 bug("%s: out of memory\n", DEVNAME
);
219 return RNDIS_STATUS_FAILURE
;
222 *bufsz
= letoh32(msg
->rm_infobuflen
);
224 p
= (char *)&msg
->rm_rid
;
225 p
+= letoh32(msg
->rm_infobufoffset
);
226 memcpy(*buf
, p
, letoh32(msg
->rm_infobuflen
));
230 return letoh32(msg
->rm_status
);
235 urndis_ctrl_set(struct NepClassEth
*ncp
, uint32_t oid
, void *buf
, size_t len
)
237 struct urndis_set_req
*msg
;
239 struct urndis_comp_hdr
*hdr
;
241 msg
= psdAllocVec(sizeof(*msg
) + len
);
243 bug("%s: out of memory\n", DEVNAME
);
244 return RNDIS_STATUS_FAILURE
;
247 msg
->rm_type
= htole32(REMOTE_NDIS_SET_MSG
);
248 msg
->rm_len
= htole32(sizeof(*msg
) + len
);
249 msg
->rm_rid
= 0; /* XXX */
250 msg
->rm_oid
= htole32(oid
);
251 msg
->rm_infobuflen
= htole32(len
);
253 msg
->rm_infobufoffset
= htole32(20);
254 memcpy((char*)msg
+ 20, buf
, len
);
256 msg
->rm_infobufoffset
= 0;
257 msg
->rm_devicevchdl
= 0;
259 bug("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x "
260 "infobuflen %u infobufoffset %u devicevchdl %u\n",
262 letoh32(msg
->rm_type
),
263 letoh32(msg
->rm_len
),
264 letoh32(msg
->rm_rid
),
265 letoh32(msg
->rm_oid
),
266 letoh32(msg
->rm_infobuflen
),
267 letoh32(msg
->rm_infobufoffset
),
268 letoh32(msg
->rm_devicevchdl
));
270 rval
= urndis_ctrl_send(ncp
, msg
, sizeof(*msg
));
273 if (rval
!= RNDIS_STATUS_SUCCESS
) {
274 bug("%s: set failed\n", DEVNAME
);
278 if ((hdr
= urndis_ctrl_recv(ncp
)) == NULL
) {
279 bug("%s: unable to get set response\n", DEVNAME
);
280 return RNDIS_STATUS_FAILURE
;
282 rval
= urndis_ctrl_handle(ncp
, hdr
, NULL
, NULL
);
283 if (rval
!= RNDIS_STATUS_SUCCESS
)
284 bug("%s: set failed 0x%x\n", DEVNAME
, rval
);
291 urndis_ctrl_handle_reset(struct NepClassEth
*ncp
,
292 const struct urndis_comp_hdr
*hdr
)
294 const struct urndis_reset_comp
*msg
;
297 msg
= (struct urndis_reset_comp
*) hdr
;
299 rval
= letoh32(msg
->rm_status
);
301 bug("%s: urndis_ctrl_handle_reset: len %u status 0x%x "
304 letoh32(msg
->rm_len
),
306 letoh32(msg
->rm_adrreset
));
308 if (rval
!= RNDIS_STATUS_SUCCESS
) {
309 bug("%s: reset failed 0x%x\n", DEVNAME
, rval
);
313 if (letoh32(msg
->rm_adrreset
) != 0) {
316 filter
= htole32(ncp
->sc_filter
);
317 rval
= urndis_ctrl_set(ncp
, OID_GEN_CURRENT_PACKET_FILTER
,
318 &filter
, sizeof(filter
));
319 if (rval
!= RNDIS_STATUS_SUCCESS
) {
320 bug("%s: unable to reset data filters\n",
330 uint32_t urndis_ctrl_handle(struct NepClassEth
*ncp
, struct urndis_comp_hdr
*hdr
,void **buf
, size_t *bufsz
)
334 bug("%s: urndis_ctrl_handle\n", DEVNAME
);
341 switch (letoh32(hdr
->rm_type
)) {
342 case REMOTE_NDIS_INITIALIZE_CMPLT
:
343 rval
= urndis_ctrl_handle_init(ncp
, hdr
);
346 case REMOTE_NDIS_QUERY_CMPLT
:
347 rval
= urndis_ctrl_handle_query(ncp
, hdr
, buf
, bufsz
);
350 case REMOTE_NDIS_RESET_CMPLT
:
351 rval
= urndis_ctrl_handle_reset(ncp
, hdr
);
354 case REMOTE_NDIS_KEEPALIVE_CMPLT
:
355 case REMOTE_NDIS_SET_CMPLT
:
356 rval
= letoh32(hdr
->rm_status
);
360 bug("%s: ctrl message error: unknown event 0x%x\n",
361 DEVNAME
, letoh32(hdr
->rm_type
));
362 rval
= RNDIS_STATUS_FAILURE
;
372 urndis_ctrl_query(struct NepClassEth
*ncp
, uint32_t oid
,
373 void *qbuf
, size_t qlen
,
374 void **rbuf
, size_t *rbufsz
)
376 struct urndis_query_req
*msg
;
378 struct urndis_comp_hdr
*hdr
;
380 msg
= psdAllocVec(sizeof(*msg
) + qlen
);
382 bug("%s: out of memory\n", DEVNAME
);
383 return RNDIS_STATUS_FAILURE
;
386 msg
->rm_type
= htole32(REMOTE_NDIS_QUERY_MSG
);
387 msg
->rm_len
= htole32(sizeof(*msg
) + qlen
);
388 msg
->rm_rid
= 0; /* XXX */
389 msg
->rm_oid
= htole32(oid
);
390 msg
->rm_infobuflen
= htole32(qlen
);
392 msg
->rm_infobufoffset
= htole32(20);
393 memcpy((char*)msg
+ 20, qbuf
, qlen
);
395 msg
->rm_infobufoffset
= 0;
396 msg
->rm_devicevchdl
= 0;
398 bug("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x "
399 "infobuflen %u infobufoffset %u devicevchdl %u\n",
401 letoh32(msg
->rm_type
),
402 letoh32(msg
->rm_len
),
403 letoh32(msg
->rm_rid
),
404 letoh32(msg
->rm_oid
),
405 letoh32(msg
->rm_infobuflen
),
406 letoh32(msg
->rm_infobufoffset
),
407 letoh32(msg
->rm_devicevchdl
));
409 rval
= urndis_ctrl_send(ncp
, msg
, sizeof(*msg
));
412 if (rval
!= RNDIS_STATUS_SUCCESS
) {
413 bug("%s: query failed\n", DEVNAME
);
417 if ((hdr
= urndis_ctrl_recv(ncp
)) == NULL
) {
418 bug("%s: unable to get query response\n", DEVNAME
);
419 return RNDIS_STATUS_FAILURE
;
421 rval
= urndis_ctrl_handle(ncp
, hdr
, rbuf
, rbufsz
);
427 uint32_t urndis_ctrl_init(struct NepClassEth
*ncp
)
429 struct urndis_init_req
*msg
;
431 struct urndis_comp_hdr
*hdr
;
433 msg
= psdAllocVec(sizeof(*msg
));
435 bug("out of memory\n");
436 return RNDIS_STATUS_FAILURE
;
439 msg
->rm_type
= htole32(REMOTE_NDIS_INITIALIZE_MSG
);
440 msg
->rm_len
= htole32(sizeof(*msg
));
441 msg
->rm_rid
= htole32(0);
442 msg
->rm_ver_major
= htole32(1);
443 msg
->rm_ver_minor
= htole32(1);
444 msg
->rm_max_xfersz
= htole32(RNDIS_BUFSZ
);
446 bug("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u "
447 "ver_minor %u max_xfersz %u\n",
449 letoh32(msg
->rm_type
),
450 letoh32(msg
->rm_len
),
451 letoh32(msg
->rm_rid
),
452 letoh32(msg
->rm_ver_major
),
453 letoh32(msg
->rm_ver_minor
),
454 letoh32(msg
->rm_max_xfersz
));
458 rval
= urndis_ctrl_send(ncp
, msg
, sizeof(*msg
));
462 bug("%s: init failed\n", DEVNAME
);
466 if ((hdr
= urndis_ctrl_recv(ncp
)) == NULL
) {
467 bug("%s: unable to get init response\n", DEVNAME
);
468 return RNDIS_STATUS_FAILURE
;
470 rval
= urndis_ctrl_handle(ncp
, hdr
, NULL
, NULL
);
476 long urndis_encap(struct NepClassEth
*ncp
, BYTE
*m
,LONG len
)
479 struct urndis_packet_msg
*msg
;
480 msg
= (struct urndis_packet_msg
*)m
;
482 memset(msg
, 0, sizeof(*msg
));
483 msg
->rm_type
= htole32(REMOTE_NDIS_PACKET_MSG
);
484 msg
->rm_len
= htole32(sizeof(*msg
) + len
);
486 msg
->rm_dataoffset
= htole32(RNDIS_DATA_OFFSET
);
487 msg
->rm_datalen
= htole32(len
);
489 //m_copydata(m, 0, len,((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET));
491 DB(bug("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n",
493 letoh32(msg
->rm_type
),
494 letoh32(msg
->rm_len
),
495 letoh32(msg
->rm_dataoffset
),
496 letoh32(msg
->rm_datalen
)));
498 return(sizeof(*msg
));
502 void urndis_decap(struct NepClassEth
*ncp
, const UBYTE
*buf
, const LONG datalen
)
505 struct urndis_packet_msg
*msg
;
513 msg
= (struct urndis_packet_msg
*)(buf
+ offset
);
514 DB(bug("%s: urndis_decap buffer size left %u\n", DEVNAME
,len
));
516 if (len
< sizeof(*msg
)) {
517 bug("%s: urndis_decap invalid buffer len %u < "
518 "minimum header %u\n",
525 DB(bug("%s: urndis_decap len %u data(off:%u len:%u) "
526 "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
528 letoh32(msg
->rm_len
),
529 letoh32(msg
->rm_dataoffset
),
530 letoh32(msg
->rm_datalen
),
531 letoh32(msg
->rm_oobdataoffset
),
532 letoh32(msg
->rm_oobdatalen
),
533 letoh32(msg
->rm_oobdataelements
),
534 letoh32(msg
->rm_pktinfooffset
),
535 letoh32(msg
->rm_pktinfooffset
)));
537 if (letoh32(msg
->rm_type
) != REMOTE_NDIS_PACKET_MSG
) {
538 bug("%s: urndis_decap invalid type 0x%x != 0x%x\n",
540 letoh32(msg
->rm_type
),
541 REMOTE_NDIS_PACKET_MSG
);
544 if (letoh32(msg
->rm_len
) < sizeof(*msg
)) {
545 bug("%s: urndis_decap invalid msg len %u < %u\n",
547 letoh32(msg
->rm_len
),
551 if (letoh32(msg
->rm_len
) > len
) {
552 bug("%s: urndis_decap invalid msg len %u > buffer "
555 letoh32(msg
->rm_len
),
560 if (letoh32(msg
->rm_dataoffset
) +
561 letoh32(msg
->rm_datalen
) + RNDIS_HEADER_OFFSET
562 > letoh32(msg
->rm_len
)) {
563 bug("%s: urndis_decap invalid data "
564 "len/offset/end_position(%u/%u/%u) -> "
565 "go out of receive buffer limit %u\n",
567 letoh32(msg
->rm_datalen
),
568 letoh32(msg
->rm_dataoffset
),
569 letoh32(msg
->rm_dataoffset
) +
570 letoh32(msg
->rm_datalen
) + RNDIS_HEADER_OFFSET
,
571 letoh32(msg
->rm_len
));
575 if (letoh32(msg
->rm_datalen
) < sizeof(struct EtherPacketHeader
)) {
576 bug("%s: urndis_decap invalid ethernet size "
579 letoh32(msg
->rm_datalen
),
580 sizeof(struct EtherPacketHeader
));
584 DB(bug("%s: urndis_decap ethernet packet OK,size %d,offset %d\n",DEVNAME
, letoh32(msg
->rm_datalen
),offset
));
586 nReadPacket(ncp
, ((char*)&msg
->rm_dataoffset
+ letoh32(msg
->rm_dataoffset
)), letoh32(msg
->rm_datalen
) );
588 offset
+= letoh32(msg
->rm_len
);
589 len
-= letoh32(msg
->rm_len
);
595 urndis_attach(struct NepClassEth
*ncp
)
598 uint8_t eaddr
[ETHER_ADDR_SIZE
];
603 urndis_ctrl_init(ncp
);
605 if (urndis_ctrl_query(ncp
, OID_802_3_PERMANENT_ADDRESS
, NULL
, 0,
606 &buf
, &bufsz
) != RNDIS_STATUS_SUCCESS
) {
607 bug("%s: unable to get hardware address\n", DEVNAME
);
610 if (bufsz
== ETHER_ADDR_SIZE
) {
611 memcpy(eaddr
, buf
, ETHER_ADDR_SIZE
);
612 bug("%s: address %x:%x:%x:%x:%x:%x\n", DEVNAME
, eaddr
[0],eaddr
[1],eaddr
[2],eaddr
[3],eaddr
[4],eaddr
[5]);
615 bug("%s: invalid address\n", DEVNAME
);
620 /* Initialize packet filter */
621 ncp
->sc_filter
= RNDIS_PACKET_TYPE_BROADCAST
;
622 ncp
->sc_filter
|= RNDIS_PACKET_TYPE_ALL_MULTICAST
;
623 filter
= htole32(ncp
->sc_filter
);
624 if (urndis_ctrl_set(ncp
, OID_GEN_CURRENT_PACKET_FILTER
, &filter
,
625 sizeof(filter
)) != RNDIS_STATUS_SUCCESS
) {
626 bug("%s: unable to set data filters\n", DEVNAME
);
630 bug("%s: urndis_attach OK!\n", DEVNAME
);
632 CopyMem(eaddr
, ncp
->ncp_MacAddress
, ETHER_ADDR_SIZE
);
633 CopyMem(eaddr
, ncp
->ncp_ROMAddress
, ETHER_ADDR_SIZE
);