37 #include <linux/errno.h>
39 #include <linux/kernel.h>
40 #include <linux/module.h>
41 #include <linux/slab.h>
51 #define MOD_DESC "USB Driver for Sasem Remote Controller V1.1"
52 #define MOD_NAME "lirc_sasem"
53 #define MOD_VERSION "0.5"
55 #define VFD_MINOR_BASE 144
56 #define DEVICE_NAME "lcd%d"
58 #define BUF_CHUNK_SIZE 8
61 #define IOCTL_LCD_CONTRAST 1
69 static void usb_rx_callback(
struct urb *
urb);
70 static void usb_tx_callback(
struct urb *
urb);
74 static long vfd_ioctl(
struct file *
file,
unsigned cmd,
unsigned long arg);
77 size_t n_bytes, loff_t *
pos);
80 static int ir_open(
void *
data);
81 static void ir_close(
void *
data);
84 #define SASEM_DATA_BUF_SZ 32
88 struct usb_device *
dev;
123 .unlocked_ioctl = &vfd_ioctl,
124 .release = &vfd_close,
131 { USB_DEVICE(0x11ba, 0x0101) },
137 static struct usb_driver sasem_driver = {
139 .probe = sasem_probe,
140 .disconnect = sasem_disconnect,
141 .id_table = sasem_usb_id_table,
144 static struct usb_class_driver sasem_class = {
168 lirc_buffer_free(context->
driver->rbuf);
177 static void deregister_from_lirc(
struct sasem_context *context)
206 subminor = iminor(inode);
210 ": %s: could not find interface for minor %d\n",
215 context = usb_get_intfdata(interface);
219 "%s: no context found for minor %d\n",
229 "%s: VFD port is already open", __func__);
234 dev_info(&interface->dev,
"VFD port opened\n");
248 static long vfd_ioctl(
struct file *file,
unsigned cmd,
unsigned long arg)
256 ": %s: no context for device\n", __func__);
282 static int vfd_close(
struct inode *inode,
struct file *file)
291 ": %s: no context for device\n", __func__);
298 dev_err(&context->
dev->dev,
"%s: VFD is not open\n", __func__);
309 delete_context(context);
327 pipe = usb_sndintpipe(context->
dev,
331 usb_fill_int_urb(context->
tx_urb, context->
dev, pipe,
333 usb_tx_callback, context, interval);
335 context->
tx_urb->actual_length = 0;
337 init_completion(&context->
tx.finished);
343 dev_err(&context->
dev->dev,
"%s: error submitting urb (%d)\n",
351 retval = context->
tx.status;
354 "%s: packet tx failed (%d)\n",
366 static ssize_t vfd_write(
struct file *file,
const char *
buf,
367 size_t n_bytes, loff_t *
pos)
377 ": %s: no context for device\n", __func__);
385 ": %s: no Sasem device present\n", __func__);
391 dev_err(&context->
dev->dev,
"%s: invalid payload size\n",
398 if (IS_ERR(data_buf)) {
399 retval = PTR_ERR(data_buf);
403 memcpy(context->
tx.data_buf, data_buf, n_bytes);
407 context->
tx.data_buf[i] =
' ';
412 for (i = 0; i < 9; i++) {
431 context->
tx.data_buf + 8, 8);
441 context->
tx.data_buf + 16, 8);
445 context->
tx.data_buf + 24, 8);
451 "%s: send packet failed for packet #%d\n",
461 return (!retval) ? n_bytes :
retval;
467 static void usb_tx_callback(
struct urb *
urb)
477 context->
tx.status = urb->status;
489 static int ir_open(
void *
data)
502 dev_err(&context->
dev->dev,
"%s: IR port is already open\n",
508 usb_fill_int_urb(context->
rx_urb, context->
dev,
509 usb_rcvintpipe(context->
dev,
512 usb_rx_callback, context, context->
rx_endpoint->bInterval);
518 "%s: usb_submit_urb failed for ir_open (%d)\n",
535 static void ir_close(
void *data)
542 ": %s: no context for device\n", __func__);
559 deregister_from_lirc(context);
564 delete_context(context);
580 int len = urb->actual_length;
581 unsigned char *buf = urb->transfer_buffer;
594 for (i = 0; i < 8; ++
i)
606 ms = (tv.tv_sec - context->
presstime.tv_sec) * 1000 +
607 (tv.tv_usec - context->
presstime.tv_usec) / 1000;
609 if (
memcmp(buf,
"\x08\0\0\0\0\0\0\0", 8) == 0) {
621 if ((ms < 250) && (context->
codesaved != 0)) {
638 lirc_buffer_write(context->
driver->rbuf, buf);
645 static void usb_rx_callback(
struct urb *urb)
655 switch (urb->status) {
662 incoming_packet(context, urb);
667 __func__, urb->status);
684 struct usb_host_interface *iface_desc =
NULL;
687 struct urb *rx_urb =
NULL;
688 struct urb *tx_urb =
NULL;
700 dev_info(&interface->dev,
"%s: found Sasem device\n", __func__);
704 iface_desc = interface->cur_altsetting;
705 num_endpoints = iface_desc->desc.bNumEndpoints;
716 for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++
i) {
721 ep = &iface_desc->endpoint [
i].desc;
733 "%s: found IR endpoint\n", __func__);
735 }
else if (!vfd_ep_found &&
743 "%s: found VFD endpoint\n", __func__);
750 "%s: no valid input (IR) endpoint found.\n", __func__);
757 "%s: no valid output (VFD) endpoint found.\n",
767 "%s: kzalloc failed for context\n", __func__);
769 goto alloc_status_switch;
774 "%s: kzalloc failed for lirc_driver\n", __func__);
776 goto alloc_status_switch;
781 "%s: kmalloc failed for lirc_buffer\n", __func__);
783 goto alloc_status_switch;
787 "%s: lirc_buffer_init failed\n", __func__);
789 goto alloc_status_switch;
794 "%s: usb_alloc_urb failed for IR urb\n", __func__);
796 goto alloc_status_switch;
802 "%s: usb_alloc_urb failed for VFD urb",
805 goto alloc_status_switch;
820 driver->
dev = &interface->dev;
826 if (lirc_minor < 0) {
828 "%s: lirc_register_driver failed\n", __func__);
834 __func__, lirc_minor);
837 driver->
minor = lirc_minor;
850 usb_set_intfdata(interface, context);
859 "for VFD\n", __func__);
863 __func__, dev->bus->busnum, dev->devnum);
868 switch (alloc_status) {
876 lirc_buffer_free(rbuf);
896 static void sasem_disconnect(
struct usb_interface *interface)
903 context = usb_get_intfdata(interface);
908 usb_set_intfdata(interface,
NULL);
923 deregister_from_lirc(context);
930 delete_context(context);