1 /*-------------------------------------------------------------
3 network_wii.c -- Wii network subsystem
5 Copyright (C) 2008 bushing
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any
9 damages arising from the use of this software.
11 Permission is granted to anyone to use this software for any
12 purpose, including commercial applications, and to alter it and
13 redistribute it freely, subject to the following restrictions:
15 1. The origin of this software must not be misrepresented; you
16 must not claim that you wrote the original software. If you use
17 this software in a product, an acknowledgment in the product
18 documentation would be appreciated but is not required.
20 2. Altered source versions must be plainly marked as such, and
21 must not be misrepresented as being the original software.
23 3. This notice may not be removed or altered from any source
26 -------------------------------------------------------------*/
31 #define MAX_IP_RETRIES 100
32 #define MAX_INIT_RETRIES 32
37 #define debug_printf(fmt, args...) \
39 fprintf(stderr, "%s:%d:" fmt, __FUNCTION__, __LINE__, ##args); \
42 #define debug_printf(fmt, args...) do { } while (0)
48 #define __LINUX_ERRNO_EXTENSIONS__
55 #include "processor.h"
60 #define NET_HEAP_SIZE 64*1024
62 #define IOS_O_NONBLOCK 0x04 //(O_NONBLOCK >> 16) - it's in octal representation, so this shift leads to 0 and hence nonblocking sockets didn't work. changed it to the right value.
64 #define IOCTL_NWC24_STARTUP 0x06
66 #define IOCTL_NCD_SETIFCONFIG3 0x03
67 #define IOCTL_NCD_SETIFCONFIG4 0x04
68 #define IOCTL_NCD_GETLINKSTATUS 0x07
69 #define IOCTLV_NCD_GETMACADDRESS 0x08
71 #define NET_UNKNOWN_ERROR_OFFSET -10000
79 IOCTL_SO_GETPEERNAME
, // todo
80 IOCTL_SO_GETSOCKNAME
, // todo
81 IOCTL_SO_GETSOCKOPT
, // todo 8
84 IOCTL_SO_POLL
, // todo b
87 IOCTL_SO_SHUTDOWN
, // todo e
90 IOCTL_SO_GETHOSTBYNAME
,
91 IOCTL_SO_GETHOSTBYADDR
,// todo
92 IOCTLV_SO_GETNAMEINFO
, // todo 13
93 IOCTL_SO_UNK14
, // todo
94 IOCTL_SO_INETATON
, // todo
95 IOCTL_SO_INETPTON
, // todo
96 IOCTL_SO_INETNTOP
, // todo
97 IOCTLV_SO_GETADDRINFO
, // todo
98 IOCTL_SO_SOCKATMARK
, // todo
99 IOCTLV_SO_UNK1A
, // todo
100 IOCTLV_SO_UNK1B
, // todo
101 IOCTLV_SO_GETINTERFACEOPT
, // todo
102 IOCTLV_SO_SETINTERFACEOPT
, // todo
103 IOCTL_SO_SETINTERFACE
, // todo
104 IOCTL_SO_STARTUP
, // 0x1f
105 IOCTL_SO_ICMPSOCKET
= 0x30, // todo
106 IOCTLV_SO_ICMPPING
, // todo
107 IOCTL_SO_ICMPCANCEL
, // todo
108 IOCTL_SO_ICMPCLOSE
// todo
123 struct init_default_cb
{
134 struct connect_params
{
140 struct sendto_params
{
147 struct setsockopt_params
{
155 // 0 means we don't know what this error code means
156 // I sense a pattern here...
157 static u8 _net_error_code_map
[] = {
237 static volatile bool _init_busy
= false;
238 static volatile bool _init_abort
= false;
239 static vs32 _last_init_result
= -ENETDOWN
;
240 static s32 net_ip_top_fd
= -1;
241 static u8 __net_heap_inited
= 0;
242 static s32 __net_hid
=-1;
243 static heap_cntrl __net_heap
;
245 static char __manage_fs
[] ATTRIBUTE_ALIGN(32) = "/dev/net/ncd/manage";
246 static char __iptop_fs
[] ATTRIBUTE_ALIGN(32) = "/dev/net/ip/top";
247 static char __kd_fs
[] ATTRIBUTE_ALIGN(32) = "/dev/net/kd/request";
249 #define ROUNDDOWN32(v) (((u32)(v)-0x1f)&~0x1f)
251 static s32
NetCreateHeap()
256 _CPU_ISR_Disable(level
);
258 if(__net_heap_inited
)
260 _CPU_ISR_Restore(level
);
264 net_heap_ptr
= (void *)ROUNDDOWN32(((u32
)SYS_GetArena2Hi() - NET_HEAP_SIZE
));
265 if((u32
)net_heap_ptr
< (u32
)SYS_GetArena2Lo())
267 _CPU_ISR_Restore(level
);
270 SYS_SetArena2Hi(net_heap_ptr
);
271 __lwp_heap_init(&__net_heap
, net_heap_ptr
, NET_HEAP_SIZE
, 32);
273 _CPU_ISR_Restore(level
);
277 static void* net_malloc(u32 size
)
279 return __lwp_heap_allocate(&__net_heap
, size
);
282 static BOOL
net_free(void *ptr
)
284 return __lwp_heap_free(&__net_heap
, ptr
);
287 static s32
_net_convert_error(s32 ios_retval
)
289 // return ios_retval;
290 if (ios_retval
>= 0) return ios_retval
;
291 if (ios_retval
< -sizeof(_net_error_code_map
)
292 || !_net_error_code_map
[-ios_retval
])
293 return NET_UNKNOWN_ERROR_OFFSET
+ ios_retval
;
294 return -_net_error_code_map
[-ios_retval
];
297 u32
net_gethostip(void)
302 if (net_ip_top_fd
< 0) return 0;
303 for (retries
=0, ip_addr
=0; !ip_addr
&& retries
< 5; retries
++) {
304 ip_addr
= IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_GETHOSTID
, 0, 0, 0, 0);
316 static s32
net_init_chain(s32 result
, void *usrdata
);
318 static void net_init_alarm(syswd_t alarm
, void *cb_arg
) {
319 debug_printf("net_init alarm\n");
320 net_init_chain(0, cb_arg
);
323 static s32
net_init_chain(s32 result
, void *usrdata
) {
324 struct init_data
*data
= (struct init_data
*) usrdata
;
327 debug_printf("net_init chain entered: %u %d\n", data
->state
, result
);
334 switch (data
->state
) {
335 case 0: // open manage fd
337 data
->result
= IOS_OpenAsync(__manage_fs
, 0, net_init_chain
, data
);
338 if (data
->result
< 0) {
339 data
->result
= _net_convert_error(data
->result
);
344 case 1: // get link status
345 if (result
== IPC_ENOENT
) {
346 debug_printf("IPC_ENOENT, retrying...\n");
349 tb
.tv_nsec
= 100000000;
350 data
->result
= SYS_SetAlarm(data
->alarm
, &tb
, net_init_alarm
, data
);
352 debug_printf("error setting the alarm: %d\n", data
->result
);
359 data
->result
= _net_convert_error(result
);
360 debug_printf("error opening the manage fd: %d\n", data
->result
);
366 data
->result
= IOS_IoctlvFormatAsync(__net_hid
, data
->fd
, IOCTL_NCD_GETLINKSTATUS
, net_init_chain
, data
, ":d", data
->buf
, 0x20);
367 if (data
->result
< 0) {
368 data
->result
= _net_convert_error(data
->result
);
370 if (IOS_CloseAsync(data
->fd
, net_init_chain
, data
) < 0)
375 case 2: // close manage fd
376 data
->prevres
= result
;
378 data
->result
= IOS_CloseAsync(data
->fd
, net_init_chain
, data
);
379 if (data
->result
< 0) {
380 data
->result
= _net_convert_error(data
->result
);
385 case 3: // open top fd
386 if (data
->prevres
< 0) {
387 data
->result
= _net_convert_error(data
->prevres
);
388 debug_printf("invalid link status %d\n", data
->result
);
393 data
->result
= IOS_OpenAsync(__iptop_fs
, 0, net_init_chain
, data
);
394 if (data
->result
< 0) {
395 data
->result
= _net_convert_error(data
->result
);
400 case 4: // open request fd
402 data
->result
= _net_convert_error(result
);
403 debug_printf("error opening the top fd: %d\n", data
->result
);
407 net_ip_top_fd
= result
;
409 data
->result
= IOS_OpenAsync(__kd_fs
, 0, net_init_chain
, data
);
410 if (data
->result
< 0) {
411 data
->result
= _net_convert_error(data
->result
);
417 case 5: // NWC24 startup
419 data
->result
= _net_convert_error(result
);
420 debug_printf("error opening the request fd: %d\n", data
->result
);
426 data
->retries
= MAX_INIT_RETRIES
;
429 data
->result
= IOS_IoctlAsync(data
->fd
, IOCTL_NWC24_STARTUP
, NULL
, 0, data
->buf
, 0x20, net_init_chain
, data
);
430 if (data
->result
< 0) {
431 data
->result
= _net_convert_error(data
->result
);
433 if (IOS_CloseAsync(data
->fd
, net_init_chain
, data
) < 0)
439 memcpy(&result
, data
->buf
, sizeof(result
));
440 if(result
==-29 && --data
->retries
) {
443 tb
.tv_nsec
= 100000000;
444 data
->result
= SYS_SetAlarm(data
->alarm
, &tb
, net_init_alarm
, data
);
447 debug_printf("error setting the alarm: %d\n", data
->result
);
448 if (IOS_CloseAsync(data
->fd
, net_init_chain
, data
) < 0)
452 } else if (result
== -15) // this happens if it's already been started
456 data
->prevres
= result
;
458 data
->result
= IOS_CloseAsync(data
->fd
, net_init_chain
, data
);
459 if (data
->result
< 0) {
460 data
->result
= _net_convert_error(data
->result
);
466 case 8: // socket startup
467 if (data
->prevres
< 0) {
468 data
->result
= _net_convert_error(data
->prevres
);
469 debug_printf("NWC24 startup failed: %d\n", data
->result
);
475 data
->retries
= MAX_IP_RETRIES
;
476 data
->result
= IOS_IoctlAsync(net_ip_top_fd
, IOCTL_SO_STARTUP
, 0, 0, 0, 0, net_init_chain
, data
);
477 if (data
->result
< 0) {
478 data
->result
= _net_convert_error(data
->result
);
486 data
->result
= _net_convert_error(result
);
487 debug_printf("socket startup failed: %d\n", data
->result
);
493 data
->result
= IOS_IoctlAsync(net_ip_top_fd
, IOCTL_SO_GETHOSTID
, 0, 0, 0, 0, net_init_chain
, data
);
494 if (data
->result
< 0) {
495 data
->result
= _net_convert_error(data
->result
);
501 case 10: // done, check result
503 if (!data
->retries
) {
504 data
->result
= -ETIMEDOUT
;
505 debug_printf("unable to obtain ip\n");
510 debug_printf("unable to obtain ip, retrying...\n");
514 tb
.tv_nsec
= 100000000;
515 data
->result
= SYS_SetAlarm(data
->alarm
, &tb
, net_init_alarm
, data
);
518 debug_printf("error setting the alarm: %d\n", data
->result
);
528 case 0xff: // error occured before, last async call finished
529 if (net_ip_top_fd
>= 0) {
530 data
->fd
= net_ip_top_fd
;
532 if (IOS_CloseAsync(data
->fd
, net_init_chain
, data
) < 0)
539 debug_printf("unknown state in chain %d\n", data
->state
);
546 SYS_RemoveAlarm(data
->alarm
);
548 _last_init_result
= data
->result
;
551 data
->cb(data
->result
, data
->usrdata
);
561 s32
net_init_async(netcallback cb
, void *usrdata
) {
563 struct init_data
*data
;
565 if (net_ip_top_fd
>= 0)
571 ret
= NetCreateHeap();
576 __net_hid
= iosCreateHeap(1024); //only needed for ios calls
581 data
= malloc(sizeof(struct init_data
));
585 memset(data
, 0, sizeof(struct init_data
));
587 if (SYS_CreateAlarm(&data
->alarm
)) {
588 debug_printf("error creating alarm\n");
593 data
->buf
= memalign(32, 0x20);
600 data
->usrdata
= usrdata
;
602 // kick off the callback chain
605 _last_init_result
= -EBUSY
;
606 net_init_chain(IPC_ENOENT
, data
);
611 static void net_init_callback(s32 result
, void *usrdata
) {
612 struct init_default_cb
*data
= (struct init_default_cb
*) usrdata
;
614 data
->result
= result
;
615 LWP_ThreadBroadcast(data
->queue
);
621 struct init_default_cb data
;
623 if (net_ip_top_fd
>= 0)
626 LWP_InitQueue(&data
.queue
);
627 net_init_async((netcallback
)net_init_callback
, &data
);
628 LWP_ThreadSleep(data
.queue
);
629 LWP_CloseQueue(data
.queue
);
634 s32
net_get_status(void) {
635 return _last_init_result
;
640 debug_printf("aborting net_init_async\n");
644 debug_printf("net_init_async done\n");
647 if (net_ip_top_fd
>= 0) IOS_Close(net_ip_top_fd
);
649 _last_init_result
= -ENETDOWN
;
652 void net_wc24cleanup() {
654 STACK_ALIGN(u8
, kd_buf
, 0x20, 32);
656 kd_fd
= IOS_Open(__kd_fs
, 0);
658 ret
= IOS_Ioctl(kd_fd
, 7, NULL
, 0, kd_buf
, 0x20);
663 s32
net_get_mac_address(void *mac_buf
) {
667 STACK_ALIGN(u32
, manage_buf
, 0x20, 32);
669 if (mac_buf
==NULL
) return -EINVAL
;
671 result
= NetCreateHeap();
672 if (result
!=IPC_OK
) return result
;
674 _mac_buf
= net_malloc(6);
675 if (_mac_buf
==NULL
) return IPC_ENOMEM
;
677 fd
= IOS_Open(__manage_fs
, 0);
683 result
= IOS_IoctlvFormat(__net_hid
, fd
, IOCTLV_NCD_GETMACADDRESS
, ":dd", manage_buf
, 0x20, _mac_buf
, 0x06);
687 memcpy(mac_buf
, _mac_buf
, 6);
688 if (manage_buf
[0]) result
= manage_buf
[0];
695 /* Returned value is a static buffer -- this function is not threadsafe! */
696 struct hostent
* net_gethostbyname(const char *addrString
)
700 struct hostent
*ipData
;
702 static u8 ipBuffer
[0x460] ATTRIBUTE_ALIGN(32);
704 memset(ipBuffer
, 0, 0x460);
706 if (net_ip_top_fd
< 0) {
711 len
= strlen(addrString
) + 1;
712 params
= net_malloc(len
);
718 memcpy(params
, addrString
, len
);
720 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_GETHOSTBYNAME
, params
, len
, ipBuffer
, 0x460));
722 if(params
!=NULL
) net_free(params
);
729 ipData
= ((struct hostent
*)ipBuffer
);
730 addrOffset
= (u32
)MEM_PHYSICAL_TO_K0(ipData
->h_name
) - ((u32
)ipBuffer
+ 0x10);
732 ipData
->h_name
= MEM_PHYSICAL_TO_K0(ipData
->h_name
) - addrOffset
;
733 ipData
->h_aliases
= MEM_PHYSICAL_TO_K0(ipData
->h_aliases
) - addrOffset
;
735 for (i
=0; (i
< 0x40) && (ipData
->h_aliases
[i
] != 0); i
++) {
736 ipData
->h_aliases
[i
] = MEM_PHYSICAL_TO_K0(ipData
->h_aliases
[i
]) - addrOffset
;
739 ipData
->h_addr_list
= MEM_PHYSICAL_TO_K0(ipData
->h_addr_list
) - addrOffset
;
741 for (i
=0; (i
< 0x40) && (ipData
->h_addr_list
[i
] != 0); i
++) {
742 ipData
->h_addr_list
[i
] = MEM_PHYSICAL_TO_K0(ipData
->h_addr_list
[i
]) - addrOffset
;
749 s32
net_socket(u32 domain
, u32 type
, u32 protocol
)
752 STACK_ALIGN(u32
, params
, 3, 32);
754 if (net_ip_top_fd
< 0) return -ENXIO
;
758 params
[2] = protocol
;
760 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_SOCKET
, params
, 12, NULL
, 0));
761 if(ret
>=0) // set tcp window size to 24kb
763 int window_size
= 24576;
764 net_setsockopt(ret
, SOL_SOCKET
, SO_RCVBUF
, (char *) &window_size
, sizeof(window_size
));
766 debug_printf("net_socket(%d, %d, %d)=%d\n", domain
, type
, protocol
, ret
);
770 s32
net_shutdown(s32 s
, u32 how
)
773 STACK_ALIGN(u32
, params
, 2, 32);
775 if (net_ip_top_fd
< 0) return -ENXIO
;
779 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_SHUTDOWN
, params
, 8, NULL
, 0));
781 debug_printf("net_shutdown(%d, %d)=%d\n", s
, how
, ret
);
785 s32
net_bind(s32 s
, struct sockaddr
*name
, socklen_t namelen
)
788 STACK_ALIGN(struct bind_params
,params
,1,32);
790 if (net_ip_top_fd
< 0) return -ENXIO
;
791 if (name
->sa_family
!= AF_INET
) return -EAFNOSUPPORT
;
795 memset(params
, 0, sizeof(struct bind_params
));
797 params
->has_name
= 1;
798 memcpy(params
->name
, name
, 8);
800 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_BIND
, params
, sizeof (struct bind_params
), NULL
, 0));
801 debug_printf("net_bind(%d, %p)=%d\n", s
, name
, ret
);
806 s32
net_listen(s32 s
, u32 backlog
)
809 STACK_ALIGN(u32
, params
, 2, 32);
811 if (net_ip_top_fd
< 0) return -ENXIO
;
816 debug_printf("calling ios_ioctl(%d, %d, %p, %d)\n", net_ip_top_fd
, IOCTL_SO_SOCKET
, params
, 8);
818 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_LISTEN
, params
, 8, NULL
, 0));
819 debug_printf("net_listen(%d, %d)=%d\n", s
, backlog
, ret
);
823 s32
net_accept(s32 s
, struct sockaddr
*addr
, socklen_t
*addrlen
)
826 STACK_ALIGN(u32
, _socket
, 1, 32);
828 debug_printf("net_accept()\n");
830 if (net_ip_top_fd
< 0) return -ENXIO
;
832 if (!addr
) return -EINVAL
;
834 addr
->sa_family
= AF_INET
;
836 if (!addrlen
) return -EINVAL
;
838 if (*addrlen
< 8) return -ENOMEM
;
843 debug_printf("calling ios_ioctl(%d, %d, %p, %d)\n", net_ip_top_fd
, IOCTL_SO_ACCEPT
, _socket
, 4);
844 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_ACCEPT
, _socket
, 4, addr
, *addrlen
));
846 debug_printf("net_accept(%d, %p)=%d\n", s
, addr
, ret
);
850 s32
net_connect(s32 s
, struct sockaddr
*addr
, socklen_t addrlen
)
853 STACK_ALIGN(struct connect_params
,params
,1,32);
855 if (net_ip_top_fd
< 0) return -ENXIO
;
856 if (addr
->sa_family
!= AF_INET
) return -EAFNOSUPPORT
;
857 if (addrlen
< 8) return -EINVAL
;
861 memset(params
, 0, sizeof(struct connect_params
));
863 params
->has_addr
= 1;
864 memcpy(¶ms
->addr
, addr
, addrlen
);
866 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_CONNECT
, params
, sizeof(struct connect_params
), NULL
, 0));
868 debug_printf("SOConnect(%d, %p)=%d\n", s
, addr
, ret
);
873 s32
net_write(s32 s
, const void *data
, s32 size
)
875 return net_send(s
, data
, size
, 0);
878 s32
net_send(s32 s
, const void *data
, s32 size
, u32 flags
)
880 return net_sendto(s
, data
, size
, flags
, NULL
, 0);
883 s32
net_sendto(s32 s
, const void *data
, s32 len
, u32 flags
, struct sockaddr
*to
, socklen_t tolen
)
886 u8
* message_buf
= NULL
;
887 STACK_ALIGN(struct sendto_params
,params
,1,32);
889 if (net_ip_top_fd
< 0) return -ENXIO
;
890 if (tolen
> 28) return -EOVERFLOW
;
892 message_buf
= net_malloc(len
);
893 if (message_buf
== NULL
) {
894 debug_printf("net_send: failed to alloc %d bytes\n", len
);
898 debug_printf("net_sendto(%d, %p, %d, %d, %p, %d)\n", s
, data
, len
, flags
, to
, tolen
);
900 if (to
&& to
->sa_len
!= tolen
) {
901 debug_printf("warning: to->sa_len was %d, setting to %d\n", to
->sa_len
, tolen
);
905 memset(params
, 0, sizeof(struct sendto_params
));
906 memcpy(message_buf
, data
, len
); // ensure message buf is aligned
909 params
->flags
= flags
;
911 params
->has_destaddr
= 1;
912 memcpy(params
->destaddr
, to
, to
->sa_len
);
914 params
->has_destaddr
= 0;
917 ret
= _net_convert_error(IOS_IoctlvFormat(__net_hid
, net_ip_top_fd
, IOCTLV_SO_SENDTO
, "dd:", message_buf
, len
, params
, sizeof(struct sendto_params
)));
918 debug_printf("net_send retuned %d\n", ret
);
920 if(message_buf
!=NULL
) net_free(message_buf
);
924 s32
net_recv(s32 s
, void *mem
, s32 len
, u32 flags
)
926 return net_recvfrom(s
, mem
, len
, flags
, NULL
, NULL
);
929 s32
net_recvfrom(s32 s
, void *mem
, s32 len
, u32 flags
, struct sockaddr
*from
, socklen_t
*fromlen
)
932 u8
* message_buf
= NULL
;
933 STACK_ALIGN(u32
, params
, 2, 32);
935 if (net_ip_top_fd
< 0) return -ENXIO
;
936 if (len
<=0) return -EINVAL
;
938 if (fromlen
&& from
->sa_len
!= *fromlen
) {
939 debug_printf("warning: from->sa_len was %d, setting to %d\n",from
->sa_len
, *fromlen
);
940 from
->sa_len
= *fromlen
;
943 message_buf
= net_malloc(len
);
944 if (message_buf
== NULL
) {
945 debug_printf("SORecv: failed to alloc %d bytes\n", len
);
949 debug_printf("net_recvfrom(%d, '%s', %d, %d, %p, %d)\n", s
, (char *)mem
, len
, flags
, from
, fromlen
?*fromlen
:0);
951 memset(message_buf
, 0, len
);
955 ret
= _net_convert_error(IOS_IoctlvFormat(__net_hid
, net_ip_top_fd
, IOCTLV_SO_RECVFROM
, "d:dd", params
, 8, message_buf
, len
, from
, (fromlen
?*fromlen
:0)));
956 debug_printf("net_recvfrom returned %d\n", ret
);
964 memcpy(mem
, message_buf
, ret
);
967 if (fromlen
&& from
) *fromlen
= from
->sa_len
;
970 if(message_buf
!=NULL
) net_free(message_buf
);
974 s32
net_read(s32 s
, void *mem
, s32 len
)
976 return net_recvfrom(s
, mem
, len
, 0, NULL
, NULL
);
982 STACK_ALIGN(u32
, _socket
, 1, 32);
984 if (net_ip_top_fd
< 0) return -ENXIO
;
987 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_CLOSE
, _socket
, 4, NULL
, 0));
990 debug_printf("net_close(%d)=%d\n", s
, ret
);
995 s32
net_select(s32 maxfdp1
, fd_set
*readset
, fd_set
*writeset
, fd_set
*exceptset
, struct timeval
*timeout
)
997 // not yet implemented
1001 s32
net_setsockopt(s32 s
, u32 level
, u32 optname
, const void *optval
, socklen_t optlen
)
1004 STACK_ALIGN(struct setsockopt_params
,params
,1,32);
1006 if (net_ip_top_fd
< 0) return -ENXIO
;
1007 if (optlen
< 0 || optlen
> 20) return -EINVAL
;
1009 memset(params
, 0, sizeof(struct setsockopt_params
));
1011 params
->level
= level
;
1012 params
->optname
= optname
;
1013 params
->optlen
= optlen
;
1014 if (optval
&& optlen
) memcpy (params
->optval
, optval
, optlen
);
1016 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_SETSOCKOPT
, params
, sizeof(struct setsockopt_params
), NULL
, 0));
1018 debug_printf("net_setsockopt(%d, %u, %u, %p, %d)=%d\n", s
, level
, optname
, optval
, optlen
, ret
);
1022 s32
net_ioctl(s32 s
, u32 cmd
, void *argp
)
1025 u32
*intp
= (u32
*)argp
;
1027 if (net_ip_top_fd
< 0) return -ENXIO
;
1028 if (!intp
) return -EINVAL
;
1032 flags
= net_fcntl(s
, F_GETFL
, 0);
1033 flags
&= ~IOS_O_NONBLOCK
;
1034 if (*intp
) flags
|= IOS_O_NONBLOCK
;
1035 return net_fcntl(s
, F_SETFL
, flags
);
1041 s32
net_fcntl(s32 s
, u32 cmd
, u32 flags
)
1044 STACK_ALIGN(u32
, params
, 3, 32);
1046 if (net_ip_top_fd
< 0) return -ENXIO
;
1047 if (cmd
!= F_GETFL
&& cmd
!= F_SETFL
) return -EINVAL
;
1054 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_FCNTL
, params
, 12, NULL
, 0));
1056 debug_printf("net_fcntl(%d, %d, %x)=%d\n", params
[0], params
[1], params
[2], ret
);
1063 * \fn s32 net_poll(struct pollsd *sds, u32 nsds, s64 timeout)
1064 * \brief Poll a set of sockets for a set of events.
1066 * \param[in] sds a pointer to an array of pollsd structures
1067 * \param[in] nsds the number of elements in the sds array
1068 * \param[in] time in milliseconds before the function should timeout
1070 * \return the number of structures in sds that now have non-zero revent fields
1072 s32
net_poll(struct pollsd
*sds
,s32 nsds
,s32 timeout
)
1081 struct pollsd
*psds
;
1082 STACK_ALIGN(u64
,params
,1,32);
1084 if(net_ip_top_fd
<0) return -ENXIO
;
1085 if(sds
==NULL
|| nsds
==0) return -EINVAL
;
1087 psds
= net_malloc((nsds
*sizeof(struct pollsd
)));
1089 debug_printf("net_poll: failed to alloc %d bytes\n", nsds
* sizeof(struct pollsd
));
1094 outv
.ul
[1] = timeout
;
1095 params
[0] = outv
.ull
;
1096 memcpy(psds
,sds
,(nsds
*sizeof(struct pollsd
)));
1098 ret
= _net_convert_error(IOS_Ioctl(net_ip_top_fd
, IOCTL_SO_POLL
, params
, 8, psds
, (nsds
* sizeof(struct pollsd
))));
1100 memcpy(sds
,psds
,(nsds
*sizeof(struct pollsd
)));
1104 debug_printf("net_poll(sds, %d, %lld)=%d\n", nsds
, params
[0], ret
);
1109 s32
if_config(char *local_ip
, char *netmask
, char *gateway
,bool use_dhcp
)
1112 struct in_addr hostip
;
1117 for (i
= 0; i
< MAX_INIT_RETRIES
; ++i
) {
1120 if ((ret
!= -EAGAIN
) && (ret
!= -ETIMEDOUT
))
1129 hostip
.s_addr
= net_gethostip();
1130 if (local_ip
&& hostip
.s_addr
) {
1131 strcpy(local_ip
, inet_ntoa(hostip
));
1138 s32
if_configex(struct in_addr
*local_ip
, struct in_addr
*netmask
, struct in_addr
*gateway
,bool use_dhcp
)
1141 struct in_addr hostip
;
1146 for (i
= 0; i
< MAX_INIT_RETRIES
; ++i
) {
1149 if ((ret
!= -EAGAIN
) && (ret
!= -ETIMEDOUT
))
1158 hostip
.s_addr
= net_gethostip();
1159 if (local_ip
&& hostip
.s_addr
) {
1167 #endif /* defined(HW_RVL) */