rdb_host.c 6.86 KB
/*
 * Host driver for the RDB device
 *
 * Note that this is just for loopback testing.  The real host
 * for this device will be a PC not a BB.
 */

#include "osint.h"
#include "host.h"

/*
 * State structure for the host rdbs driver.  Note that it
 * is not possible to have two instances of this on the same BB.
 */
struct {
	boolean rdbs_enabled;
	int_16	bulkpipein;
	int_16	bulkpipeout;
} rdbs_host_state;

/*
 * Callback function to process the device detach event
 */
static void
rdbs_host_detach
   (
      _usb_host_handle  handle,
      uint_32           length
   )
{
	USB_HOST_STATE_STRUCT_PTR hsp = (USB_HOST_STATE_STRUCT_PTR)handle;
	HOST_GLOBAL_STRUCT_PTR hgp;

	hgp = &host_global_struct[hsp->CTLR_NUM];

	_usb_host_cancel_transfer(handle, hgp->DEFAULT_PIPE);
	if (rdbs_host_state.rdbs_enabled) {
		_usb_host_cancel_transfer(handle, rdbs_host_state.bulkpipein);
		_usb_host_cancel_transfer(handle, rdbs_host_state.bulkpipeout);
	}
	return;
}

/*FUNCTION*----------------------------------------------------------------
* 
* Function Name  : rdbs_host_send_transaction_done
* Returned Value : 
* Comments       :
*     Callback function to process the transaction done event on an
*     output data pipe
* 
*END*--------------------------------------------------------------------*/
static void
rdbs_host_send_transaction_done
   (
      _usb_host_handle  handle,
      uint_32           length
   )
{
	USB_HOST_STATE_STRUCT_PTR hsp = (USB_HOST_STATE_STRUCT_PTR)handle;
	HOST_GLOBAL_STRUCT_PTR hgp;

	hgp = &host_global_struct[hsp->CTLR_NUM];

printf("<<<<rdbs_host_send_transaction_done\n"); /* XXX */

	hgp->TRANSACTION_COMPLETE = TRUE;
	return;
}

/*FUNCTION*----------------------------------------------------------------
* 
* Function Name  : rdbs_host_recv_transaction_done
* Returned Value : 
* Comments       :
*     Callback function to process the transaction done event on an
*     input data pipe
* 
*END*--------------------------------------------------------------------*/
static void
rdbs_host_recv_transaction_done
   (
      _usb_host_handle  handle,
      uint_32           length
   )
{
	USB_HOST_STATE_STRUCT_PTR hsp = (USB_HOST_STATE_STRUCT_PTR)handle;
	HOST_GLOBAL_STRUCT_PTR hgp;

	hgp = &host_global_struct[hsp->CTLR_NUM];

printf("<<<<rdbs_host_recv_transaction_done\n"); /* XXX */

	hgp->TRANSACTION_COMPLETE = TRUE;
	return;
}

/*FUNCTION*----------------------------------------------------------------
* 
* Function Name  : rdbs_host_chap9
* Returned Value : 
* Comments       :
*     Device specific chapter 9 processing
* 
*END*--------------------------------------------------------------------*/
static void
rdbs_host_chapter9(_usb_host_handle handle)
{
}

static void
rdbs_host_open(_usb_host_handle  handle)
{
	USB_HOST_STATE_STRUCT_PTR hsp = (USB_HOST_STATE_STRUCT_PTR)handle;
	HOST_GLOBAL_STRUCT_PTR hgp;
	uint_8 error;

	hgp = &host_global_struct[hsp->CTLR_NUM];

        rdbs_host_state.bulkpipeout = _usb_host_open_pipe(handle, 
            	hgp->USB_CURRENT_ADDRESS, 2, USB_SEND, 0x00, 
            	USB_BULK_PIPE, 64, 0, 0);
        rdbs_host_state.bulkpipein  = _usb_host_open_pipe(handle, 
            	hgp->USB_CURRENT_ADDRESS, 2, USB_RECV, 0x00, 
            	USB_BULK_PIPE, 64, 0, 0);
           
printf("///rdbs_host_open bulkpipein %d, bulkpipeout %d\n",
        	rdbs_host_state.bulkpipein, rdbs_host_state.bulkpipeout);

        error = _usb_host_register_service(handle, rdbs_host_state.bulkpipeout, 
                rdbs_host_send_transaction_done);
        if (error != USB_OK) {
              	printf("\nUSB Service Registration failed. Error: %x", error);
        }
            
        error = _usb_host_register_service(handle, rdbs_host_state.bulkpipein, 
               	rdbs_host_recv_transaction_done);
        if (error != USB_OK) {
               	printf("\nUSB Service Registration failed. Error: %x", error);
        }

	return;	    
}

/*
 * Hardwire the device descriptor for the rdbs device
 */
usb_dev_desc rdbs_dev_desc
__attribute__ ((aligned (16)))
= {
	18,
	1,
#ifdef BIG_ENDIAN
	0x0110,
#else
	0x1001,
#endif
	0x00,
	0x00,
	0x00,
	62,
#ifdef BIG_ENDIAN
	0xBB3D,
	0xBBDB,
	0x0001,
#else
	0x3DBB,
	0xDBBB,
	0x0100,
#endif
	1,
	2,
	0,
	1
};

/*
 * Compare Device Descriptor to see if it is the RDBS Device
 */
int
rdbs_host_match(usb_dev_desc *uddp)
{
//printf("<<<<rdbs_host_match &rdbs_dev_desc 0x%x, &IDVENDOR 0x%x\n", &rdbs_dev_desc, &(rdbs_dev_desc.IDVENDOR));

	if (swab16(uddp->IDVENDOR) != rdbs_dev_desc.IDVENDOR) {
		//printf("Vendor id 0x%x not rdbs 0x%x\n", swab16(uddp->IDVENDOR), rdbs_dev_desc.IDVENDOR);
		return(0);
	}

	if (swab16(uddp->IDPRODUCT) != rdbs_dev_desc.IDPRODUCT) {
		//printf("Prod id 0x%x not rdbs\n", swab16(uddp->IDPRODUCT));
		return(0);
	}

	if (swab16(uddp->BCDDEVICE) != rdbs_dev_desc.BCDDEVICE) {
		//printf("Dev version 0x%x not rdbs\n", swab16(uddp->BCDDEVICE));
		return(0);
	}

	return(1);
}

static void
rdbs_host_poll(_usb_host_handle handle)
{
	return;
}

static char rdbs_send_buf[64];

static void
rdbs_host_send(_usb_host_handle handle, u8 *buffer, s32 len, u64 offset)
{
	USB_HOST_STATE_STRUCT_PTR hsp = (USB_HOST_STATE_STRUCT_PTR)handle;
	HOST_GLOBAL_STRUCT_PTR hgp;
	uint_8 error;

	hgp = &host_global_struct[hsp->CTLR_NUM];

	hgp->TRANSACTION_COMPLETE = FALSE;
printf("--rdbs_host_send buf 0x%x, len %d, pipe %d\n", buffer, len, rdbs_host_state.bulkpipeout);
	/*
	 * For RDB device, there is no position, so offset is ignored
	 */
	if (len > 62) {
printf("---rdbs_host_send bad len %d\n", len);
		len = 62;
	}

	bzero((void *)rdbs_send_buf, sizeof(rdbs_send_buf));
	*(uint_16 *)rdbs_send_buf = len;
	bcopy((void *)buffer, (void *)&rdbs_send_buf[2], len);

        error = _usb_host_send_data(handle, rdbs_host_state.bulkpipeout, (uchar_ptr)rdbs_send_buf, 64);
	if (error != USB_STATUS_TRANSFER_QUEUED) {
		printf("---rdbs_host_send: host_send_data err %d\n", error);
	}

	while (hgp->TRANSACTION_COMPLETE == FALSE) {
		if (!hgp->DEVICE_ATTACHED)
			return;
		osYieldThread();
	}

	return;
}

static char rdbs_recv_buf[64];

static void
rdbs_host_recv(_usb_host_handle handle, u8 *buffer, s32 len, u64 offset)
{
	USB_HOST_STATE_STRUCT_PTR hsp = (USB_HOST_STATE_STRUCT_PTR)handle;
	HOST_GLOBAL_STRUCT_PTR hgp;

	hgp = &host_global_struct[hsp->CTLR_NUM];

	hgp->TRANSACTION_COMPLETE = FALSE;
printf("--rdbs_host_recv buf 0x%x, len %d, pipe %d\n", buffer, len, rdbs_host_state.bulkpipein);

	_usb_host_recv_data(handle, rdbs_host_state.bulkpipein, (uchar_ptr)rdbs_recv_buf, 64);
	while (hgp->TRANSACTION_COMPLETE == FALSE) {
		if (!hgp->DEVICE_ATTACHED)
			return;
		osYieldThread();
	}

	len = *(uint_16 *)rdbs_recv_buf;
	if (len > 62)
		len = 62;
	bcopy((void *)&rdbs_recv_buf[2], (void *)buffer, len);
	return;
}

usb_host_driver_funcs rdbs_host_funcs = {
	rdbs_host_match,
	rdbs_host_open,
	rdbs_host_poll,
	rdbs_host_send,
	rdbs_host_recv,
	rdbs_host_detach,
	rdbs_host_chapter9,
};

usb_host_driver rdbs_host_driver = {
	&rdbs_dev_desc,
	&rdbs_host_funcs,
	"BB RDB host driver"
};