struct ias_object *irias_new_object( char *name, int id) { struct ias_object *obj; IRDA_DEBUG( 4, "%s()\n", __func__); obj = kzalloc(sizeof(struct ias_object), GFP_ATOMIC); if (obj == NULL) { IRDA_WARNING("%s(), Unable to allocate object!\n", __func__); return NULL; } obj->magic = IAS_OBJECT_MAGIC; obj->name = kstrndup(name, IAS_MAX_CLASSNAME, GFP_ATOMIC); if (!obj->name) { IRDA_WARNING("%s(), Unable to allocate name!\n", __func__); kfree(obj); return NULL; } obj->id = id; obj->attribs = hashbin_new(HB_LOCK); if (obj->attribs == NULL) { IRDA_WARNING("%s(), Unable to allocate attribs!\n", __func__); kfree(obj->name); kfree(obj); return NULL; } return obj; }
/* * Send a command to change the speed of the dongle * Need to be called with spinlock on. */ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) { __u8 *frame; struct urb *urb; int ret; IRDA_DEBUG(2, "%s(), speed=%d, xbofs=%d\n", __FUNCTION__, self->new_speed, self->new_xbofs); /* Grab the speed URB */ urb = self->speed_urb; if (urb->status != 0) { IRDA_WARNING("%s(), URB still in use!\n", __FUNCTION__); return; } /* Allocate the fake frame */ frame = self->speed_buff; /* Set the new speed and xbofs in this fake frame */ irda_usb_build_header(self, frame, 1); /* Submit the 0 length IrDA frame to trigger new speed settings */ usb_fill_bulk_urb(urb, self->usbdev, usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), frame, IRDA_USB_SPEED_MTU, speed_bulk_callback, self); urb->transfer_buffer_length = USB_IRDA_HEADER; urb->transfer_flags = 0; /* Irq disabled -> GFP_ATOMIC */ if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { IRDA_WARNING("%s(), failed Speed URB\n", __FUNCTION__); } }
/* * Function ias_new_object (name, id) * * Create a new IAS object * */ struct ias_object *irias_new_object( char *name, int id) { struct ias_object *obj; IRDA_DEBUG( 4, "%s()\n", __FUNCTION__); obj = kmalloc(sizeof(struct ias_object), GFP_ATOMIC); if (obj == NULL) { IRDA_WARNING("%s(), Unable to allocate object!\n", __FUNCTION__); return NULL; } memset(obj, 0, sizeof( struct ias_object)); obj->magic = IAS_OBJECT_MAGIC; obj->name = strndup(name, IAS_MAX_CLASSNAME); obj->id = id; /* Locking notes : the attrib spinlock has lower precendence * than the objects spinlock. Never grap the objects spinlock * while holding any attrib spinlock (risk of deadlock). Jean II */ obj->attribs = hashbin_new(HB_LOCK); if (obj->attribs == NULL) { IRDA_WARNING("%s(), Unable to allocate attribs!\n", __FUNCTION__); kfree(obj); return NULL; } return obj; }
/* * Function msb_index (word) * * Returns index to most significant bit (MSB) in word * */ static int msb_index (__u16 word) { __u16 msb = 0x8000; int index = 15; /* Current MSB */ /* Check for buggy peers. * Note : there is a small probability that it could be us, but I * would expect driver authors to catch that pretty early and be * able to check precisely what's going on. If a end user sees this, * it's very likely the peer. - Jean II */ if (word == 0) { IRDA_WARNING("%s(), Detected buggy peer, adjust null PV to 0x1!\n", __func__); /* The only safe choice (we don't know the array size) */ word = 0x1; } while (msb) { if (word & msb) break; /* Found it! */ msb >>=1; index--; } return index; }
/* * Function async_unwrap_ce(dev, byte) * * Handle Character Escape character received within a frame * */ static inline void async_unwrap_ce(struct net_device *dev, struct net_device_stats *stats, iobuff_t *rx_buff, __u8 byte) { switch(rx_buff->state) { case OUTSIDE_FRAME: /* Activate carrier sense */ break; case LINK_ESCAPE: IRDA_WARNING("%s: state not defined\n", __func__); break; case BEGIN_FRAME: case INSIDE_FRAME: default: /* Stuffed byte coming */ rx_buff->state = LINK_ESCAPE; break; } }
/* * Function strndup (str, max) * * My own kernel version of strndup! * * Faster, check boundary... Jean II */ static char *strndup(char *str, int max) { char *new_str; int len; /* Check string */ if (str == NULL) return NULL; /* Check length, truncate */ len = strlen(str); if(len > max) len = max; /* Allocate new string */ new_str = kmalloc(len + 1, GFP_ATOMIC); if (new_str == NULL) { IRDA_WARNING("%s: Unable to kmalloc!\n", __FUNCTION__); return NULL; } /* Copy and truncate */ memcpy(new_str, str, len); new_str[len] = '\0'; return new_str; }
int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) { if (!dev || !dev->netdev) { IRDA_WARNING("%s(), not ready yet!\n", __func__); return -1; } if (!dev->irlap) { IRDA_WARNING("%s - too early: %p / %zd!\n", __func__, cp, count); return -1; } if (cp==NULL) { /* error already at lower level receive * just update stats and set media busy */ irda_device_set_media_busy(dev->netdev, TRUE); dev->netdev->stats.rx_dropped++; IRDA_DEBUG(0, "%s; rx-drop: %zd\n", __func__, count); return 0; } /* Read the characters into the buffer */ if (likely(atomic_read(&dev->enable_rx))) { while (count--) /* Unwrap and destuff one byte */ async_unwrap_char(dev->netdev, &dev->netdev->stats, &dev->rx_buff, *cp++); } else { while (count--) { /* rx not enabled: save the raw bytes and never * trigger any netif_rx. The received bytes are flushed * later when we re-enable rx but might be read meanwhile * by the dongle driver. */ dev->rx_buff.data[dev->rx_buff.len++] = *cp++; /* What should we do when the buffer is full? */ if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize)) dev->rx_buff.len = 0; } } return 0; }
/* * Function iriap_init (void) * * Initializes the IrIAP layer, called by the module initialization code * in irmod.c */ int __init iriap_init(void) { struct ias_object *obj; struct iriap_cb *server; __u8 oct_seq[6]; __u16 hints; /* Allocate master array */ iriap = hashbin_new(HB_LOCK); if (!iriap) return -ENOMEM; /* Object repository - defined in irias_object.c */ irias_objects = hashbin_new(HB_LOCK); if (!irias_objects) { IRDA_WARNING("%s: Can't allocate irias_objects hashbin!\n", __func__); hashbin_delete(iriap, NULL); return -ENOMEM; } lockdep_set_class_and_name(&irias_objects->hb_spinlock, &irias_objects_key, "irias_objects"); /* * Register some default services for IrLMP */ hints = irlmp_service_to_hint(S_COMPUTER); service_handle = irlmp_register_service(hints); /* Register the Device object with LM-IAS */ obj = irias_new_object("Device", IAS_DEVICE_ID); irias_add_string_attrib(obj, "DeviceName", "Linux", IAS_KERNEL_ATTR); oct_seq[0] = 0x01; /* Version 1 */ oct_seq[1] = 0x00; /* IAS support bits */ oct_seq[2] = 0x00; /* LM-MUX support bits */ #ifdef CONFIG_IRDA_ULTRA oct_seq[2] |= 0x04; /* Connectionless Data support */ #endif irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3, IAS_KERNEL_ATTR); irias_insert_object(obj); /* * Register server support with IrLMP so we can accept incoming * connections */ server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL); if (!server) { IRDA_DEBUG(0, "%s(), unable to open server\n", __func__); return -1; } iriap_register_lsap(server, LSAP_IAS, IAS_SERVER); return 0; }
int __init irda_device_init( void) { dongles = hashbin_new(HB_NOLOCK); if (dongles == NULL) { IRDA_WARNING("IrDA: Can't allocate dongles hashbin!\n"); return -ENOMEM; } spin_lock_init(&dongles->hb_spinlock); tasks = hashbin_new(HB_LOCK); if (tasks == NULL) { IRDA_WARNING("IrDA: Can't allocate tasks hashbin!\n"); hashbin_delete(dongles, NULL); return -ENOMEM; } /* We no longer initialise the driver ourselves here, we let * the system do it for us... - Jean II */ return 0; }
static int ma600_change_speed(struct sir_dev *dev, unsigned speed) { u8 byte; IRDA_DEBUG(2, "%s(), speed=%d (was %d)\n", __func__, speed, dev->speed); /* dongle already reset, dongle and port at default speed (9600) */ /* Set RTS low for 1 ms */ sirdev_set_dtr_rts(dev, TRUE, FALSE); mdelay(1); /* Write control byte */ byte = get_control_byte(speed); sirdev_raw_write(dev, &byte, sizeof(byte)); /* Wait at least 10ms: fake wait_until_sent - 10 bits at 9600 baud*/ msleep(15); /* old ma600 uses 15ms */ #if 1 /* read-back of the control byte. ma600 is the first dongle driver * which uses this so there might be some unidentified issues. * Disable this in case of problems with readback. */ sirdev_raw_read(dev, &byte, sizeof(byte)); if (byte != get_control_byte(speed)) { IRDA_WARNING("%s(): bad control byte read-back %02x != %02x\n", __func__, (unsigned) byte, (unsigned) get_control_byte(speed)); return -1; } else IRDA_DEBUG(2, "%s() control byte write read OK\n", __func__); #endif /* Set DTR, Set RTS */ sirdev_set_dtr_rts(dev, TRUE, TRUE); /* Wait at least 10ms */ msleep(10); /* dongle is now switched to the new speed */ dev->speed = speed; return 0; }
/* * Function iriap_open (void) * * Opens an instance of the IrIAP layer, and registers with IrLMP */ struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, CONFIRM_CALLBACK callback) { struct iriap_cb *self; IRDA_DEBUG(2, "%s()\n", __func__); self = kzalloc(sizeof(*self), GFP_ATOMIC); if (!self) { IRDA_WARNING("%s: Unable to kmalloc!\n", __func__); return NULL; } /* * Initialize instance */ self->magic = IAS_MAGIC; self->mode = mode; if (mode == IAS_CLIENT) { if (iriap_register_lsap(self, slsap_sel, mode)) { kfree(self); return NULL; } } self->confirm = callback; self->priv = priv; /* iriap_getvaluebyclass_request() will construct packets before * we connect, so this must have a sane value... Jean II */ self->max_header_size = LMP_MAX_HEADER; init_timer(&self->watchdog_timer); hashbin_insert(iriap, (irda_queue_t *) self, (long) self, NULL); /* Initialize state machines */ iriap_next_client_state(self, S_DISCONNECT); iriap_next_call_state(self, S_MAKE_CALL); iriap_next_server_state(self, R_DISCONNECT); iriap_next_r_connect_state(self, R_WAITING); return self; }
static void leftover_dongle(void *arg) { struct dongle_reg *reg = arg; IRDA_WARNING("IrDA: Dongle type %x not unregistered\n", reg->type); }
/* * Function ircomm_tty_change_speed (driver) * * Change speed of the driver. If the remote device is a DCE, then this * should make it change the speed of its serial port */ static void ircomm_tty_change_speed(struct ircomm_tty_cb *self) { unsigned cflag, cval; int baud; IRDA_DEBUG(2, "%s()\n", __func__ ); if (!self->tty || !self->tty->termios || !self->ircomm) return; cflag = self->tty->termios->c_cflag; /* byte size and parity */ switch (cflag & CSIZE) { case CS5: cval = IRCOMM_WSIZE_5; break; case CS6: cval = IRCOMM_WSIZE_6; break; case CS7: cval = IRCOMM_WSIZE_7; break; case CS8: cval = IRCOMM_WSIZE_8; break; default: cval = IRCOMM_WSIZE_5; break; } if (cflag & CSTOPB) cval |= IRCOMM_2_STOP_BIT; if (cflag & PARENB) cval |= IRCOMM_PARITY_ENABLE; if (!(cflag & PARODD)) cval |= IRCOMM_PARITY_EVEN; /* Determine divisor based on baud rate */ baud = tty_get_baud_rate(self->tty); if (!baud) baud = 9600; /* B0 transition handled in rs_set_termios */ self->settings.data_rate = baud; ircomm_param_request(self, IRCOMM_DATA_RATE, FALSE); /* CTS flow control flag and modem status interrupts */ if (cflag & CRTSCTS) { self->flags |= ASYNC_CTS_FLOW; self->settings.flow_control |= IRCOMM_RTS_CTS_IN; /* This got me. Bummer. Jean II */ if (self->service_type == IRCOMM_3_WIRE_RAW) IRDA_WARNING("%s(), enabling RTS/CTS on link that doesn't support it (3-wire-raw)\n", __func__); } else { self->flags &= ~ASYNC_CTS_FLOW; self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN; } if (cflag & CLOCAL) self->flags &= ~ASYNC_CHECK_CD; else self->flags |= ASYNC_CHECK_CD; #if 0 /* * Set up parity check flag */ if (I_INPCK(self->tty)) driver->read_status_mask |= LSR_FE | LSR_PE; if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty)) driver->read_status_mask |= LSR_BI; /* * Characters to ignore */ driver->ignore_status_mask = 0; if (I_IGNPAR(driver->tty)) driver->ignore_status_mask |= LSR_PE | LSR_FE; if (I_IGNBRK(self->tty)) { self->ignore_status_mask |= LSR_BI; /* * If we're ignore parity and break indicators, ignore * overruns too. (For real raw support). */ if (I_IGNPAR(self->tty)) self->ignore_status_mask |= LSR_OE; } #endif self->settings.data_format = cval; ircomm_param_request(self, IRCOMM_DATA_FORMAT, FALSE); ircomm_param_request(self, IRCOMM_FLOW_CONTROL, TRUE); }
static int __init nsc_ircc_open(chipio_t *info) { struct net_device *dev; struct nsc_ircc_cb *self; void *ret; int err, chip_index; IRDA_DEBUG(2, "%s()\n", __func__); for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { if (!dev_self[chip_index]) break; } if (chip_index == ARRAY_SIZE(dev_self)) { IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __func__); return -ENOMEM; } IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base); if ((nsc_ircc_setup(info)) == -1) return -1; IRDA_MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name); dev = alloc_irdadev(sizeof(struct nsc_ircc_cb)); if (dev == NULL) { IRDA_ERROR("%s(), can't allocate memory for " "control block!\n", __func__); return -ENOMEM; } self = netdev_priv(dev); self->netdev = dev; spin_lock_init(&self->lock); dev_self[chip_index] = self; self->index = chip_index; self->io.cfg_base = info->cfg_base; self->io.fir_base = info->fir_base; self->io.irq = info->irq; self->io.fir_ext = CHIP_IO_EXTENT; self->io.dma = info->dma; self->io.fifo_size = 32; ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name); if (!ret) { IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", __func__, self->io.fir_base); err = -ENODEV; goto out1; } irda_init_max_qos_capabilies(&self->qos); self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8); self->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value(&self->qos); self->rx_buff.truesize = 14384; self->tx_buff.truesize = 14384; self->rx_buff.head = dma_alloc_coherent(NULL, self->rx_buff.truesize, &self->rx_buff_dma, GFP_KERNEL); if (self->rx_buff.head == NULL) { err = -ENOMEM; goto out2; } memset(self->rx_buff.head, 0, self->rx_buff.truesize); self->tx_buff.head = dma_alloc_coherent(NULL, self->tx_buff.truesize, &self->tx_buff_dma, GFP_KERNEL); if (self->tx_buff.head == NULL) { err = -ENOMEM; goto out3; } memset(self->tx_buff.head, 0, self->tx_buff.truesize); self->rx_buff.in_frame = FALSE; self->rx_buff.state = OUTSIDE_FRAME; self->tx_buff.data = self->tx_buff.head; self->rx_buff.data = self->rx_buff.head; self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; self->tx_fifo.tail = self->tx_buff.head; dev->netdev_ops = &nsc_ircc_sir_ops; err = register_netdev(dev); if (err) { IRDA_ERROR("%s(), register_netdev() failed!\n", __func__); goto out4; } IRDA_MESSAGE("IrDA: Registered device %s\n", dev->name); if ((dongle_id <= 0) || (dongle_id >= ARRAY_SIZE(dongle_types))) { dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, dongle_types[dongle_id]); } else { IRDA_MESSAGE("%s, Using dongle: %s\n", driver_name, dongle_types[dongle_id]); } self->io.dongle_id = dongle_id; nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME, self->index, NULL, 0); if (IS_ERR(self->pldev)) { err = PTR_ERR(self->pldev); goto out5; } platform_set_drvdata(self->pldev, self); return chip_index; out5: unregister_netdev(dev); out4: dma_free_coherent(NULL, self->tx_buff.truesize, self->tx_buff.head, self->tx_buff_dma); out3: dma_free_coherent(NULL, self->rx_buff.truesize, self->rx_buff.head, self->rx_buff_dma); out2: release_region(self->io.fir_base, self->io.fir_ext); out1: free_netdev(dev); dev_self[chip_index] = NULL; return err; }
int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) { int i; unsigned char c[32]; unsigned char *eofp, *ebufp; int framelen; if (!dev || !dev->netdev) { IRDA_WARNING("%s(), not ready yet!\n", __func__); return -1; } if (!dev->irlap) { IRDA_WARNING("%s - too early: %p / %zd!\n", __func__, cp, count); return -1; } if (cp==NULL) { /* error already at lower level receive * just update stats and set media busy */ irda_device_set_media_busy(dev->netdev, TRUE); dev->netdev->stats.rx_dropped++; IRDA_DEBUG(0, "%s; rx-drop: %zd\n", __func__, count); return 0; } IRDA_DEBUG(3, "%s; get rx: %zd\n", __func__, count); /* Read the characters into the buffer */ if (likely(atomic_read(&dev->enable_rx))) { rx_count_log = count; if (count >0){ for(i= 0; i<32; i ++){ if (i<count){ c[i] = cp[i]; } else { c[i] = 0x00; } } IRDA_DEBUG(3, "RcvData= %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", c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15], c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31] ); } if (count >= 32){ for(i= 0; i<32; i ++){ if ( i < count-32){ c[i] = cp[i+32]; } else { c[i] = 0x00; } } IRDA_DEBUG(3, "RcvData= %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", c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15], c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31] ); } if (count >= 64){ for(i= 0; i< 32; i ++){ if ( i < count-64){ c[i] = cp[i+64]; } else { c[i] = 0x00; } } IRDA_DEBUG(3, "RcvData= %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", c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15], c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31] ); } if (count >=96){ for(i= 0; i<32; i ++){ if ( i < count-96){ c[i] = cp[i+96]; } else { c[i] = 0x00; } } IRDA_DEBUG(3, "RcvData= %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", c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15], c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31] ); } ebufp = localechobuf; if ( ( count < 20) && localechodata > 0 && dev->rx_buff.state == OUTSIDE_FRAME){ if ( count > localechodata){ if (!memcmp(localechobuf, cp + count - localechodata, localechodata)){ IRDA_DEBUG(4, "%s; data mutch trush %d byte!\n", __func__, count); localechodata = 0; cp += count; count = 0; } } else { if (!memcmp(localechobuf + localechodata - count, cp , count)){ IRDA_DEBUG(4, "%s; data mutch trush %d byte!\n", __func__, count); localechodata = 0; cp += count; count = 0; } } } while (count--){ if (localechodata > 0 && dev->rx_buff.state == OUTSIDE_FRAME){ switch(*cp) { case BOF: if ( count > 1 && *(cp + 1) == BOF){ ebufp ++; localechodata--; cp++; continue; break; } else { eofp = (unsigned char *)memchr( (void *)cp, (int)EOF, count); if ( eofp == NULL){ IRDA_DEBUG(4, "%s; not find eof, get start of next frame.\n", __func__); localechodata = 0; break; } else { framelen = eofp - cp +1 ; if ( framelen <= localechodata && !memcmp((void *)cp, ebufp + localechodata - framelen, framelen)){ IRDA_DEBUG(4, "%s; find one frame, skip it\n", __func__); cp += framelen; count -= framelen; localechodata = 0; break; } else { IRDA_DEBUG(4, "%s; frame line =%d, localechodata = %d.\n", __func__, framelen, localechodata); IRDA_DEBUG(4, "%s; find start of next frame.\n", __func__); localechodata = 0; break; } } } case EOF: IRDA_DEBUG(4, "%s; find end of trush data!\n", __func__); ebufp ++; localechodata = 0; cp++; continue; break; default: ebufp ++; localechodata--; cp++; continue; break; } } async_unwrap_char(dev->netdev, &dev->netdev->stats, &dev->rx_buff, *cp++); } } else { while (count--) { /* rx not enabled: save the raw bytes and never * trigger any netif_rx. The received bytes are flushed * later when we re-enable rx but might be read meanwhile * by the dongle driver. */ dev->rx_buff.data[dev->rx_buff.len++] = *cp++; /* What should we do when the buffer is full? */ if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize)) dev->rx_buff.len = 0; } } return 0; }