whcdi.c revision ff0e937b36dcde1a47ff7b00aa76a491c0dc07a8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* USBA: Solaris USB Architecture support
*
* whcdi.c is part of the WUSB extension to the USBA framework.
*
* It mainly contains functions that can be shared by whci and hwahc
* drivers to enable WUSB host functionality, such as WUSB channel
* resource management, MMC IE handling, WUSB HC specific requests,
* WUSB device authentication, child connection/disconnection, etc.
*/
#define USBA_FRAMEWORK
/*
* local variables
*/
static kmutex_t whcdi_mutex;
/* use 0-30 bit as wusb cluster_id bitmaps */
static uint32_t cluster_id_mask = 0;
/*
* initialize private data
*/
void
{
&whcdi_errmask, NULL, 0);
"whcdi_initialization");
}
void
{
"whcdi_destroy");
}
/*
* Assign a cluster id for a WUSB channel
* return 0 if no free cluster id is available
*/
{
int i;
for (i = 0; i < WUSB_CLUSTER_ID_COUNT; i++) {
/* find the first unused slot */
if (cluster_id_mask & (1 << i)) {
continue;
}
/* set the bitmask */
cluster_id_mask |= (1 << i);
id = WUSB_MIN_CLUSTER_ID + i;
return (id);
}
"no cluster id available");
return (0);
}
/* Free the cluster id */
void
{
int i = id - WUSB_MIN_CLUSTER_ID;
if ((i < 0) || (i >= WUSB_CLUSTER_ID_COUNT)) {
return;
}
if (cluster_id_mask & (1 << i)) {
/* unset the bitmask */
cluster_id_mask &= ~(1 << i);
} else {
"cluster id already freed");
}
}
/*
* Allocate iehdl according to the order specified in WUSB 1.0/7.5
* WUSB Errata 06.12 requires iehdl to be zero based
*/
int
{
int i, rval = USB_SUCCESS;
switch (hdr->bIEIdentifier) {
case WUSB_IE_HOSTINFO:
/*
* 7.5.2(and 7.5 under Table 7-38) says this IE should be located
* in an MMC afte all WCTA_IEs. This mean its handle should
* be the last one. See also whci r0.95 page 105 top. HC sends
* IE blocks in ascending IE_HANDLE order.
*/
break;
case WUSB_IE_ISOC_DISCARD:
/*
* 7.5.10 says this IE must be included before any WxCTAs.
*/
break;
default:
/*
* search for existing slot or find the last empty slot
* so that the other IEs would always set after WCTA_IEs
*/
break;
}
}
if (hdl == 0xFF) {
"no IE handle available\n");
}
break;
}
if (rval == USB_SUCCESS) {
}
return (rval);
}
/* Deallocate iehdl */
void
{
return;
}
}
}
/*
* ******************************************************************
* WUSB host controller specific requests, refer to WUSB 1.0/8.5.3
*
* WHCI driver needs to translate the requests to register operations
* ******************************************************************
*/
/* For HWA, see WUSB 8.5.3.11 - Set WUSB Cluster ID */
int
{
int rval;
return (USB_INVALID_ARGS);
}
!= USB_SUCCESS) {
"Set_Cluster_ID fails: rval=%d ", rval);
} else {
}
return (rval);
}
/*
* WUSB 8.5.3.13 - Set WUSB Stream Index
* From 7.7, stream index should be 3bits and less than 8.
*/
int
{
int rval;
if (stream_idx > 7) {
"Set_Stream_Idx fails: invalid idx = %d",
return (USB_INVALID_ARGS);
}
if (rval != USB_SUCCESS) {
"Set_Stream_Idx fails: rval=%d",
rval);
}
return (rval);
}
/* For HWA, see WUSB 8.5.3.12 - Set WUSB MAS */
int
{
int rval;
if (rval != USB_SUCCESS) {
"Set_WUSB_MAS fails: rval=%d", rval);
}
return (rval);
}
/* For HWA, see WUSB 8.5.3.1 - Add MMC IE */
int
{
int rval;
if (rval != USB_SUCCESS) {
"Add_MMC_IE fails: rval=%d ",
rval);
}
return (rval);
}
/* For HWA, see WUSB 8.5.3.5 - Remove MMC IE */
int
{
int rval;
return (USB_FAILURE);
}
if (rval != USB_SUCCESS) {
"Remove_MMC_IE fails: rval=%d ", rval);
}
return (rval);
}
/* For HWA, see WUSB 8.5.3.14 - WUSB Channel Stop */
int
{
int rval;
if (rval != USB_SUCCESS) {
"WUSB_Ch_Stop fails: rval=%d ", rval);
}
return (rval);
}
/* For HWA, see WUSB 8.5. 3.10 - Set Num DNTS Slots */
int
{
int rval;
if (rval != USB_SUCCESS) {
"Set_Num_DNTS fails: rval=%d ", rval);
}
return (rval);
}
/*
* For HWA, see WUSB 8.5.3.2 - 8.5.3.4 Get Time
* time_type:
* WUSB_TIME_ADJ - Get BPST Adjustment
* WUSB_TIME_BPST - Get BPST Time
* WUSB_TIME_WUSB - Get WUSB Time
*/
int
{
int rval;
/* call the HC's specific get_time function */
if (rval != USB_SUCCESS) {
"Set_Num_DNTS fails: rval=%d ", rval);
}
return (rval);
}
/*
* Remove the specified IE from host MMC and release the related IE handle
*/
void
{
int i;
for (i = 0; i < hc_data->hc_num_mmcies; i++) {
break;
}
}
if (iehdl == -1) {
"wusb_hc_rem_ie: IE(%p) iehdl not found", (void *)ieh);
return;
}
}
/* Add Host Info IE */
int
{
int rval;
if (hc_data->hc_newcon_enabled) {
} else {
}
if (rval != USB_SUCCESS) {
"wusb_hc_add_host_info: get ie handle fails");
return (rval);
}
"wusb_hc_add_host_info: iehdl=%d", iehdl);
if (rval != USB_SUCCESS) {
"wusb_hc_add_host_info: add host info mmc ie fails");
return (rval);
}
return (USB_SUCCESS);
}
/* Remove Host Info IE */
void
{
/* host info IE is always the last one */
/* something wrong */
return;
}
}
/*
* Check if a device with certain CDID is connected
* return 1 if a device with the same CDID is found;
* return 0 if not
*/
{
int i;
*port = (usb_port_t)i;
"wusb_hc_is_dev_connected: find dev at port "
"%d", *port);
return (1);
}
}
return (0);
}
/*
* Check if a device with certain address is connected
* return 1 if a device with the same address is found;
* return 0 if not
*/
{
int i;
*port = (usb_port_t)i;
"wusb_hc_is_addr_valid: find addr at port "
"%d", *port);
return (1);
}
}
return (0);
}
/*
* Assign port number for a newly connected device
* return the first free port number if any, or 0 if none
*/
{
int i;
port = (usb_port_t)i;
"wusb_hc_get_free_port: find free port %d", port);
return (port);
}
}
return (0);
}
/* Add Connect Acknowledge IE */
int
{
int rval;
if (rval != USB_SUCCESS) {
"wusb_hc_ack_conn: get ie handle fails");
return (rval);
}
if (rval != USB_SUCCESS) {
"wusb_hc_ack_conn: add connect ack ie fails");
return (rval);
}
/*
* WUSB 1.0/7.5.1 requires at least 2ms delay between ConnectAck
* and WUSB transactions, wait for 2ms here
*/
return (USB_SUCCESS);
}
/* Remove Connect Acknowledge IE */
void
{
int i;
for (i = 0; i < hc_data->hc_num_mmcies; i++) {
break;
}
}
if (iehdl == -1) {
"wusb_hc_rm_ack: ack iehdl not found");
return;
}
/* remove mmc ie and free handle & memory */
}
/*
* Send a KeepAlive IE to the device. See WUSB 1.0 section 7.5.9
*/
int
{
int rval;
/*
* the scheme ensures each time only one device addr
* is set each time
*/
/* padding, no active wusb device addr will be 1 */
&iehdl);
if (rval != USB_SUCCESS) {
"wusb_hc_send_keepalive_ie: get ie handle fails");
return (rval);
}
"wusb_hc_send_keepalive_ie: get ie handle = %d", iehdl);
/*
* we must release the lock so that the DN notification
* thread can update the device active bit
*/
if (rval != USB_SUCCESS) {
"wusb_hc_send_keepalive_ie: add keepalive ie fails");
/* no need to free the ack iehdl since it is reused */
return (rval);
}
/*
* wait 400ms for the device to reply a DN_Alive notification
*/
/*
* cease transmitting the IE and release the IE handle,
* no matter we receive a response or not.
*/
return (USB_SUCCESS);
}
/*
* Check the hc_cc_list for matching CDID and return the pointer
* to the matched cc. Return NULL if no matching cc is found.
*/
{
break;
}
}
return (cc);
}
/*
* ***************************************************************
* WUSB specific standard device requests, refer to WUSB 1.0/7.3.1
* ***************************************************************
*/
/* Get WUSB device BOS descr and UWB capability descr */
int
{
int rval;
"wusb_get_dev_uwb_descr: port = %d", port);
return (USB_FAILURE);
}
return (USB_FAILURE);
}
/* only get bos descr the first time */
if (rval != USB_SUCCESS) {
"wusb_get_dev_uwb_descr: failed to "
"get bos descriptor");
return (rval);
}
sizeof (usb_uwb_cap_descr_t), KM_SLEEP);
"wusb_get_dev_uwb_descr: parsed uwb descr size is %d",
(int)size);
if (size < USB_UWB_CAP_DESCR_SIZE) {
sizeof (usb_uwb_cap_descr_t));
return (USB_FAILURE);
}
/* store a parsed uwb descriptor */
} else {
"wusb_get_dev_uwb_descr: already done");
}
return (USB_SUCCESS);
}
/* Get WUSB device BOS descr cloud, refer to WUSB 1.0/7.4.1 */
int
{
int rval;
"wusb_get_bos_cloud: ");
KM_SLEEP);
USB_DESCR_TYPE_BOS << 8,
0,
&pdata,
0,
&cb_flags,
0)) == USB_SUCCESS) {
/* this must be true since we didn't allow data underruns */
"device returned incorrect bos "
"descriptor size.");
rval = USB_FAILURE;
goto done;
}
/*
* Parse the bos descriptor
*/
sizeof (usb_bos_descr_t));
/* if parse bos descr error, it should return failure */
if (size == USB_PARSE_ERROR) {
"device returned incorrect "
"bos descriptor type.");
}
rval = USB_FAILURE;
goto done;
}
"device returned incorrect "
"bos descriptor size.");
rval = USB_FAILURE;
goto done;
}
/* Now fetch the complete bos cloud */
USB_DESCR_TYPE_BOS << 8,
0,
&pdata,
0,
&cb_flags,
0)) == USB_SUCCESS) {
"device returned incorrect "
"bos descriptor cloud.");
rval = USB_FAILURE;
goto done;
}
/*
* copy bos descriptor into usba_device
*/
"bos_length = %d",
}
}
done:
if (rval != USB_SUCCESS) {
"wusb_get_bos_cloud: "
"error in retrieving bos descriptor, rval=%d cr=%d",
}
if (pdata) {
}
return (rval);
}
/* Get WUSB device security descriptors, refer to WUSB 1.0/7.4.5 */
int
{
int i, rval;
uint8_t *p;
if (rval != USB_SUCCESS) {
"wusb_get_dev_security_descr "
return (rval);
}
"received incorrect security descriptor size");
rval = USB_FAILURE;
goto done;
}
/* Parse the security descriptor */
sizeof (usb_security_descr_t));
/* check if the parsed descr is good */
if (size < USB_SECURITY_DESCR_SIZE) {
rval = USB_FAILURE;
goto done;
}
"device returned incorrect security descriptor size");
rval = USB_FAILURE;
goto done;
}
/* Now fetch the complete security descr cloud */
if (rval != USB_SUCCESS) {
"wusb_get_dev_security_descr "
goto done;
}
"received incorrect security descriptor cloud size");
rval = USB_FAILURE;
goto done;
}
for (i = 0; i < secrt_data->secrt_n_encry; i++) {
&secrt_data->secrt_encry_descr[i],
sizeof (usb_encryption_descr_t));
if (size < USB_ENCRYPTION_DESCR_SIZE) {
"parse %dth encryption descr failed", i);
rval = USB_FAILURE;
goto done;
}
}
done:
if (rval != USB_SUCCESS) {
"wusb_get_dev_security_descr: "
"error in retrieving security descriptors");
if (secrt_data->secrt_encry_descr) {
}
}
if (pdata) {
}
return (rval);
}
/* Get WUSB device status, refer to WUSB 1.0/7.3.1.2 */
int
{
int rval;
if (rval != USB_SUCCESS) {
return (rval);
}
return (USB_FAILURE);
}
"received incorrect dev status size");
return (USB_FAILURE);
}
if ((selector == WUSB_STS_TYPE_MAS_AVAIL) &&
(len == WUSB_SET_WUSB_MAS_LEN)) {
"mas_avail: %x %x %x %x %x %x %x %x %x %x %x %x "
"%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x "
"%x %x %x %x", p[0], p[1], p[2], p[3], p[4], p[5], p[6],
p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15],
p[16], p[17], p[18], p[19], p[20], p[21], p[22], p[23],
p[24], p[25], p[26], p[27], p[28], p[29], p[30], p[31]);
}
return (USB_SUCCESS);
}
/* test function, can be removed */
void
{
int i, rval;
for (i = 0; i < 10; i++) {
"wusb_test_ctrlreq %d started:", i);
if (rval != USB_SUCCESS) {
"get mas availability status %d failed, "
"rval = %d", i, rval);
continue;
}
}
}
/* test function, can be removed */
void
{
int i, j, rval;
for (j = 0; j < 10; j++) {
for (i = 0; i < len; i++) {
}
"wusb_test_loopback_write %d start:", j);
if (rval != USB_SUCCESS) {
"wusb_test_loopback_write %d failed, "
return;
}
}
}
/* test function, can be removed */
void
{
int i, rval;
if (value == -1) {
"wusb_test_write: cannot find ccm encryption type");
return;
}
/* failed at 2nd write */
for (i = 0; i < 1; i++) {
"wusb_test_write %d start:", i);
if (rval != USB_SUCCESS) {
"wusb_test_write: %dth set encryption failed", i);
continue;
}
}
}
/* enable CCM encryption on the device */
int
{
int rval;
"wusb_enable_dev_encrypt:enter");
if (value == -1) {
"wusb_enable_dev_encrypt: cannot find ccm encryption type");
return (USB_FAILURE);
}
if (rval != USB_SUCCESS) {
"wusb_enable_dev_encrypt: set encryption failed");
}
"wusb_enable_dev_encrypti:exit");
return (rval);
}
/*
* Perform the authentication process, refer to WUSB 1.0/7.1.2.
* host secrt_data will be used for 4-way handshake
*/
/* ARGSUSED */
int
{
"wusb_hc_auth_dev: port %d invalid", port);
return (USB_INVALID_ARGS);
}
/* get device security descrs */
"wusb_hc_auth_dev: failed to get device security descrs");
return (USB_FAILURE);
}
/*
* enable CCM encryption on the device, this needs to be done
* before 4-way handshake. [WUSB 1.0/7.3.2.5]
*/
"wusb_hc_auth_dev: set encryption failed");
return (USB_FAILURE);
}
/* this seems to relieve the non-response issue somehow */
/* unauthenticated state */
/* check cc_list for existing cc with the same CDID */
"wusb_hc_auth_dev: no matching cc found");
if (dev_info->wdev_is_newconn == 0) {
"wusb_hc_auth_dev: not new connection, "
"just fail");
return (USB_FAILURE);
}
/* now we simply return not supported */
"wusb_hc_auth_dev: numeric association not supported");
return (USB_NOT_SUPPORTED);
}
"wusb_hc_auth_dev: matching cc found 0x%p",
USB_SUCCESS) {
"usb_pipe_open failed");
return (USB_FAILURE);
}
/* recording the default pipe */
/* perform 4-way handshake */
"port(%d) 4-way handshake authentication failed!",
port);
/* perhaps resetting the device is better */
(void) wusb_dev_set_encrypt(child_ph, 0);
return (USB_FAILURE);
}
return (USB_SUCCESS);
}
/* Acknowledge WUSB Device Disconnect notification, refer to WUSB 1.0/7.6.2 */
int
{
int rval;
/*
* the scheme ensures each time only one device addr
* is set each time
*/
if (!disconn_ie) {
return (USB_NO_RESOURCES);
}
/* padding, no active wusb device addr will be 1 */
&iehdl);
if (rval != USB_SUCCESS) {
"wusb_hc_ack_disconn: get ie handle fails");
return (rval);
}
if (rval != USB_SUCCESS) {
"wusb_hc_ack_disconn: add dev disconnect ie fails");
return (rval);
}
/*
* WUSB 1.0/7.5.4 requires the IE to be transmitted at least
* 100ms before ceasing, wait for 150ms here
*/
/* cease transmitting the IE */
return (USB_SUCCESS);
}
/* create child devinfo node and usba_device structure */
int
{
/* grab the mutex to keep warlock happy */
/* store the usba_device point in the dip */
return (USB_SUCCESS);
}
/*
* Handle WUSB child device connection, including creating child devinfo
* and usba strutures, authentication, configuration and attach.
*/
int
{
int rval;
int child_created = 0;
int ackie_removed = 0;
"wusb_hc_handle_port_connect: hc_data=0x%p, port=%d",
"wusb_hc_handle_port_connect: port %d invalid", port);
return (USB_INVALID_ARGS);
}
/* prepare child devinfo and usba structures */
} else {
"device",
dip,
&child_dip);
if (rval != USB_SUCCESS) {
return (rval);
}
KM_SLEEP);
child_created = 1;
}
/* do necessary setup */
/*
* TODO: now only consider the situation that HWA is high
* speed dev for the children. The situation that HWA is
* connected to the USB 1.1 port is not considered. The
* available HWA devices can't work behind USB1.1 port.
*/
/*
* 255 for WUSB devices, refer to WUSB 1.0/4.8.1.
* default ctrl pipe will ignore this value
*/
sizeof (usb_dev_descr_t));
/*
* set device info and encryption mode for the host so that
* open child pipe can work later
*/
if (rval != USB_SUCCESS) {
"wusb_hc_handle_port_connect: set device info for"
" host failed, rval = %d", rval);
goto error;
}
/* set the host to unsecure mode before authentication starts */
if (rval != USB_SUCCESS) {
"wusb_hc_handle_port_connect:set unsecure encryption"
" for host failed, rval = %d", rval);
goto error;
}
/*
* Open the default pipe for the child device
* the MaxPacketSize for the default ctrl pipe is
* set in usba_init_pipe_handle().
*/
USB_SUCCESS) {
"wusb_hc_handle_port_connect:open default pipe failed (%d)",
rval);
goto error;
}
/* recording the default pipe */
/* verify the default child pipe works */
"wusb_hc_handle_port_connect: failed to get"
" device uwb descr");
goto error;
}
/* remove connect acknowledge IE */
ackie_removed = 1;
/* do authentication */
USB_SUCCESS) {
"wusb_hc_handle_port_connect: "
"device authentication fails");
goto error;
}
/* online child */
/* post reconnect event to child */
} else {
"wusb_hc_handle_port_connect: create child fails");
goto error;
}
}
return (USB_SUCCESS);
}
if (child_created) {
if (rval != USB_SUCCESS) {
"wusb_hc_handle_port_connect: "
"failure to remove child node");
}
/* no need to unset address for WUSB */
}
if (ackie_removed == 0) {
}
return (USB_FAILURE);
}
/*
* Handle device connect notification: assign port number, acknowledge
* device connection, and online child
* Refer to WUSB 1.0 4.13, 6.10, 7.1 for connection process handling
* and device state diagram
*/
void
{
usb_port_t port = 0;
if (len < WUSB_DN_CONN_PKT_LEN) {
"wusb_hc_handle_dn_connect: short pkt len %d", (int)len);
return;
}
/*
* check if the device requesting to connect was ever connected
* and decide connect request type
*/
/*
* the device with the CDID was not connected.
* It should be a connect or new connect request
*/
if (addr) {
/*
* the device may have been disconnected by the host
* the host expects to see a connect request instead
* of a reconnect request. The reconnect request is
* ignored.
*/
"wusb_hc_handle_dn_connect: device has "
"disconnected, need to connect again");
return;
}
/* assign port number */
if (port == 0) {
"wusb_hc_handle_dn_connect: cannot find "
"a free port for the device connecting");
return;
}
/* initialize dev_info structure */
/* unconnected dev addr is 0xff, refer to WUSB 1.0/7.6.1 */
new_alloc = 1;
} else {
/*
* the device with the CDID was found connected.
* It should be a reconnect or connect request.
*/
} else if (addr == 0) {
} else {
"wusb_hc_handle_dn_connect: reconnecting, but "
"device addr doesn't match");
return;
}
/*
* post removal event to child device before
* reconnecting it
*/
}
/* refer to WUSB 1.0/7.6.1/4.13 for how New Connection bit works */
if (addr == 0) {
} else {
dev_info->wdev_is_newconn = 0;
}
/*
* state=connting means new dev addr needs to be assigned
* new_alloc=1 means newly allocated dev_info structure needs to
* be freed later if the connection process fails
* To simplify, the assigned address corresponds to the faked
* port number.
*/
}
/*
* Acknowledge dn connect notification.
* The notif queue scheme will ensure only one ack_ie exists
* at one time. Don't deal with multiple ack_ie elements now
*/
"wusb_hc_handle_dn_connect: acknowledge "
"connection fails");
if (new_alloc == 1) {
} else {
}
return;
}
/*
* Handle device connection according to connect request type
* Connect Acknowledge IE is removed inside the function
*/
USB_SUCCESS) {
"wusb_hc_handle_dn_connect: connect port %d fails", port);
if (new_alloc == 1) {
sizeof (usb_encryption_descr_t) *
}
if (dev_info->wdev_uwb_descr) {
sizeof (usb_uwb_cap_descr_t));
}
} else {
}
if (pathname) {
/* output error message to syslog */
" on WUSB port %d fails",
port);
}
return;
}
}
/* Handle device disconnect notification, refer to WUSB 1.0/7.6.2 */
void
{
if (len < WUSB_DN_DISCONN_PKT_LEN) {
"wusb_hc_handle_dn_disconnect: short pkt len %d",
(int)len);
return;
}
/* send WDEV_DISCONNECT_IE to acknowledge the notification */
"wusb_hc_handle_dn_disconnect: send disconnect ie fails");
return;
}
/* offline the device requesting disconnection */
} else {
"wusb_hc_handle_dn_disconnect: device with addr "
"0x%x not found", addr);
}
}
/* post disconnect event to the device driver */
void
{
}
/* post reconnect event to the device driver */
void
{
}
/* configure child device and online it */
int
{
int rval;
return (rval);
}
/* offline child device */
int
{
int rval;
return (rval);
}
/*
* ***********************
* CC management functions
* ***********************
*/
/* add a CC to the CC list */
void
{
"wusb_hc_add_cc: cc_list = 0x%p, new_cc = 0x%p",
return;
}
return;
}
/* update an existing CC */
return;
}
/* add a new CC */
return;
}
}
}
/* remove a CC from the CC list */
void
{
return;
}
return;
}
return;
}
}
}
/* remove all CCs from the list */
void
{
}
}
/* Send Host Disconnect notification */
int
{
int rval;
&iehdl);
if (rval != USB_SUCCESS) {
"wusb_hc_send_host_disconnect: get ie handle fails");
return (rval);
}
if (rval != USB_SUCCESS) {
"wusb_hc_send_host_disconnect: add host "
"disconnect ie fails");
return (rval);
}
return (USB_SUCCESS);
}
/* Get RC dev_t by HC dip */
int
{
int found = 0;
int inst;
/* For WHCI, RC and HC share the same dip */
/* need to change when whci driver is ready */
found = 1;
} else {
/* For HWA, RC and HC share the same parent dip */
found = 1;
// minor = HWAHC_CONSTRUCT_MINOR(inst);
/*
* now hwarc driver uses inst# as minor#.
* this may change
*/
break;
}
}
}
if (found == 0) {
*dev = 0;
return (USB_FAILURE);
}
"wusb_get_rc_dev_by_hc: rc device(%s%d) major = %d, minor = %d",
return (USB_SUCCESS);
}
/* format nonce to a buffer according to WUSB Table 6-3 */
static void
{
int i, offset;
}
if (sfn_only) {
return;
}
}
/* Call the crypto framework to compute CCM MAC data */
static int
{
int ret;
return (ret);
}
/*
* Since we've known the encrypted data is none (l(m) = 0),
* the middle procedure crypto_encrypt_update() is ignored.
* The last 8-byte MAC is calculated directly.
*/
return (ret);
}
return (CRYPTO_SUCCESS);
}
/* Pseudo-Random Function according to WUSB 1.0/6.5 */
int
{
/* from WUSB 6.4 */
lm = 0;
offset = 0;
if (ret != CRYPTO_SUCCESS) {
return (ret);
};
offset += CCM_MAC_LEN;
}
return (CRYPTO_SUCCESS);
}
/* rbuf is a 16-byte buffer to store the random nonce */
int
{
uchar_t a[] = "Random Numbers";
n.sfn = 0;
p = kbuf;
p += sizeof (uint16_t);
p += sizeof (uint16_t);
p += sizeof (uint32_t);
}
/* Set WUSB device encryption type, refer to WUSB 1.0/7.3.2.2 */
int
{
}
/*
* Set WUSB device key descriptor, refer to WUSB 1.0/7.3.2.4
* ph - Device's default control pipe
* key_index - Key Index
*/
int
{
int rval;
return (USB_FAILURE);
}
return (rval);
}
/*
* Set encryption type for the specified device.
*/
int
{
int rval;
"wusb_hc_set_encrypt: set encryption type %d "
}
return (rval);
}
/*
* Set Device Key for WUSB host, refer to WUSB 1.0/8.5.3.8
* Call the HC's specific set_ptk function to set PTK for a device
* len: length of key_data
*/
int
{
int rval;
uint8_t *p;
return (USB_INVALID_ARGS);
}
USB_SUCCESS) {
"wusb_hc_set_pkt: set ptk for port %d failed", port);
}
return (rval);
}
/*
* Set GTK for a host
* Call HC's specific set_gtk function
*
* Default gtk is set at hc_initial_start, and to be changed whenever
* a device leaves the current group (refer to WUSB spec 6.2.11.2)
*/
int
{
int rval;
uint8_t *p;
return (USB_INVALID_ARGS);
}
USB_SUCCESS) {
"wusb_hc_set_gkt: set gtk failed");
}
return (rval);
}
/* Set Device Info for WUSB host, refer to WUSB 1.0/8.5.3.7 */
int
{
int rval;
"wusb_hc_set_device_info: port = %d", port);
if (rval != USB_SUCCESS) {
"wusb_hc_set_device_info: the host failed to set "
"device info, rval = %d", rval);
}
return (rval);
}
/*
* step = 1, 2, 3
*/
int
{
int rval;
if (step == 2) {
/* get handshake */
/* set handshake */
return (USB_NO_RESOURCES);
}
} else {
/* step value is invalid */
return (USB_INVALID_ARGS);
}
if (step == 2) {
if (pdata) {
}
} else {
}
return (rval);
}
/* search the security descrs for CCM encryption type descr */
{
int i;
for (i = 0; i < secrt_data->secrt_n_encry; i++) {
"ccm encryption value is %d", value);
break;
}
}
return (value);
}
static void
{
uint8_t *p;
"handshake %d data:", step);
"(CDID)%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
p[10], p[11], p[12], p[13], p[14], p[15]);
"(Nonce)%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9],
p[10], p[11], p[12], p[13], p[14], p[15]);
"(MIC)%x %x %x %x %x %x %x %x",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
}
/* ARGSUSED */
/*
* Do 4way handshake and other necessary control operations to
* transit the device to authenticated state
* refer to WUSB 1.0 [7.3.2.5, 6.2.10.9.1, 7.1.2]
* ph - pipe handle of the host controller
*/
int
{
int rval;
"wusb_4way_handshake: port = %d", port);
return (USB_FAILURE);
}
return (USB_FAILURE);
}
/* tkid is generated dynamically and saved in dev_info */
/* handshake 1 */
!= USB_SUCCESS) {
"Nonce generation failed: %d", rval);
goto done;
}
"wusb_4way_handshake: shake 1.............");
if (rval != USB_SUCCESS) {
"handshake 1 failed, rval = %d", rval);
goto done;
}
/* handshake 2 */
"wusb_4way_handshake: shake 2.............");
if (rval != USB_SUCCESS) {
"handshake 2 failed, rval = %d", rval);
goto done;
}
rval = USB_FAILURE;
goto done;
}
/* derived session keys, refer to WUSB 1.0/6.5.1 */
n.sfn = 0;
if (rval != 0) {
"compute keys failed, rval = %d", rval);
goto done;
}
/* sfn was changed in PRF(). Need to reset it to 0 */
n.sfn = 0;
/* used the derived KCK to verify received MIC (WUSB 1.0/6.5.2] */
if (rval != 0) {
"compute MIC failed, rval = %d", rval);
goto done;
}
"verify mic failed");
rval = USB_FAILURE;
goto done;
}
/* handshake 3 */
n.sfn = 0;
if (rval != 0) {
goto done;
}
"wusb_4way_handshake: shake 3.............");
if (rval != USB_SUCCESS) {
"handshake 3 failed, rval = %d", rval);
goto done;
}
/* set PTK for host */
"wusb_4way_handshake: set ptk .............");
if (rval != USB_SUCCESS) {
"set ptk for host failed, rval = %d", rval);
goto done;
}
/*
* enable CCM encryption on the host
* according to WUSB 1.0/7.1.2, the encryption mode must be
* enabled before setting GTK onto device
*/
"wusb_4way_handshake: hc set encrypt .............");
if (rval != USB_SUCCESS) {
"set encryption for host failed, rval = %d", rval);
goto done;
}
/*
* set GTK for device
* GTK is initialized when hc_data is inited
*/
done:
if (rval != USB_SUCCESS) {
/* restore the host to unsecure mode */
}
return (rval);
}