
/*
**	SANA-II extended device query test
**	Written by Timm S. Mueller
*/

#include <stdio.h>
#include <stdlib.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <devices/sana2.h>
#include <devices/sana2devqueryext.h>
#include <devices/newstyle.h>



struct MsgPort *devport = NULL;
struct IOSana2Req *ioreq = NULL;
struct Device *device = NULL;
BOOL devopen = FALSE;


static void g_exit(void)
{
	if (ioreq)
	{
		if (devopen)
			CloseDevice((struct IORequest *) ioreq);
		DeleteIORequest((struct IORequest *) ioreq);
	}
	if (devport)
		DeleteMsgPort(devport);
}


static BOOL g_init(void)
{
	for (;;)
	{
		devport = CreateMsgPort();
		if (!devport)
			break;
		ioreq = (struct IOSana2Req *) CreateIORequest(devport, 
			sizeof(struct IOSana2Req));
		if (!ioreq)
			break;
		devopen = OpenDevice("x-surf-100.device", 0,
			(struct IORequest *) ioreq, 0) == 0;
		if (!devopen)
		{
			printf("cannot open device\n");
			break;
		}
		return TRUE;
	}
	g_exit();
	return FALSE;
}


static BOOL findcmd(struct NSDeviceQueryResult *nsdqr, UWORD cmd)
{
	for (UWORD *p = nsdqr->SupportedCommands; (*p); ++p)
		if (*p == cmd)
			return TRUE;
	return FALSE;
}


int main(int argc, char **argv)
{
	int res = RETURN_FAIL;
	if (!g_init())
		return res;
	
	for (;;)
	{
		res = RETURN_ERROR;
		
		struct NSDeviceQueryResult nsdqr;
		struct IOStdReq *stdreq = (struct IOStdReq *) ioreq;
		stdreq->io_Command = NSCMD_DEVICEQUERY;
		stdreq->io_Flags = 0;
		stdreq->io_Data = &nsdqr;
		stdreq->io_Length = sizeof nsdqr;
		
		if (DoIO((struct IORequest *) ioreq) != 0)
		{
			printf("I/O error\n");
			break;
		}
		
		if (nsdqr.DeviceType != NSDEVTYPE_SANA2)
		{
			printf("device not of required type: %u\n", nsdqr.DeviceType);
			break;
		}
		
		ioreq->ios2_Req.io_Command = S2_GETSTATIONADDRESS;
		if (DoIO((struct IORequest *) ioreq) == 0)
		{
			unsigned char *p = ioreq->ios2_SrcAddr;
			printf("current: %02x:%02x:%02x:%02x:%02x:%02x\n", 
				(int) p[0], (int) p[1], (int) p[2], (int) p[3],
				(int) p[4], (int) p[5]);
			p = ioreq->ios2_DstAddr;
			printf("default: %02x:%02x:%02x:%02x:%02x:%02x\n", 
				(int) p[0], (int) p[1], (int) p[2], (int) p[3],
				(int) p[4], (int) p[5]);
		}
		else
		{
			printf("I/O error\n");
			break;
		}

		res = RETURN_WARN;
		
		if (!findcmd(&nsdqr, S2_DEVICEQUERYEXT))
		{
			printf("extended command not supported\n");
			break;
		}
		
		char vendorname[128], productname[128];
		ULONG link, speed;

		struct S2DevQueryExtParam pproductname = 
			{ productname, sizeof productname, 0 };
		struct S2DevQueryExtParam pvendorname = 
			{ vendorname, sizeof vendorname, 0 };
		struct S2DevQueryExtParam plink = { &link, sizeof link, 0 };
		struct S2DevQueryExtParam pspeed = { &speed, sizeof speed, 0 };
		
		struct TagItem tags[] =
		{
			{ S2_DevQueryExtVendorName, (ULONG) &pvendorname },
			{ S2_DevQueryExtProductName, (ULONG) &pproductname },
			{ S2_DevQueryExtLinkStatus, (ULONG) &plink },
			{ S2_DevQueryExtLinkSpeed, (ULONG) &pspeed },
			{ TAG_DONE },
		};
		
		ioreq->ios2_Req.io_Command = S2_DEVICEQUERYEXT;
		ioreq->ios2_Data = tags;
		ioreq->ios2_DataLength = sizeof tags;
		
		if (DoIO((struct IORequest *) ioreq) == 0)
		{
			if (pvendorname.Actual != 0)
			{
				vendorname[sizeof(vendorname) - 1] = 0;
				printf("vendorname: %s\n", vendorname);
			}
			if (pproductname.Actual != 0)
			{
				productname[sizeof(productname) - 1] = 0;
				printf("productname: %s\n", productname);
			}
			if (plink.Actual == sizeof link)
				printf("link: %lu\n", link);
			if (pspeed.Actual == sizeof speed)
				printf("speed: %lu\n", speed);
			
			res = RETURN_OK;
		}
		else
			printf("error getting extended attributes\n");
		
		break;
	}

	g_exit();

	return res;
}
