Exemplo n.º 1
0
/* This is our function to emulate usb_control_msg() but give us enough
 * access to make aborts/resets work
 */
int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
			 u8 request, u8 requesttype, u16 value, u16 index, 
			 void *data, u16 size)
{
	int status;
	struct usb_ctrlrequest *dr;

	/* allocate the device request structure */
	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
	if (!dr)
		return -ENOMEM;

	/* fill in the structure */
	dr->bRequestType = requesttype;
	dr->bRequest = request;
	dr->wValue = cpu_to_le16(value);
	dr->wIndex = cpu_to_le16(index);
	dr->wLength = cpu_to_le16(size);

	/* set up data structures for the wakeup system */
	init_completion(&us->current_done);

	/* lock the URB */
	down(&(us->current_urb_sem));

	/* fill the URB */
	FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, 
			 (unsigned char*) dr, data, size, 
			 usb_stor_blocking_completion, &us->current_done);
	us->current_urb->actual_length = 0;
	us->current_urb->error_count = 0;
	us->current_urb->transfer_flags = USB_ASYNC_UNLINK;
	us->current_urb->status = 0;

	/* submit the URB */
	status = usb_submit_urb(us->current_urb);
	if (status) {
		/* something went wrong */
		up(&(us->current_urb_sem));
		kfree(dr);
		return status;
	}

	/* wait for the completion of the URB */
	up(&(us->current_urb_sem));
	wait_for_completion(&us->current_done);
	down(&(us->current_urb_sem));

	/* return the actual length of the data transferred if no error*/
	status = us->current_urb->status;
	if (status == -ENOENT)
		status = -ECONNRESET;
	if (status >= 0)
		status = us->current_urb->actual_length;

	/* release the lock and return status */
	up(&(us->current_urb_sem));
	kfree(dr);
  	return status;
}
Exemplo n.º 2
0
/*
 *  This is our function to emulate USBH_SendCtrlMsg() but give us enough
 *  access to make aborts/resets work
 */
static int  usb_stor_control_msg(UMAS_DATA_T *umas, uint32_t pipe,
                                 uint8_t request, uint8_t requesttype, uint16_t value,
                                 uint16_t index, void *data, uint16_t size)
{
    URB_T       *urb = umas->current_urb;
    int         status;
    volatile int t0;
    DEV_REQ_T   dr;

    /* fill in the structure */
    dr.requesttype = requesttype;
    dr.request = request;
    dr.value = value;
    dr.index = index;
    dr.length = size;

    /* fill the URB */
    FILL_CONTROL_URB(urb, umas->pusb_dev, pipe, (uint8_t *)&dr, data, size,
                     usb_stor_blocking_completion, NULL);
    urb->actual_length = 0;
    urb->error_count = 0;
    urb->transfer_flags = USB_ASYNC_UNLINK;

    _UmasUrbComplete = 0;

    /* submit the URB */
    status = USBH_SubmitUrb(urb);
    if(status)
        return status;

    /* wait for the completion of the URB */
#if 1
    for(t0 = 0; t0 < 0x8000000; t0++)
    {
        if(is_urb_completed())
            break;
    }
    if(t0 >= 0x8000000)
#else
    t0 = umas_get_ticks();
    while(umas_get_ticks() - t0 < 300)
    {
        if(is_urb_completed())
            break;
    }

    if(umas_get_ticks() - t0 >= 300)
#endif
    {
        UMAS_DEBUG("usb_stor_control_msg time-out failed!\n");
        return USB_ERR_TIMEOUT;
    }

    /* return the actual length of the data transferred if no error*/
    status = urb->status;
    if(status >= 0)
        status = urb->actual_length;

    return status;
}
Exemplo n.º 3
0
static int hci_usb_ctrl_msg(struct hci_usb *husb, struct sk_buff *skb)
{
	struct urb *urb = husb->ctrl_urb;
	devrequest *dr  = &husb->dev_req;
	int pipe, status;

	DBG("%s len %d", husb->hdev.name, skb->len);

	pipe = usb_sndctrlpipe(husb->udev, 0);

	dr->requesttype = HCI_CTRL_REQ;
	dr->request = 0;
	dr->index   = 0;
	dr->value   = 0;
	dr->length  = cpu_to_le16(skb->len);

	FILL_CONTROL_URB(urb, husb->udev, pipe, (void*)dr, skb->data, skb->len,
	                 hci_usb_ctrl, skb);

	if ((status = usb_submit_urb(urb))) {
		DBG("%s control URB submit failed %d", husb->hdev.name, status);
		return status;
	}

	return 0;
}
Exemplo n.º 4
0
/* Completion handler for dummy retry packet */
static void auerswald_ctrlread_wretcomplete(struct urb *urb)
{
	struct auerbuf *bp = (struct auerbuf *) urb->context;
	struct auerswald *cp;
	int ret;
	dbg("auerswald_ctrlread_wretcomplete called");
	dbg("complete with status: %d", urb->status);
	cp = ((struct auerswald *) ((char *) (bp->list) -
				    (unsigned
				     long) (&((struct auerswald *) 0)->
					    bufctl)));

	/* check if it is possible to advance */
	if (!auerswald_status_retry(urb->status) || !cp->usbdev) {
		/* reuse the buffer */
		err("control dummy: transmission error %d, can not retry",
		    urb->status);
		auerbuf_releasebuf(bp);
		/* Wake up all processes waiting for a buffer */
		wake_up(&cp->bufferwait);
		return;
	}

	/* fill the control message */
	bp->dr->bRequestType = AUT_RREQ;
	bp->dr->bRequest = AUV_RBLOCK;
	bp->dr->wLength = bp->dr->wValue;	/* temporary stored */
	bp->dr->wValue = cpu_to_le16(1);	/* Retry Flag */
	/* bp->dr->wIndex    = channel id;          remains */
	FILL_CONTROL_URB(bp->urbp, cp->usbdev,
			 usb_rcvctrlpipe(cp->usbdev, 0),
			 (unsigned char *) bp->dr, bp->bufp,
			 le16_to_cpu(bp->dr->wLength),
			 (usb_complete_t) auerswald_ctrlread_complete, bp);

	/* submit the control msg as next paket */
	ret = auerchain_submit_urb_list(&cp->controlchain, bp->urbp, 1);
	if (ret) {
		dbg("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
		bp->urbp->status = ret;
		auerswald_ctrlread_complete(bp->urbp);
	}
}
Exemplo n.º 5
0
static void
ecos_usbeth_set_rx_mode(struct net_device* net)
{
    ecos_usbeth* usbeth         = (ecos_usbeth*) net->priv;
    __u16        promiscuous    = net->flags & IFF_PROMISC;
    int          res;
    
    if (promiscuous != usbeth->target_promiscuous) {
        devrequest*     req;
        urb_t*          urb;

        urb = usb_alloc_urb(0);
        if ((urb_t*)0 == urb) {
            return;
        }
        req = kmalloc(sizeof(devrequest), GFP_KERNEL);
        if ((devrequest*)0 == req) {
            usb_free_urb(urb);
            return;
        }
        req->requesttype        = USB_TYPE_CLASS | USB_RECIP_DEVICE;
        req->request            = ECOS_USBETH_CONTROL_SET_PROMISCUOUS_MODE;
        req->value              = cpu_to_le16p(&promiscuous);
        req->index              = 0;
        req->length             = 0;

        FILL_CONTROL_URB(urb,
                         usbeth->usb_dev,
                         usb_sndctrlpipe(usbeth->usb_dev, 0),
                         (unsigned char*) req,
                         (void*) 0,
                         0,
                         &ecos_usbeth_set_rx_mode_callback,
                         (void*) usbeth);
        res = usb_submit_urb(urb);
        if (0 != res) {
            kfree(req);
            usb_free_urb(urb);
        } else {
            usbeth->target_promiscuous = promiscuous;
        }
    }
}
Exemplo n.º 6
0
/* Open the D-channel once more */
static void auerisdn_dcopen(unsigned long data)
{
	struct auerswald *cp = (struct auerswald *) data;
	struct auerbuf *bp;
	int ret;

	if (cp->disconnecting)
		return;
	dbg("auerisdn_dcopen running");

	/* get a buffer for the command */
	bp = auerbuf_getbuf(&cp->bufctl);
	/* if no buffer available: can't change the mode */
	if (!bp) {
		err("auerisdn_dcopen: no data buffer available");
		return;
	}

	/* fill the control message */
	bp->dr->bRequestType = AUT_WREQ;
	bp->dr->bRequest = AUV_CHANNELCTL;
	bp->dr->wValue = cpu_to_le16(1);
	bp->dr->wIndex = cpu_to_le16(0);
	bp->dr->wLength = cpu_to_le16(0);
	FILL_CONTROL_URB(bp->urbp, cp->usbdev,
			 usb_sndctrlpipe(cp->usbdev, 0),
			 (unsigned char *) bp->dr, bp->bufp, 0,
			 (usb_complete_t) auerisdn_dcopen_complete, bp);

	/* submit the control msg */
	ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
	dbg("dcopen submitted");
	if (ret) {
		bp->urbp->status = ret;
		auerisdn_dcopen_complete(bp->urbp);
	}
	return;
}
Exemplo n.º 7
0
static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size)
{
	int ret;

	if (test_bit(RX_REG_SET, &dev->flags))
		return -EAGAIN;

	dev->dr.bRequestType = RTL8150_REQT_WRITE;
	dev->dr.bRequest = RTL8150_REQ_SET_REGS;
	dev->dr.wValue = cpu_to_le16(indx);
	dev->dr.wIndex = 0;
	dev->dr.wLength = cpu_to_le16(2);
	dev->ctrl_urb->transfer_buffer_length = 2;
	FILL_CONTROL_URB(dev->ctrl_urb, dev->udev,
			 usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr,
			 &dev->rx_creg, 2, ctrl_callback, dev);
	if ((ret = usb_submit_urb(dev->ctrl_urb)))
		err("control request submission failed: %d", ret);
	else
		set_bit(RX_REG_SET, &dev->flags);

	return ret;
}
/* Decide if we need to issue a control message and do so. Must be called with pm->lock down */
static void powermate_sync_state(struct powermate_device *pm)
{
	if(pm->requires_update == 0) 
		return; /* no updates are required */
	if(pm->config.status == -EINPROGRESS) 
		return; /* an update is already in progress; it'll issue this update when it completes */

	if(pm->requires_update & UPDATE_PULSE_ASLEEP){
		pm->configdr.wValue = cpu_to_le16( SET_PULSE_ASLEEP );
		pm->configdr.wIndex = cpu_to_le16( pm->pulse_asleep ? 1 : 0 );
		pm->requires_update &= ~UPDATE_PULSE_ASLEEP;
	}else if(pm->requires_update & UPDATE_PULSE_AWAKE){
		pm->configdr.wValue = cpu_to_le16( SET_PULSE_AWAKE );
		pm->configdr.wIndex = cpu_to_le16( pm->pulse_awake ? 1 : 0 );
		pm->requires_update &= ~UPDATE_PULSE_AWAKE;
	}else if(pm->requires_update & UPDATE_PULSE_MODE){
		int op, arg;
		/* the powermate takes an operation and an argument for its pulse algorithm.
		   the operation can be:
		   0: divide the speed
		   1: pulse at normal speed
		   2: multiply the speed
		   the argument only has an effect for operations 0 and 2, and ranges between
		   1 (least effect) to 255 (maximum effect).
       
		   thus, several states are equivalent and are coalesced into one state.

		   we map this onto a range from 0 to 510, with:
		   0 -- 254    -- use divide (0 = slowest)
		   255         -- use normal speed
		   256 -- 510  -- use multiple (510 = fastest).

		   Only values of 'arg' quite close to 255 are particularly useful/spectacular.
		*/    
		if(pm->pulse_speed < 255){
			op = 0;                   // divide
			arg = 255 - pm->pulse_speed;
		}else if(pm->pulse_speed > 255){
			op = 2;                   // multiply
			arg = pm->pulse_speed - 255;
		}else{
			op = 1;                   // normal speed
			arg = 0;                  // can be any value
		}
		pm->configdr.wValue = cpu_to_le16( (pm->pulse_table << 8) | SET_PULSE_MODE );
		pm->configdr.wIndex = cpu_to_le16( (arg << 8) | op );
		pm->requires_update &= ~UPDATE_PULSE_MODE;
	}else if(pm->requires_update & UPDATE_STATIC_BRIGHTNESS){
		pm->configdr.wValue = cpu_to_le16( SET_STATIC_BRIGHTNESS );
		pm->configdr.wIndex = cpu_to_le16( pm->static_brightness );
		pm->requires_update &= ~UPDATE_STATIC_BRIGHTNESS;
	}else{
		printk(KERN_ERR "powermate: unknown update required");
		pm->requires_update = 0; /* fudge the bug */
		return;
	}

	pm->config.dev = pm->udev; /* is this necessary? */
	pm->configdr.bRequestType = 0x41; /* vendor request */
	pm->configdr.bRequest = 0x01;
	pm->configdr.wLength = 0;

        FILL_CONTROL_URB(&pm->config, pm->udev, usb_sndctrlpipe(pm->udev, 0), 
			 (void*)&pm->configdr, 0, 0, powermate_config_complete, pm);	

	if(usb_submit_urb(&pm->config))
		printk(KERN_ERR "powermate: usb_submit_urb(config) failed");
}
Exemplo n.º 9
0
int __devinit st5481_setup_usb(struct st5481_adapter *adapter)
{
	struct usb_device *dev = adapter->usb_dev;
	struct st5481_ctrl *ctrl = &adapter->ctrl;
	struct st5481_intr *intr = &adapter->intr;
	struct usb_interface_descriptor *altsetting;
	struct usb_endpoint_descriptor *endpoint;
	int status;
	urb_t *urb;
	u_char *buf;
	
	DBG(1,"");
	
	if ((status = usb_set_configuration (dev,dev->config[0].bConfigurationValue)) < 0) {
		WARN("set_configuration failed,status=%d",status);
		return status;
	}

	
	altsetting = &(dev->config->interface[0].altsetting[3]);	

	// Check if the config is sane
	if ( altsetting->bNumEndpoints != 7 ) {
		WARN("expecting 7 got %d endpoints!", altsetting->bNumEndpoints);
		return -EINVAL;
	}

	// The descriptor is wrong for some early samples of the ST5481 chip
	altsetting->endpoint[3].wMaxPacketSize = 32;
	altsetting->endpoint[4].wMaxPacketSize = 32;

	// Use alternative setting 3 on interface 0 to have 2B+D
	if ((status = usb_set_interface (dev, 0, 3)) < 0) {
		WARN("usb_set_interface failed,status=%d",status);
		return status;
	}

	// Allocate URB for control endpoint
	urb = usb_alloc_urb(0);
	if (!urb) {
		return -ENOMEM;
	}
	ctrl->urb = urb;
	
	// Fill the control URB
	FILL_CONTROL_URB (urb, dev, 
			  usb_sndctrlpipe(dev, 0),
			  NULL, NULL, 0, usb_ctrl_complete, adapter);

		
	fifo_init(&ctrl->msg_fifo.f, ARRAY_SIZE(ctrl->msg_fifo.data));

	// Allocate URBs and buffers for interrupt endpoint
	urb = usb_alloc_urb(0);
	if (!urb) { 
		return -ENOMEM;
	}
	intr->urb = urb;
	
	buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL);
	if (!buf) {
		return -ENOMEM;
	}

	endpoint = &altsetting->endpoint[EP_INT-1];
				
	// Fill the interrupt URB
	FILL_INT_URB(urb, dev,
		     usb_rcvintpipe(dev, endpoint->bEndpointAddress),
		     buf, INT_PKT_SIZE,
		     usb_int_complete, adapter,
		     endpoint->bInterval);
		
	return 0;
}
Exemplo n.º 10
0
/* D-channel transfer function L2->L1 */
static void auerisdn_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
{
	struct auerhisax *ahp;
	struct sk_buff *skb;
	unsigned int len;
	int ret;
	struct auerbuf *bp;
	struct auerswald *cp;
	unsigned long flags;
	unsigned int l2_index;
	unsigned char c;
	unsigned char l2_header[32];
	unsigned char *sp;

	dbg("hisax D-Channel l2l1 called");

	/* Get reference to auerhisax struct */
	cp = NULL;
	ahp = hisax_d_if->priv;
	if (ahp)
		cp = ahp->cp;
	if (cp && !cp->disconnecting) {
		/* normal usage */
		switch (pr) {
		case PH_ACTIVATE | REQUEST:	/* activation request */
			dbg("Activation Request");
			cp->isdn.dc_activated = 1;
			/* send activation back to layer 2 */
			auerisdn_d_l1l2(&cp->isdn,
					PH_ACTIVATE | INDICATION, NULL);
			break;
		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
			dbg("Deactivation Request");
			cp->isdn.dc_activated = 0;
			/* send deactivation back to layer 2 */
			auerisdn_d_l1l2(&cp->isdn,
					PH_DEACTIVATE | INDICATION, NULL);
			break;
		case PH_DATA | REQUEST:	/* Transmit data request */
			skb = (struct sk_buff *) arg;
			len = skb->len;
			l2_index = 0;
			sp = skb->data;
			dump("Data Request:", sp, len);

			/* Parse the L2 header */
			if (!len)
				goto phd_free;
			c = *sp++;	/* SAPI */
			l2_header[l2_index++] = c;
			len--;
			if (!len)
				goto phd_free;
			c = *sp++;	/* TEI */
			l2_header[l2_index++] = c;
			len--;
			if (!len)
				goto phd_free;
			c = *sp++;	/* Control Field, Byte 1 */
			len--;
			if (!(c & 0x01)) {
				/* I FRAME */
				dbg("I Frame");
				if (!len)
					goto phd_free;
				spin_lock_irqsave(&ahp->seq_lock, flags);
				ahp->rxseq = c + 2;	/* store new sequence info */
				spin_unlock_irqrestore(&ahp->seq_lock,
						       flags);
				sp++;	/* skip Control Field, Byte 2 */
				len--;
				/* Check for RELEASE command */
				/* and change to RELEASE_COMPLETE */
				if (sp[3] == 0x4D)
					sp[3] = 0x5A;
				goto phd_send;
			}
			/* check the frame type */
			switch (c) {
			case 0x03:	/* UI frame */
				dbg("UI Frame");
				if (l2_header[0] == 0xFC) {
					dbg("TEI Managment");
					l2_header[0] = 0xFE;	/* set C/R bit in answer */
					l2_header[l2_index++] = c;	/* Answer is UI frame */
					if (!len)
						break;
					c = *sp++;	/* Managment ID */
					len--;
					if (c != 0x0F)
						break;
					l2_header[l2_index++] = c;
					/* Read Reference Number */
					if (!len)
						break;
					l2_header[l2_index++] = *sp++;
					len--;
					if (!len)
						break;
					l2_header[l2_index++] = *sp++;
					len--;
					if (!len)
						break;
					c = *sp++;	/* Message Type */
					len--;
					switch (c) {
					case 0x01:	/* Identity Request */
						dbg("Identity Request");
						l2_header[l2_index++] = 0x02;	/* Identity Assign */
						l2_header[l2_index++] =
						    (AUISDN_TEI << 1) |
						    0x01;
						goto phd_answer;
					default:
						dbg("Unhandled TEI Managment %X", (int) c);
						break;
					}
					// throw away
					goto phd_free;
				}
				/* else send UI frame out */
				goto phd_send;
			case 0x01:	/* RR frame */
			case 0x05:	/* RNR frame */
				dbg("RR/RNR Frame");
				if (!len)
					break;
				c = *sp++;	/* Control Field, Byte 2 */
				len--;
				if (!(c & 0x01))
					break;	/* P/F = 1 in commands */
				if (l2_header[0] & 0x02)
					break;	/* C/R = 0 from TE */
				dbg("Send RR as answer");
				l2_header[l2_index++] = 0x01;	/* send an RR as Answer */
				spin_lock_irqsave(&ahp->seq_lock, flags);
				l2_header[l2_index++] = ahp->rxseq | 0x01;
				spin_unlock_irqrestore(&ahp->seq_lock,
						       flags);
				goto phd_answer;
			case 0x7F:	/* SABME */
				dbg("SABME");
				spin_lock_irqsave(&ahp->seq_lock, flags);
				ahp->txseq = 0;
				ahp->rxseq = 0;
				spin_unlock_irqrestore(&ahp->seq_lock,
						       flags);
				l2_header[l2_index++] = 0x73;	/* UA */
				goto phd_answer;
			case 0x53:	/* DISC */
				dbg("DISC");
				/* Send back a UA */
				l2_header[l2_index++] = 0x73;	/* UA */
				goto phd_answer;
			default:
				dbg("Unhandled L2 Message %X", (int) c);
				break;
			}
			/* all done */
			goto phd_free;

			/* we have to generate a local answer */
			/* first, confirm old message, free old skb */
		      phd_answer:auerisdn_d_confirmskb(cp,
					      skb);

			/* allocate a new skbuff */
			skb = dev_alloc_skb(l2_index);
			if (!skb) {
				err("no memory for new skb");
				break;
			}
			dump("local answer to L2 is:", l2_header,
			     l2_index);
			memcpy(skb_put(skb, l2_index), l2_header,
			       l2_index);
			auerisdn_d_l1l2(&cp->isdn, PH_DATA | INDICATION,
					skb);
			break;

			/* we have to send the L3 message out */
		      phd_send:if (!len)
				goto phd_free;	/* no message left */

			/* get a new data buffer */
			bp = auerbuf_getbuf(&cp->bufctl);
			if (!bp) {
				warn("no auerbuf free");
				goto phd_free;
			}
			/* protect against too big write requests */
			/* Should not happen */
			if (len > cp->maxControlLength) {
				err("too long D-channel paket truncated");
				len = cp->maxControlLength;
			}

			/* Copy the data */
			memcpy(bp->bufp + AUH_SIZE, sp, len);

			/* set the header byte */
			*(bp->bufp) =
			    cp->isdn.dchannelservice.
			    id | AUH_DIRECT | AUH_UNSPLIT;

			/* Set the transfer Parameters */
			bp->len = len + AUH_SIZE;
			bp->dr->bRequestType = AUT_WREQ;
			bp->dr->bRequest = AUV_WBLOCK;
			bp->dr->wValue = cpu_to_le16(0);
			bp->dr->wIndex =
			    cpu_to_le16(cp->isdn.dchannelservice.
					id | AUH_DIRECT | AUH_UNSPLIT);
			bp->dr->wLength = cpu_to_le16(len + AUH_SIZE);
			FILL_CONTROL_URB(bp->urbp, cp->usbdev,
					 usb_sndctrlpipe(cp->usbdev, 0),
					 (unsigned char *) bp->dr,
					 bp->bufp, len + AUH_SIZE,
					 auerisdn_dcw_complete, bp);
			/* up we go */
			ret =
			    auerchain_submit_urb(&cp->controlchain,
						 bp->urbp);
			if (ret)
				auerisdn_dcw_complete(bp->urbp);
			else
				dbg("auerisdn_dwrite: Write OK");
			/* confirm message, free skb */
		      phd_free:auerisdn_d_confirmskb(cp,
					      skb);
			break;

		default:
			warn("pr %#x\n", pr);
			break;
		}
	} else {
		/* hisax interface is down */
		switch (pr) {
		case PH_ACTIVATE | REQUEST:	/* activation request */
			dbg("D channel PH_ACTIVATE | REQUEST with interface down");
			/* don't answer this request! Endless... */
			break;
		case PH_DEACTIVATE | REQUEST:	/* deactivation request */
			dbg("D channel PH_DEACTIVATE | REQUEST with interface down");
			hisax_d_if->l1l2(hisax_d_if,
					 PH_DEACTIVATE | INDICATION, NULL);
			break;
		case PH_DATA | REQUEST:	/* Transmit data request */
			dbg("D channel PH_DATA | REQUEST with interface down");
			skb = (struct sk_buff *) arg;
			/* free data buffer */
			if (skb) {
				skb_pull(skb, skb->len);
				dev_kfree_skb_any(skb);
			}
			/* send confirmation back to layer 2 */
			hisax_d_if->l1l2(hisax_d_if, PH_DATA | CONFIRM,
					 NULL);
			break;
		default:
			warn("pr %#x\n", pr);
			break;
		}
	}
}
Exemplo n.º 11
0
/* Translate non-ETSI ISDN messages from the device */
static void auerisdn_translate_incoming(struct auerswald *cp,
					unsigned char *msg,
					unsigned int len)
{
	struct auerbuf *bp;
	int ret;

	/* Translate incomming CONNECT -> CONNECT_ACK */
	/* Format:   0   1    2     3     4        5        6    7      */
	/*         SAPI TEI TXSEQ RXSEQ PID=08 CREFLEN=01 CREF MSG=7 ...*/
	/* CREF.7 == 0 -> Incoming Call                                 */

	/* Check for minimum length */
	if (len < 8)
		return;

	/* Check for a CONNECT, call originated from device */
	if (((msg[6] & 0x80) == 0) && (msg[7] == 0x07)) {
		dbg("false CONNECT from device found");
		/* change into CONNECT_ACK */
		msg[7] = 0x0F;

		/* Send a CONNECT_ACK back to the device */

		/* get a new data buffer */
		bp = auerbuf_getbuf(&cp->bufctl);
		if (!bp) {
			warn("no auerbuf free");
			return;
		}

		/* Form a CONNECT ACK */
		bp->bufp[0] =
		    cp->isdn.dchannelservice.id | AUH_DIRECT | AUH_UNSPLIT;
		bp->bufp[1] = 0x08;
		bp->bufp[2] = 0x01;
		bp->bufp[3] = msg[6] | 0x80;
		bp->bufp[4] = 0x0F;

		/* Set the transfer Parameters */
		bp->len = 5;
		bp->dr->bRequestType = AUT_WREQ;
		bp->dr->bRequest = AUV_WBLOCK;
		bp->dr->wValue = cpu_to_le16(0);
		bp->dr->wIndex =
		    cpu_to_le16(cp->isdn.dchannelservice.
				id | AUH_DIRECT | AUH_UNSPLIT);
		bp->dr->wLength = cpu_to_le16(5);
		FILL_CONTROL_URB(bp->urbp, cp->usbdev,
				 usb_sndctrlpipe(cp->usbdev, 0),
				 (unsigned char *) bp->dr, bp->bufp, 5,
				 auerisdn_dcw_complete, bp);
		/* up we go */
		ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
		if (ret)
			auerisdn_dcw_complete(bp->urbp);
		else
			dbg("auerisdn_translate: Write OK");
	}
	/* Check for a DISCONNECT and change to RELEASE */
	if (msg[7] == 0x45) {
		dbg("DISCONNECT changed to RELEASE");
		msg[7] = 0x4D;
		return;
	}
}
Exemplo n.º 12
0
/* int completion handler. */
static void auerswald_int_complete(struct urb *urb)
{
	unsigned int channelid;
	unsigned int bytecount;
	int ret;
	struct auerbuf *bp = NULL;
	struct auerswald *cp = (struct auerswald *) urb->context;

	dbg("auerswald_int_complete called");

	/* do not respond to an error condition */
	if (urb->status != 0) {
		dbg("nonzero URB status = %d", urb->status);
		return;
	}

	/* check if all needed data was received */
	if (urb->actual_length < AU_IRQMINSIZE) {
		dbg("invalid data length received: %d bytes",
		    urb->actual_length);
		return;
	}

	/* check the command code */
	if (cp->intbufp[0] != AU_IRQCMDID) {
		dbg("invalid command received: %d", cp->intbufp[0]);
		return;
	}

	/* check the command type */
	if (cp->intbufp[1] != AU_BLOCKRDY) {
		dbg("invalid command type received: %d", cp->intbufp[1]);
		return;
	}

	/* now extract the information */
	channelid = cp->intbufp[2];
	bytecount = le16_to_cpup(&cp->intbufp[3]);

	/* check the channel id */
	if (channelid >= AUH_TYPESIZE) {
		dbg("invalid channel id received: %d", channelid);
		return;
	}

	/* check the byte count */
	if (bytecount > (cp->maxControlLength + AUH_SIZE)) {
		dbg("invalid byte count received: %d", bytecount);
		return;
	}
	dbg("Service Channel = %d", channelid);
	dbg("Byte Count = %d", bytecount);

	/* get a buffer for the next data paket */
	bp = auerbuf_getbuf(&cp->bufctl);
	/* if no buffer available: skip it */
	if (!bp) {
		dbg("auerswald_int_complete: no data buffer available");
		/* can we do something more?
		   This is a big problem: if this int packet is ignored, the
		   device will wait forever and not signal any more data.
		   The only real solution is: having enought buffers!
		   Or perhaps temporary disabling the int endpoint?
		 */
		return;
	}

	/* fill the control message */
	bp->dr->bRequestType = AUT_RREQ;
	bp->dr->bRequest = AUV_RBLOCK;
	bp->dr->wValue = cpu_to_le16(0);
	bp->dr->wIndex = cpu_to_le16(channelid | AUH_DIRECT | AUH_UNSPLIT);
	bp->dr->wLength = cpu_to_le16(bytecount);
	FILL_CONTROL_URB(bp->urbp, cp->usbdev,
			 usb_rcvctrlpipe(cp->usbdev, 0),
			 (unsigned char *) bp->dr, bp->bufp, bytecount,
			 (usb_complete_t) auerswald_ctrlread_complete, bp);

	/* submit the control msg */
	ret = auerchain_submit_urb(&cp->controlchain, bp->urbp);
	if (ret) {
		dbg("auerswald_int_complete: nonzero result of auerchain_submit_urb %d", ret);
		bp->urbp->status = ret;
		auerswald_ctrlread_complete(bp->urbp);
		/* here applies the same problem as above: device locking! */
	}
}
Exemplo n.º 13
0
/* completion handler for receiving of control messages */
static void auerswald_ctrlread_complete(struct urb *urb)
{
	unsigned int serviceid;
	struct auerswald *cp;
	struct auerscon *scp;
	struct auerbuf *bp = (struct auerbuf *) urb->context;
	int ret;
	dbg("auerswald_ctrlread_complete called");

	cp = ((struct auerswald *) ((char *) (bp->list) -
				    (unsigned
				     long) (&((struct auerswald *) 0)->
					    bufctl)));

	/* check if there is valid data in this urb */
	if (urb->status) {
		dbg("complete with non-zero status: %d", urb->status);
		/* should we do a retry? */
		if (!auerswald_status_retry(urb->status)
		    || !cp->usbdev || (cp->version < AUV_RETRY)
		    || (bp->retries >= AU_RETRIES)) {
			/* reuse the buffer */
			err("control read: transmission error %d, can not retry", urb->status);
			auerbuf_releasebuf(bp);
			/* Wake up all processes waiting for a buffer */
			wake_up(&cp->bufferwait);
			return;
		}
		bp->retries++;
		dbg("Retry count = %d", bp->retries);
		/* send a long dummy control-write-message to allow device firmware to react */
		bp->dr->bRequestType = AUT_WREQ;
		bp->dr->bRequest = AUV_DUMMY;
		bp->dr->wValue = bp->dr->wLength;	/* temporary storage */
		// bp->dr->wIndex    channel ID remains
		bp->dr->wLength = cpu_to_le16(32);	/* >= 8 bytes */
		FILL_CONTROL_URB(bp->urbp, cp->usbdev,
				 usb_sndctrlpipe(cp->usbdev, 0),
				 (unsigned char *) bp->dr, bp->bufp, 32,
				 (usb_complete_t)
				 auerswald_ctrlread_wretcomplete, bp);

		/* submit the control msg as next paket */
		ret =
		    auerchain_submit_urb_list(&cp->controlchain, bp->urbp,
					      1);
		if (ret) {
			dbg("auerswald_ctrlread_complete: nonzero result of auerchain_submit_urb_list %d", ret);
			bp->urbp->status = ret;
			auerswald_ctrlread_wretcomplete(bp->urbp);
		}
		return;
	}

	/* get the actual bytecount (incl. headerbyte) */
	bp->len = urb->actual_length;
	serviceid = bp->bufp[0] & AUH_TYPEMASK;
	dbg("Paket with serviceid %d and %d bytes received", serviceid,
	    bp->len);

	/* dispatch the paket */
	scp = cp->services[serviceid];
	if (scp) {
		/* look, Ma, a listener! */
		scp->dispatch(scp, bp);
	}

	/* release the paket */
	auerbuf_releasebuf(bp);
	/* Wake up all processes waiting for a buffer */
	wake_up(&cp->bufferwait);
}
Exemplo n.º 14
0
/* Setup a B channel transfer mode */
static void auerisdn_bmode(struct auerisdnbc *bc, unsigned int mode)
{
	struct auerswald *cp = bc->cp;
	struct auerbuf *bp;
	int ret;

	/* don't allow activation on disconnect */
	if (cp->disconnecting) {
		mode = L1_MODE_NULL;

		/* Else check if something changed */
	} else if (bc->mode != mode) {
		if ((mode != L1_MODE_NULL) && (mode != L1_MODE_TRANS)) {
			/* init RX hdlc decoder */
			dbg("rcv init");
			isdnhdlc_rcv_init(&bc->inp_hdlc_state, 0);
			/* init TX hdlc decoder */
			dbg("out init");
			isdnhdlc_out_init(&bc->outp_hdlc_state, 0, 0);
		}
		/* stop ASAP */
		if (mode == L1_MODE_NULL)
			bc->mode = mode;
		if ((bc->mode == L1_MODE_NULL) || (mode == L1_MODE_NULL)) {
			/* Activation or deactivation required */

			/* get a buffer for the command */
			bp = auerbuf_getbuf(&cp->bufctl);
			/* if no buffer available: can't change the mode */
			if (!bp) {
				err("auerisdn_bmode: no data buffer available");
				return;
			}

			/* fill the control message */
			bp->dr->bRequestType = AUT_WREQ;
			bp->dr->bRequest = AUV_CHANNELCTL;
			if (mode != L1_MODE_NULL)
				bp->dr->wValue = cpu_to_le16(1);
			else
				bp->dr->wValue = cpu_to_le16(0);
			bp->dr->wIndex =
			    cpu_to_le16(AUH_B1CHANNEL + bc->channel);
			bp->dr->wLength = cpu_to_le16(0);
			*bp->bufp = mode;
			FILL_CONTROL_URB(bp->urbp, cp->usbdev,
					 usb_sndctrlpipe(cp->usbdev, 0),
					 (unsigned char *) bp->dr,
					 bp->bufp, 0,
					 (usb_complete_t)
					 auerisdn_bmode_complete, bp);

			/* submit the control msg */
			ret =
			    auerchain_submit_urb(&cp->controlchain,
						 bp->urbp);
			if (ret) {
				bp->urbp->status = ret;
				auerisdn_bmode_complete(bp->urbp);
			}
			return;
		}
	}
	/* new mode is set */
	bc->mode = mode;

	/* send confirmation to L2 */
	auerisdn_bconf(bc);
}