Ejemplo n.º 1
0
bool
usb_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags)
{
	TRACE_FUNCALLS("> usb_serial_service(0x%08x, 0x%08x, 0x%08x)\n", ptty, ddr, flags);

	for (int32 i = 0; i < DEVICES_COUNT; i++) {
		if (gSerialDevices[i] && gSerialDevices[i]->Service(ptty, ddr, flags)) {
			TRACE_FUNCRET("< usb_serial_service() returns: true\n");
			return true;
		}
	}

	TRACE_FUNCRET("< usb_serial_service() returns: false\n");
	return false;
}
Ejemplo n.º 2
0
/* init_driver - optional function - called every time the driver is loaded. */
status_t init_driver (void){
  int i;
  status_t status = B_OK;
  load_setting();
  create_log();

  TRACE_FUNCALLS("init_driver\n");
  
  if((status = get_module(B_USB_MODULE_NAME, (module_info **)&usb)) == B_OK){
    if(usb){
      for(i = 0; i < DEVICES_COUNT; i++)
        usb_vision_devices[i] = 0;
        
      usb_vision_names[0] = NULL;  

      (*usb->register_driver)(DRIVER_NAME, supported_devices, SIZEOF(supported_devices), DRIVER_NAME);
      (*usb->install_notify)(DRIVER_NAME, &notify_hooks);

      usb_vision_lock = create_sem(1, DRIVER_NAME"_devices_table_lock");
    }else{
      status = B_ERROR;
      TRACE_ALWAYS("init_driver failed: usb:%08x", usb);
    } 
  }else
    TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, B_USB_MODULE_NAME);
  
  TRACE_FUNCRET("init_driver returns:%08x\n", status);
  return status;
}
Ejemplo n.º 3
0
Archivo: FTDI.cpp Proyecto: DonCN/haiku
status_t
FTDIDevice::SetControlLineState(uint16 state)
{
	TRACE_FUNCALLS("> FTDIDevice::SetControlLineState(0x%08x, 0x%04x)\n", this, state);

	int32 control;
	control = (state & USB_CDC_CONTROL_SIGNAL_STATE_RTS) ? FTDI_SIO_SET_RTS_HIGH
		: FTDI_SIO_SET_RTS_LOW;

	size_t length = 0;
	status_t status = gUSBModule->send_request(Device(),
		USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
		FTDI_SIO_MODEM_CTRL, control,
		FTDI_PIT_DEFAULT, 0, NULL, &length);

	if (status != B_OK)
		TRACE_ALWAYS("= FTDIDevice::SetControlLineState(): control set request failed: 0x%08x\n", status);

	control = (state & USB_CDC_CONTROL_SIGNAL_STATE_DTR) ? FTDI_SIO_SET_DTR_HIGH
		: FTDI_SIO_SET_DTR_LOW;

	status = gUSBModule->send_request(Device(),
		USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
		FTDI_SIO_MODEM_CTRL, control,
		FTDI_PIT_DEFAULT, 0, NULL, &length);

	if (status != B_OK)
		TRACE_ALWAYS("= FTDIDevice::SetControlLineState(): control set request failed: 0x%08x\n", status);

	TRACE_FUNCRET("< FTDIDevice::SetControlLineState() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 4
0
static status_t usb_vision_open (const char *name, uint32 flags, void** cookie)
{
  int i;
  status_t status = ENODEV;
  TRACE_FUNCALLS("usb_vision_open:%s flags:%d cookie:%08x\n", name, flags, cookie);
  
  for(i = 0; i < DEVICES_COUNT; i++)
    TRACE("%08x\n", usb_vision_devices[i]);
  
  *cookie = NULL;
  i = strtol(name + BASENAME_LEN, NULL, 10);
  if(i >= 0 && i < DEVICES_COUNT){
    acquire_sem(usb_vision_lock);
    if(usb_vision_devices[i]){
      if(atomic_add(&usb_vision_devices[i]->open_count, 1) == 0){
        *cookie = usb_vision_devices[i];
        TRACE("cookie in open:%08x\n", *cookie);
        status = B_OK;
      }else{
        atomic_add(&usb_vision_devices[i]->open_count, -1);
        status = B_BUSY;
      }
    }
    release_sem(usb_vision_lock);
  }

  TRACE_FUNCRET("usb_vision_open returns:%08x\n", status);
  return status;
}
Ejemplo n.º 5
0
static status_t add_device(usb_vision_device *uvd, const usb_configuration_info *uci){
  usb_endpoint_info *control_epi = NULL;
  usb_endpoint_info *data_epi = NULL;
  status_t status = ENODEV;
  int i = 0;
  usb_interface_info *uii = uci->interface[0].active;
  TRACE_FUNCALLS("> add_device(%08x, %08x)\n", uvd, uci);

  for(i=0; i < uii->endpoint_count; i++){
    if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_ISOCHRONOUS){
      if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) == USB_EP_ADDR_DIR_IN){
        data_epi = &uii->endpoint[i];
        TRACE("iso_ep:%d\n", i);
      }
    }
    if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_CONTROL){
      control_epi = &uii->endpoint[i];
        TRACE("cont_ep:%d\n", i);
    }
    if(control_epi && data_epi)
      break;
  }
  
  if(control_epi && data_epi){
    status = create_add_device(uvd, uci, control_epi, data_epi);
  }
  
  TRACE_FUNCRET("< create_add_device returns:%08x\n", status);
  return status;
}
Ejemplo n.º 6
0
status_t
pc_serial_device_removed(void *cookie)
{
	TRACE_FUNCALLS("> pc_serial_device_removed(0x%08x)\n", cookie);

	acquire_sem(gDriverLock);

	SerialDevice *device = (SerialDevice *)cookie;
	for (int32 i = 0; i < DEVICES_COUNT; i++) {
		if (gSerialDevices[i] == device) {
			if (device->IsOpen()) {
				// the device will be deleted upon being freed
				device->Removed();
			} else {
				delete device;
				gSerialDevices[i] = NULL;
			}
			break;
		}
	}

	release_sem(gDriverLock);
	TRACE_FUNCRET("< pc_serial_device_removed() returns\n");
	return B_OK;
}
Ejemplo n.º 7
0
/* usb_vision_close - handle close() calls */
static status_t usb_vision_close (void* cookie)
{
  status_t status = B_OK;//ENODEV;
  TRACE_FUNCALLS("usb_vision_close:%08x\n", cookie);

  TRACE_FUNCRET("usb_vision_close returns:%08x\n", status);
  return status;
}
Ejemplo n.º 8
0
bool
usb_serial_service(struct tty *tty, uint32 op, void *buffer, size_t length)
{
	TRACE_FUNCALLS("> usb_serial_service(%p, 0x%08lx, %p, %lu)\n", tty,
		op, buffer, length);

	for (int32 i = 0; i < DEVICES_COUNT; i++) {
		if (gSerialDevices[i]
			&& gSerialDevices[i]->Service(tty, op, buffer, length)) {
			TRACE_FUNCRET("< usb_serial_service() returns: true\n");
			return true;
		}
	}

	TRACE_FUNCRET("< usb_serial_service() returns: false\n");
	return false;
}
Ejemplo n.º 9
0
/* usb_serial_close - handle close() calls */
static status_t
usb_serial_close(void *cookie)
{
	TRACE_FUNCALLS("> usb_serial_close(0x%08x)\n", cookie);
	SerialDevice *device = (SerialDevice *)cookie;
	status_t status = device->Close();
	TRACE_FUNCRET("< usb_serial_close() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 10
0
/* usb_serial_deselect - handle select exit */
static status_t
usb_serial_deselect(void *cookie, uint8 event, selectsync *sync)
{
	TRACE_FUNCALLS("> usb_serial_deselect(0x%08x, 0x%08x, %p)\n",
		cookie, event, sync);
	SerialDevice *device = (SerialDevice *)cookie;
	status_t status = device->DeSelect(event, sync);
	TRACE_FUNCRET("< usb_serial_deselect() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 11
0
/* usb_serial_control - handle ioctl calls */
static status_t
usb_serial_control(void *cookie, uint32 op, void *arg, size_t length)
{
	TRACE_FUNCALLS("> usb_serial_control(0x%08x, 0x%08x, 0x%08x, %d)\n",
		cookie, op, arg, length);
	SerialDevice *device = (SerialDevice *)cookie;
	status_t status = device->Control(op, arg, length);
	TRACE_FUNCRET("< usb_serial_control() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 12
0
/* usb_serial_read - handle read() calls */
static status_t
usb_serial_read(void *cookie, off_t position, void *buffer, size_t *numBytes)
{
	TRACE_FUNCALLS("> usb_serial_read(0x%08x, %Ld, 0x%08x, %d)\n", cookie,
		position, buffer, *numBytes);
	SerialDevice *device = (SerialDevice *)cookie;
	status_t status = device->Read((char *)buffer, numBytes);
	TRACE_FUNCRET("< usb_serial_read() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 13
0
status_t
ProlificDevice::AddDevice(const usb_configuration_info *config)
{
	TRACE_FUNCALLS("> ProlificDevice::AddDevice(%08x, %08x)\n", this, config);

	// check for device type.
	// Linux checks for type 0, 1 and HX, but handles 0 and 1 the same.
	// We'll just check for HX then.
	const usb_device_descriptor *deviceDescriptor = NULL;
	deviceDescriptor = gUSBModule->get_device_descriptor(Device());
	if (deviceDescriptor) {
		fIsHX = (deviceDescriptor->device_class != 0x02
			&& deviceDescriptor->max_packet_size_0 == 0x40);
	}

	int32 pipesSet = 0;
	status_t status = ENODEV;
	if (config->interface_count > 0) {
		usb_interface_info *interface = config->interface[0].active;
		for (size_t i = 0; i < interface->endpoint_count; i++) {
			usb_endpoint_info *endpoint = &interface->endpoint[i];
			if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_INTERRUPT) {
				if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
					SetControlPipe(endpoint->handle);
					pipesSet++;
				}
			}
		}

		/* They say that USB-RSAQ1 has 2 interfaces */
		if (config->interface_count >= 2)
			interface = config->interface[1].active;

		for (size_t i = 0; i < interface->endpoint_count; i++) {
			usb_endpoint_info *endpoint = &interface->endpoint[i];
			if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
				if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN)
					SetReadPipe(endpoint->handle);
				else
					SetWritePipe(endpoint->handle);

				if (++pipesSet >= 3)
					break;
			}
		}

		if (pipesSet >= 3)
			status = B_OK;
	}

	TRACE_FUNCRET("< ProlificDevice::AddDevice() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 14
0
/* usb_vision_free - called after the last device is closed, and after all i/o is complete. */
static status_t usb_vision_free (void* cookie)
{
  status_t status = B_OK;
  TRACE_FUNCALLS("usb_vision_free:%08x\n", cookie);

  if(cookie){
    usb_vision_device *uvd = (usb_vision_device *)cookie;
    atomic_add(&uvd->open_count, -1);
  }

  TRACE_FUNCRET("usb_vision_free returns:%08x\n", status);
  return status;
}
Ejemplo n.º 15
0
static status_t create_add_device(usb_vision_device *uvd, const struct usb_configuration_info *uci,
                                              struct usb_endpoint_info *control_epi, 
                                              struct usb_endpoint_info *data_epi){
//  char name[32]; 
  status_t status = ENODEV;
//  size_t buf_len;
  int i = 0;
 
  TRACE_FUNCALLS("create_add_device(%08x, %08x, %08x, %08x)\n", uvd, uci, control_epi, data_epi);
  
  acquire_sem(usb_vision_lock);

  for(i = 0; i < DEVICES_COUNT; i++){
    if(usb_vision_devices[i] != NULL)
      continue;

    usb_vision_devices[i] = uvd;
   /*   
    usd->active = 1;
    usd->open = 0;
   
    sprintf(name, "usb_vision:%d:done_read", i );
    usd->done_read = create_sem(0, name);
    
    sprintf(name, "usb_vision:%d:done_write", i);
    usd->done_write = create_sem(0, name);

    usd->tty = NULL;
    
    buf_len = usd->read_buffer_size + usd->write_buffer_size + usd->interrupt_buffer_size;

    usd->buffers_area = create_area("usb_serial:buffers_area", (void *)&usd->read_buffer, B_ANY_KERNEL_ADDRESS,
                                        ROUNDUP(buf_len, B_PAGE_SIZE),
                                           B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA);
      
    usd->write_buffer     = usd->read_buffer + usd->read_buffer_size;
    usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size;           
*/
    (*usb->set_configuration)(uvd->dev, uci);

    uvd->control_pipe = control_epi->handle;
    uvd->data_pipe = data_epi->handle;
   
    status = B_OK; 
    break;
  } 
  release_sem(usb_vision_lock);
  
  TRACE_FUNCRET("add_device returns:%08x\n", status);
  return status;
}
Ejemplo n.º 16
0
Archivo: FTDI.cpp Proyecto: DonCN/haiku
status_t
FTDIDevice::ResetDevice()
{
	TRACE_FUNCALLS("> FTDIDevice::ResetDevice(0x%08x)\n", this);

	size_t length = 0;
	status_t status = gUSBModule->send_request(Device(),
		USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
		FTDI_SIO_RESET, FTDI_SIO_RESET_SIO,
		FTDI_PIT_DEFAULT, 0, NULL, &length);

	TRACE_FUNCRET("< FTDIDevice::ResetDevice() returns:%08x\n", status);
	return status;
}
Ejemplo n.º 17
0
static status_t xet_nt_register(bool is_read, usb_vision_device *uvd, xet_nt100x_reg *ri)
{
  status_t status = B_ERROR;
  //uint8 req_type = USB_REQTYPE_VENDOR | (is_read ? USB_REQTYPE_DEVICE_IN : USB_REQTYPE_DEVICE_OUT);
  
  TRACE_FUNCALLS("set_nt_register:%08x, %08x\n", uvd, ri);
  TRACE_FUNCRES(trace_reginfo, ri);
  
  //(*usb->send_request)(uvd->dev, req_type,
  //                     )

  TRACE_FUNCRET("set_nt_register returns:%08x\n", status);
  return status;
}
Ejemplo n.º 18
0
status_t
ProlificDevice::ResetDevice()
{
	TRACE_FUNCALLS("> ProlificDevice::ResetDevice(%08x)\n", this);

	SendRequestList(prolific_reset_common, B_COUNT_OF(prolific_reset_common));
	if (fIsHX)
		SendRequestList(prolific_reset_common_hx, B_COUNT_OF(prolific_reset_common_hx));
	else
		SendRequestList(prolific_reset_common_nhx, B_COUNT_OF(prolific_reset_common_nhx));

	status_t status = B_OK; /* discard */
	TRACE_FUNCRET("< ProlificDevice::ResetDevice() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 19
0
/* usb_vision_control - handle ioctl calls */
static status_t usb_vision_control (void* cookie, uint32 op, void* arg, size_t len)
{
  status_t status = B_BAD_VALUE;
  TRACE_FUNCALLS("usb_vision_control:%08x, %d, %08x, %d\n", cookie, op, arg, len);
  switch(op){
  case NT_IOCTL_READ_REGISTER:
    status = xet_nt_register(true, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg);
    break;
  case NT_IOCTL_WRITE_REGISTER:
    status = xet_nt_register(false, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg);
    break;
  default:
    break;
  }
  TRACE_FUNCRET("usb_vision_control returns:%08x\n", status);
  return status;
}
Ejemplo n.º 20
0
/* usb_serial_open - handle open() calls */
static status_t
usb_serial_open(const char *name, uint32 flags, void **cookie)
{
	TRACE_FUNCALLS("> usb_serial_open(%s, 0x%08x, 0x%08x)\n", name, flags, cookie);
	acquire_sem(gDriverLock);
	status_t status = ENODEV;

	*cookie = NULL;
	int i = strtol(name + strlen(sDeviceBaseName), NULL, 10);
	if (i >= 0 && i < DEVICES_COUNT && gSerialDevices[i]) {
		status = gSerialDevices[i]->Open(flags);
		*cookie = gSerialDevices[i];
	}

	release_sem(gDriverLock);
	TRACE_FUNCRET("< usb_serial_open() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 21
0
Archivo: FTDI.cpp Proyecto: DonCN/haiku
status_t
FTDIDevice::AddDevice(const usb_configuration_info *config)
{
	TRACE_FUNCALLS("> FTDIDevice::AddDevice(%08x, %08x)\n", this, config);
	status_t status = ENODEV;
	if (config->interface_count > 0) {
		int32 pipesSet = 0;
		usb_interface_info *interface = config->interface[0].active;
		for (size_t i = 0; i < interface->endpoint_count; i++) {
			usb_endpoint_info *endpoint = &interface->endpoint[i];
			if (endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
				if (endpoint->descr->endpoint_address & USB_ENDPOINT_ADDR_DIR_IN) {
					SetReadPipe(endpoint->handle);
					if (++pipesSet >= 3)
						break;
				} else {
					if (endpoint->descr->endpoint_address) {
						SetControlPipe(endpoint->handle);
						SetWritePipe(endpoint->handle);
						pipesSet += 2;
						if (pipesSet >= 3)
							break;
					}
				}
			}
		}

		if (pipesSet >= 3) {
			if (ProductID() == 0x8372) // AU100AX
				fHeaderLength = 1;
			else
				fHeaderLength = 0;

			status = B_OK;
		}
	}

	TRACE_FUNCRET("< FTDIDevice::AddDevice() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 22
0
/* init_driver - called every time the driver is loaded. */
status_t
init_driver()
{
	load_settings();
	create_log_file();

	TRACE_FUNCALLS("> init_driver()\n");

	status_t status = get_module(B_TTY_MODULE_NAME, (module_info **)&gTTYModule);
	if (status < B_OK)
		return status;

	status = get_module(B_USB_MODULE_NAME, (module_info **)&gUSBModule);
	if (status < B_OK) {
		put_module(B_TTY_MODULE_NAME);
		return status;
	}

	for (int32 i = 0; i < DEVICES_COUNT; i++)
		gSerialDevices[i] = NULL;

	gDeviceNames[0] = NULL;

	gDriverLock = create_sem(1, DRIVER_NAME"_devices_table_lock");
	if (gDriverLock < B_OK) {
		put_module(B_USB_MODULE_NAME);
		put_module(B_TTY_MODULE_NAME);
		return gDriverLock;
	}

	static usb_notify_hooks notifyHooks = {
		&usb_serial_device_added,
		&usb_serial_device_removed
	};

	gUSBModule->register_driver(DRIVER_NAME, NULL, 0, NULL);
	gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
	TRACE_FUNCRET("< init_driver() returns\n");
	return B_OK;
}
Ejemplo n.º 23
0
/* usb_serial_free - called after last device is closed, and all i/o complete. */
static status_t
usb_serial_free(void *cookie)
{
	TRACE_FUNCALLS("> usb_serial_free(0x%08x)\n", cookie);
	SerialDevice *device = (SerialDevice *)cookie;
	acquire_sem(gDriverLock);
	status_t status = device->Free();
	if (device->IsRemoved()) {
		for (int32 i = 0; i < DEVICES_COUNT; i++) {
			if (gSerialDevices[i] == device) {
				// the device is removed already but as it was open the
				// removed hook has not deleted the object
				delete device;
				gSerialDevices[i] = NULL;
				break;
			}
		}
	}

	release_sem(gDriverLock);
	TRACE_FUNCRET("< usb_serial_free() returns: 0x%08x\n", status);
	return status;
}
Ejemplo n.º 24
0
status_t usb_vision_device_removed(void *cookie){
  int i;
  status_t status = B_OK;
  struct usb_device *ud = (struct usb_device *) cookie;
  TRACE_FUNCALLS("usb_vision_device_removed:%08x\n", cookie);

  acquire_sem(usb_vision_lock);
  
  for(i = 0; i < DEVICES_COUNT; i++ ){
    usb_vision_device *uvd = usb_vision_devices[i];
    if(uvd){
      if(ud == uvd->dev){
        free(uvd);
        usb_vision_devices[i] = 0;
      }
    }
  }
  
  release_sem(usb_vision_lock);

  TRACE_FUNCRET("usb_vision_device_removed returns:%08x\n", status);
  return status;
}
Ejemplo n.º 25
0
status_t usb_vision_device_added(const usb_device *dev, void **cookie){
  int dev_idx;
  status_t status = B_OK;
  const usb_device_descriptor *udd;
  usb_vision_device *uvd = 0;
  TRACE_FUNCALLS("usb_vision_device_added:%08x cookie:%08x\n", dev, cookie);
  
  udd = (*usb->get_device_descriptor)(dev);
  TRACE_ALWAYS("Probing device: %08x/%08x\n", udd->vendor_id, udd->product_id);

  *cookie = 0;
  for(dev_idx = 0; dev_idx < SIZEOF(supported_devices); dev_idx++)
    if(supported_devices[dev_idx].vendor == udd->vendor_id
      && supported_devices[dev_idx].product == udd->product_id){
      const usb_configuration_info *uci;
      int cfg_idx;
      for(cfg_idx = 0; (uci = (*usb->get_nth_configuration)(dev, cfg_idx)) != NULL; cfg_idx++){
        uvd = malloc(sizeof(usb_vision_device));
        if(uvd){
          memset(uvd, 0, sizeof(usb_vision_device));
          uvd->dev = dev;
          if((status = add_device(uvd, uci)) == B_OK){
            *cookie = (void *)dev;
            TRACE_ALWAYS("(%04x/%04x) added \n", supported_devices[dev_idx].vendor,
                                               supported_devices[dev_idx].product);
            break;
          }else
            free(uvd);
        }else
          status = B_NO_MEMORY;
      }
      break;
    }

  TRACE_FUNCRET("usb_vision_device_added returns:%08x\n", status);
  return status;
}
Ejemplo n.º 26
0
/* uninit_driver - called every time the driver is unloaded */
void
uninit_driver()
{
	TRACE_FUNCALLS("> uninit_driver()\n");

	gUSBModule->uninstall_notify(DRIVER_NAME);
	acquire_sem(gDriverLock);

	for (int32 i = 0; i < DEVICES_COUNT; i++) {
		if (gSerialDevices[i]) {
			delete gSerialDevices[i];
			gSerialDevices[i] = NULL;
		}
	}

	for (int32 i = 0; gDeviceNames[i]; i++)
		free(gDeviceNames[i]);

	delete_sem(gDriverLock);
	put_module(B_USB_MODULE_NAME);
	put_module(B_TTY_MODULE_NAME);

	TRACE_FUNCRET("< uninit_driver() returns\n");
}
Ejemplo n.º 27
0
Archivo: FTDI.cpp Proyecto: DonCN/haiku
status_t
FTDIDevice::SetLineCoding(usb_cdc_line_coding *lineCoding)
{
	TRACE_FUNCALLS("> FTDIDevice::SetLineCoding(0x%08x, {%d, 0x%02x, 0x%02x, 0x%02x})\n",
		this, lineCoding->speed, lineCoding->stopbits, lineCoding->parity,
		lineCoding->databits);

	int32 rate = 0;
	if (ProductID() == 0x8372) {
		// AU100AX
		switch (lineCoding->speed) {
			case 300: rate = ftdi_sio_b300; break;
			case 600: rate = ftdi_sio_b600; break;
			case 1200: rate = ftdi_sio_b1200; break;
			case 2400: rate = ftdi_sio_b2400; break;
			case 4800: rate = ftdi_sio_b4800; break;
			case 9600: rate = ftdi_sio_b9600; break;
			case 19200: rate = ftdi_sio_b19200; break;
			case 38400: rate = ftdi_sio_b38400; break;
			case 57600: rate = ftdi_sio_b57600; break;
			case 115200: rate = ftdi_sio_b115200; break;
			default:
				rate = ftdi_sio_b19200;
				TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is "
					"not supported by this hardware. Defaulted to %d\n",
					lineCoding->speed, rate);
			break;
		}
	} else {
		switch (lineCoding->speed) {
			case 300: rate = ftdi_8u232am_b300; break;
			case 600: rate = ftdi_8u232am_b600; break;
			case 1200: rate = ftdi_8u232am_b1200; break;
			case 2400: rate = ftdi_8u232am_b2400; break;
			case 4800: rate = ftdi_8u232am_b4800; break;
			case 9600: rate = ftdi_8u232am_b9600; break;
			case 19200: rate = ftdi_8u232am_b19200; break;
			case 38400: rate = ftdi_8u232am_b38400; break;
			case 57600: rate = ftdi_8u232am_b57600; break;
			case 115200: rate = ftdi_8u232am_b115200; break;
			case 230400: rate = ftdi_8u232am_b230400; break;
			case 460800: rate = ftdi_8u232am_b460800; break;
			case 921600: rate = ftdi_8u232am_b921600; break;
			default:
				rate = ftdi_sio_b19200;
				TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Datarate: %d is "
					"not supported by this hardware. Defaulted to %d\n",
					lineCoding->speed, rate);
				break;
		}
	}

	size_t length = 0;
	status_t status = gUSBModule->send_request(Device(),
		USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
		FTDI_SIO_SET_BAUD_RATE, rate,
		FTDI_PIT_DEFAULT, 0, NULL, &length);
	if (status != B_OK)
		TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): datarate set request failed: 0x%08x\n", status);

	int32 data = 0;
	switch (lineCoding->stopbits) {
		case USB_CDC_LINE_CODING_1_STOPBIT: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break;
		case USB_CDC_LINE_CODING_2_STOPBITS: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break;
		default:
			TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong stopbits param: %d\n",
				lineCoding->stopbits);
			break;
	}

	switch (lineCoding->parity) {
		case USB_CDC_LINE_CODING_NO_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break;
		case USB_CDC_LINE_CODING_EVEN_PARITY: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break;
		case USB_CDC_LINE_CODING_ODD_PARITY:	data |= FTDI_SIO_SET_DATA_PARITY_ODD; break;
		default:
			TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong parity param: %d\n",
				lineCoding->parity);
			break;
	}

	switch (lineCoding->databits) {
		case 8: data |= FTDI_SIO_SET_DATA_BITS(8); break;
		case 7: data |= FTDI_SIO_SET_DATA_BITS(7); break;
		default:
			TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): Wrong databits param: %d\n",
				lineCoding->databits);
			break;
	}

	length = 0;
	status = gUSBModule->send_request(Device(),
		USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
		FTDI_SIO_SET_DATA, data,
		FTDI_PIT_DEFAULT, 0, NULL, &length);
	if (status != B_OK)
		TRACE_ALWAYS("= FTDIDevice::SetLineCoding(): data set request failed: %08x\n", status);

	TRACE_FUNCRET("< FTDIDevice::SetLineCoding() returns: 0x%08x\n", status);
	return status;
}